From ae126cfdd5ca2ed8e32ce5ba1d3d9e6d3c49ce87 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Fri, 10 Aug 2018 11:11:08 +0100 Subject: Duktape: Update to version 2.3.0 release. --- content/handlers/javascript/duktape/duk_config.h | 120 +- content/handlers/javascript/duktape/duktape.c | 6038 ++++++++++++++-------- content/handlers/javascript/duktape/duktape.h | 108 +- 3 files changed, 3974 insertions(+), 2292 deletions(-) (limited to 'content') diff --git a/content/handlers/javascript/duktape/duk_config.h b/content/handlers/javascript/duktape/duk_config.h index 7ee0b13ba..40df0fe8e 100644 --- a/content/handlers/javascript/duktape/duk_config.h +++ b/content/handlers/javascript/duktape/duk_config.h @@ -218,12 +218,6 @@ #define DUK_F_UNIX #endif -/* C++ */ -#undef DUK_F_CPP -#if defined(__cplusplus) -#define DUK_F_CPP -#endif - /* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers), * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32. * https://sites.google.com/site/x32abi/ @@ -301,6 +295,12 @@ #define DUK_F_CLANG #endif +/* C++ */ +#undef DUK_F_CPP +#if defined(__cplusplus) +#define DUK_F_CPP +#endif + /* C99 or above */ #undef DUK_F_C99 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) @@ -836,9 +836,7 @@ #include #endif -#if defined(DUK_F_CPP) -#include /* std::exception */ -#endif +/* is only included if needed, based on DUK_USE_xxx flags. */ /* * Architecture autodetection @@ -850,13 +848,16 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 1 #endif -/* XXX: This is technically not guaranteed because it's possible to configure - * an x86 to require aligned accesses with Alignment Check (AC) flag. + +#define DUK_USE_PACKED_TVAL + +/* FreeBSD, -m32, and clang prior to 5.0 has union aliasing issues which + * break duk_tval copying. Disable packed duk_tval automatically. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 1 +#if defined(DUK_F_FREEBSD) && defined(DUK_F_X86) && \ + defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 5) +#undef DUK_USE_PACKED_TVAL #endif -#define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_X64) /* --- x64 --- */ @@ -864,12 +865,6 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 1 #endif -/* XXX: This is technically not guaranteed because it's possible to configure - * an x86 to require aligned accesses with Alignment Check (AC) flag. - */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 1 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_X32) @@ -878,48 +873,30 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 1 #endif -/* XXX: This is technically not guaranteed because it's possible to configure - * an x86 to require aligned accesses with Alignment Check (AC) flag. - */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 1 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_ARM32) /* --- ARM 32-bit --- */ #define DUK_USE_ARCH_STRING "arm32" /* Byte order varies, so rely on autodetect. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_ARM64) /* --- ARM 64-bit --- */ #define DUK_USE_ARCH_STRING "arm64" /* Byte order varies, so rely on autodetect. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_MIPS32) /* --- MIPS 32-bit --- */ #define DUK_USE_ARCH_STRING "mips32" /* MIPS byte order varies so rely on autodetection. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_MIPS64) /* --- MIPS 64-bit --- */ #define DUK_USE_ARCH_STRING "mips64" /* MIPS byte order varies so rely on autodetection. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_PPC32) @@ -928,9 +905,6 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 3 #endif -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_PPC64) @@ -939,39 +913,24 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 3 #endif -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_SPARC32) /* --- SPARC 32-bit --- */ #define DUK_USE_ARCH_STRING "sparc32" /* SPARC byte order varies so rely on autodetection. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_SPARC64) /* --- SPARC 64-bit --- */ #define DUK_USE_ARCH_STRING "sparc64" /* SPARC byte order varies so rely on autodetection. */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_SUPERH) /* --- SuperH --- */ #define DUK_USE_ARCH_STRING "sh" /* Byte order varies, rely on autodetection. */ -/* Based on 'make checkalign' there are no alignment requirements on - * Linux SH4, but align by 4 is probably a good basic default. - */ -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 4 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_M68K) @@ -980,9 +939,6 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 3 #endif -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #define DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #elif defined(DUK_F_EMSCRIPTEN) @@ -991,9 +947,6 @@ #if !defined(DUK_USE_BYTEORDER) #define DUK_USE_BYTEORDER 1 #endif -#if !defined(DUK_USE_ALIGN_BY) -#define DUK_USE_ALIGN_BY 8 -#endif #undef DUK_USE_PACKED_TVAL #define DUK_F_PACKED_TVAL_PROVIDED #else @@ -2540,10 +2493,13 @@ typedef struct duk_hthread duk_context; * * 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. + * but alignment to 4 or 8 may still be desirable. Note that unaligned + * accesses (and even pointers) relative to natural alignment (regardless + * of target alignment) are technically undefined behavior and thus + * compiler/architecture specific. */ -/* If not provided, use safe default for alignment. */ +/* If not forced, use safe default for alignment. */ #if !defined(DUK_USE_ALIGN_BY) #define DUK_USE_ALIGN_BY 8 #endif @@ -2595,6 +2551,7 @@ typedef struct duk_hthread duk_context; */ #define DUK_CAUSE_SEGFAULT() do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0) #endif + #if !defined(DUK_UNREF) /* Macro for suppressing warnings for potentially unreferenced variables. * The variables can be actually unreferenced or unreferenced in some @@ -2604,9 +2561,24 @@ typedef struct duk_hthread duk_context; */ #define DUK_UNREF(x) do { (void) (x); } while (0) #endif -#if !defined(DUK_NORETURN) + +/* Fillin for DUK_NORETURN; DUK_WO_NORETURN() is used to insert dummy + * dummy statements after noreturn calls to silence harmless compiler + * warnings, e.g.: + * + * DUK_ERROR_TYPE(thr, "aiee"); + * DUK_WO_NORETURN(return 0;); + * + * Statements inside DUK_WO_NORETURN() must NEVER be actually reachable, + * and they're only included to satisfy the compiler. + */ +#if defined(DUK_NORETURN) +#define DUK_WO_NORETURN(stmt) do { } while (0) +#else #define DUK_NORETURN(decl) decl +#define DUK_WO_NORETURN(stmt) do { stmt } while (0) #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 @@ -2614,6 +2586,7 @@ typedef struct duk_hthread duk_context; */ #define DUK_UNREACHABLE() do { } while (0) #endif + #if !defined(DUK_LOSE_CONST) /* Convert any input pointer into a "void *", losing a const qualifier. * This is not fully portable because casting through duk_uintptr_t may @@ -2781,8 +2754,8 @@ typedef struct duk_hthread duk_context; #if defined(DUK_F_PACKED_TVAL_POSSIBLE) #define DUK_USE_PACKED_TVAL #endif - #undef DUK_F_PACKED_TVAL_POSSIBLE + #endif /* DUK_F_PACKED_TVAL_PROVIDED */ /* Object property allocation layout has implications for memory and code * footprint and generated code size/speed. The best layout also depends @@ -2817,6 +2790,7 @@ typedef struct duk_hthread duk_context; * Autogenerated defaults */ +#undef DUK_USE_ALLOW_UNDEFINED_BEHAVIOR #define DUK_USE_ARRAY_BUILTIN #define DUK_USE_ARRAY_FASTPATH #define DUK_USE_ARRAY_PROP_FASTPATH @@ -2825,6 +2799,7 @@ typedef struct duk_hthread duk_context; #define DUK_USE_AUGMENT_ERROR_THROW #define DUK_USE_AVOID_PLATFORM_FUNCPTRS #define DUK_USE_BASE64_FASTPATH +#define DUK_USE_BASE64_SUPPORT #define DUK_USE_BOOLEAN_BUILTIN #define DUK_USE_BUFFEROBJECT_SUPPORT #undef DUK_USE_BUFLEN16 @@ -2902,6 +2877,7 @@ typedef struct duk_hthread duk_context; #undef DUK_USE_HEAPPTR_DEC16 #undef DUK_USE_HEAPPTR_ENC16 #define DUK_USE_HEX_FASTPATH +#define DUK_USE_HEX_SUPPORT #define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT 2 #define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT 9 #define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD 16 @@ -2932,11 +2908,10 @@ typedef struct duk_hthread duk_context; #define DUK_USE_JX #define DUK_USE_LEXER_SLIDING_WINDOW #undef DUK_USE_LIGHTFUNC_BUILTINS +#define DUK_USE_LITCACHE_SIZE 256 #define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256 #define DUK_USE_MATH_BUILTIN #define DUK_USE_NATIVE_CALL_RECLIMIT 1000 -#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER -#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER #define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT #undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY #undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY @@ -3017,6 +2992,15 @@ typedef struct duk_hthread duk_context; /* __OVERRIDE_DEFINES__ */ +/* + * Conditional includes + */ + +#if defined(DUK_F_CPP) && defined(DUK_USE_CPP_EXCEPTIONS) +#include /* std::exception */ +#include /* std::runtime_error */ +#endif + /* * Date provider selection * diff --git a/content/handlers/javascript/duktape/duktape.c b/content/handlers/javascript/duktape/duktape.c index dbebee282..6224aa2c6 100644 --- a/content/handlers/javascript/duktape/duktape.c +++ b/content/handlers/javascript/duktape/duktape.c @@ -1,7 +1,5 @@ -/* Omit from static analysis. */ -#ifndef __clang_analyzer__ /* - * Single source autogenerated distributable for Duktape 2.2.1. + * Single source autogenerated distributable for Duktape 2.3.0. * * Git commit external (external). * Git branch external. @@ -18,7 +16,7 @@ * * (http://opensource.org/licenses/MIT) * -* Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst) +* Copyright (c) 2013-2018 by Duktape authors (see AUTHORS.rst) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -89,6 +87,14 @@ * * Steven Don (https://github.com/shdon) * * Simon Stone (https://github.com/sstone1) * * \J. McC. (https://github.com/jmhmccr) +* * Jakub Nowakowski (https://github.com/jimvonmoon) +* * Tommy Nguyen (https://github.com/tn0502) +* * Fabrice Fontaine (https://github.com/ffontaine) +* * Christopher Hiller (https://github.com/boneskull) +* * Gonzalo Diethelm (https://github.com/gonzus) +* * Michal Kasperek (https://github.com/michalkas) +* * Andrew Janke (https://github.com/apjanke) +* * Steve Fan (https://github.com/stevefan1999) * * Other contributions * =================== @@ -127,6 +133,8 @@ * * https://github.com/chris-y * * Laurent Zubiaur (https://github.com/lzubiaur) * * Neil Kolban (https://github.com/nkolban) +* * Wilhelm Wanecek (https://github.com/wanecek) +* * Andrew Janke (https://github.com/apjanke) * * If you are accidentally missing from this list, send me an e-mail * (``sami.vaarala@iki.fi``) and I'll fix the omission. @@ -665,20 +673,32 @@ struct duk_jmpbuf { #endif /* DUK_JMPBUF_H_INCLUDED */ /* #include duk_exception.h */ /* - * Exception for Duktape internal throws when C++ exceptions are used + * Exceptions for Duktape internal throws when C++ exceptions are used * for long control transfers. - * - * Doesn't inherit from any exception base class to minimize the chance - * that user code would accidentally catch this exception. */ #if !defined(DUK_EXCEPTION_H_INCLUDED) #define DUK_EXCEPTION_H_INCLUDED #if defined(DUK_USE_CPP_EXCEPTIONS) +/* Internal exception used as a setjmp-longjmp replacement. User code should + * NEVER see or catch this exception, so it doesn't inherit from any base + * class which should minimize the chance of user code accidentally catching + * the exception. + */ class duk_internal_exception { /* intentionally empty */ }; + +/* Fatal error, thrown as a specific C++ exception with C++ exceptions + * enabled. It is unsafe to continue; doing so may cause crashes or memory + * leaks. This is intended to be either uncaught, or caught by user code + * aware of the "unsafe to continue" semantics. + */ +class duk_fatal_exception : public virtual std::runtime_error { + public: + duk_fatal_exception(const char *message) : std::runtime_error(message) {} +}; #endif #endif /* DUK_EXCEPTION_H_INCLUDED */ @@ -729,8 +749,9 @@ struct duk_breakpoint; struct duk_activation; struct duk_catcher; -struct duk_strcache; struct duk_ljstate; +struct duk_strcache_entry; +struct duk_litcache_entry; struct duk_strtab_entry; #if defined(DUK_USE_DEBUG) @@ -789,8 +810,9 @@ typedef struct duk_breakpoint duk_breakpoint; typedef struct duk_activation duk_activation; typedef struct duk_catcher duk_catcher; -typedef struct duk_strcache duk_strcache; typedef struct duk_ljstate duk_ljstate; +typedef struct duk_strcache_entry duk_strcache_entry; +typedef struct duk_litcache_entry duk_litcache_entry; typedef struct duk_strtab_entry duk_strtab_entry; #if defined(DUK_USE_DEBUG) @@ -1401,7 +1423,7 @@ typedef struct { #if 0 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv); #endif -DUK_INTERNAL_DECL DUK_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 */ @@ -1443,7 +1465,7 @@ DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(d #define DUK_FASTINT_MAX (DUK_I64_CONSTANT(0x7fffffffffff)) #define DUK_FASTINT_BITS 48 -DUK_INTERNAL_DECL DUK_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x); +DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x); DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x); #endif @@ -1687,278 +1709,290 @@ DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double #define DUK_STRIDX_OWN_KEYS 75 /* 'ownKeys' */ #define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS) #define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS) -#define DUK_STRIDX_SET_PROTOTYPE_OF 76 /* 'setPrototypeOf' */ +#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE 76 /* '\x81Symbol.toPrimitive\xff' */ +#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE) +#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE) +#define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE 77 /* '\x81Symbol.hasInstance\xff' */ +#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE) +#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE) +#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG 78 /* '\x81Symbol.toStringTag\xff' */ +#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG) +#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG) +#define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE 79 /* '\x81Symbol.isConcatSpreadable\xff' */ +#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE) +#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE) +#define DUK_STRIDX_SET_PROTOTYPE_OF 80 /* 'setPrototypeOf' */ #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF) #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF) -#define DUK_STRIDX___PROTO__ 77 /* '__proto__' */ +#define DUK_STRIDX___PROTO__ 81 /* '__proto__' */ #define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__) #define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__) -#define DUK_STRIDX_TO_STRING 78 /* 'toString' */ +#define DUK_STRIDX_TO_STRING 82 /* 'toString' */ #define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING) #define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING) -#define DUK_STRIDX_TO_JSON 79 /* 'toJSON' */ +#define DUK_STRIDX_TO_JSON 83 /* 'toJSON' */ #define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON) #define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON) -#define DUK_STRIDX_TYPE 80 /* 'type' */ +#define DUK_STRIDX_TYPE 84 /* 'type' */ #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_STRIDX_DATA 81 /* 'data' */ +#define DUK_STRIDX_DATA 85 /* 'data' */ #define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA) #define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA) -#define DUK_STRIDX_LENGTH 82 /* 'length' */ +#define DUK_STRIDX_LENGTH 86 /* 'length' */ #define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH) #define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH) -#define DUK_STRIDX_SET 83 /* 'set' */ +#define DUK_STRIDX_SET 87 /* 'set' */ #define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET) #define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET) -#define DUK_STRIDX_STACK 84 /* 'stack' */ +#define DUK_STRIDX_STACK 88 /* 'stack' */ #define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK) #define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK) -#define DUK_STRIDX_PC 85 /* 'pc' */ +#define DUK_STRIDX_PC 89 /* 'pc' */ #define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC) #define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC) -#define DUK_STRIDX_LINE_NUMBER 86 /* 'lineNumber' */ +#define DUK_STRIDX_LINE_NUMBER 90 /* 'lineNumber' */ #define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER) #define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER) -#define DUK_STRIDX_INT_TRACEDATA 87 /* '\x82Tracedata' */ +#define DUK_STRIDX_INT_TRACEDATA 91 /* '\x82Tracedata' */ #define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA) #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA) -#define DUK_STRIDX_NAME 88 /* 'name' */ +#define DUK_STRIDX_NAME 92 /* 'name' */ #define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME) #define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME) -#define DUK_STRIDX_FILE_NAME 89 /* 'fileName' */ +#define DUK_STRIDX_FILE_NAME 93 /* 'fileName' */ #define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME) #define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME) -#define DUK_STRIDX_LC_POINTER 90 /* 'pointer' */ +#define DUK_STRIDX_LC_POINTER 94 /* 'pointer' */ #define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER) #define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER) -#define DUK_STRIDX_INT_TARGET 91 /* '\x82Target' */ +#define DUK_STRIDX_INT_TARGET 95 /* '\x82Target' */ #define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET) #define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET) -#define DUK_STRIDX_INT_NEXT 92 /* '\x82Next' */ +#define DUK_STRIDX_INT_NEXT 96 /* '\x82Next' */ #define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT) #define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT) -#define DUK_STRIDX_INT_BYTECODE 93 /* '\x82Bytecode' */ +#define DUK_STRIDX_INT_BYTECODE 97 /* '\x82Bytecode' */ #define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE) #define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE) -#define DUK_STRIDX_INT_FORMALS 94 /* '\x82Formals' */ +#define DUK_STRIDX_INT_FORMALS 98 /* '\x82Formals' */ #define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS) #define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS) -#define DUK_STRIDX_INT_VARMAP 95 /* '\x82Varmap' */ +#define DUK_STRIDX_INT_VARMAP 99 /* '\x82Varmap' */ #define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP) #define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP) -#define DUK_STRIDX_INT_SOURCE 96 /* '\x82Source' */ +#define DUK_STRIDX_INT_SOURCE 100 /* '\x82Source' */ #define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE) #define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE) -#define DUK_STRIDX_INT_PC2LINE 97 /* '\x82Pc2line' */ +#define DUK_STRIDX_INT_PC2LINE 101 /* '\x82Pc2line' */ #define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE) #define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE) -#define DUK_STRIDX_INT_MAP 98 /* '\x82Map' */ +#define DUK_STRIDX_INT_MAP 102 /* '\x82Map' */ #define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP) #define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP) -#define DUK_STRIDX_INT_VARENV 99 /* '\x82Varenv' */ +#define DUK_STRIDX_INT_VARENV 103 /* '\x82Varenv' */ #define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV) #define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV) -#define DUK_STRIDX_INT_FINALIZER 100 /* '\x82Finalizer' */ +#define DUK_STRIDX_INT_FINALIZER 104 /* '\x82Finalizer' */ #define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER) #define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER) -#define DUK_STRIDX_INT_VALUE 101 /* '\x82Value' */ +#define DUK_STRIDX_INT_VALUE 105 /* '\x82Value' */ #define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE) #define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE) -#define DUK_STRIDX_COMPILE 102 /* 'compile' */ +#define DUK_STRIDX_COMPILE 106 /* 'compile' */ #define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE) #define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE) -#define DUK_STRIDX_INPUT 103 /* 'input' */ +#define DUK_STRIDX_INPUT 107 /* 'input' */ #define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT) #define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT) -#define DUK_STRIDX_ERR_CREATE 104 /* 'errCreate' */ +#define DUK_STRIDX_ERR_CREATE 108 /* 'errCreate' */ #define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE) #define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE) -#define DUK_STRIDX_ERR_THROW 105 /* 'errThrow' */ +#define DUK_STRIDX_ERR_THROW 109 /* 'errThrow' */ #define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW) #define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW) -#define DUK_STRIDX_ENV 106 /* 'env' */ +#define DUK_STRIDX_ENV 110 /* 'env' */ #define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV) #define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV) -#define DUK_STRIDX_HEX 107 /* 'hex' */ +#define DUK_STRIDX_HEX 111 /* 'hex' */ #define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX) #define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX) -#define DUK_STRIDX_BASE64 108 /* 'base64' */ +#define DUK_STRIDX_BASE64 112 /* 'base64' */ #define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64) #define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64) -#define DUK_STRIDX_JX 109 /* 'jx' */ +#define DUK_STRIDX_JX 113 /* 'jx' */ #define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX) #define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX) -#define DUK_STRIDX_JC 110 /* 'jc' */ +#define DUK_STRIDX_JC 114 /* 'jc' */ #define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC) #define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC) -#define DUK_STRIDX_JSON_EXT_UNDEFINED 111 /* '{"_undef":true}' */ +#define DUK_STRIDX_JSON_EXT_UNDEFINED 115 /* '{"_undef":true}' */ #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED) #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED) -#define DUK_STRIDX_JSON_EXT_NAN 112 /* '{"_nan":true}' */ +#define DUK_STRIDX_JSON_EXT_NAN 116 /* '{"_nan":true}' */ #define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN) #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN) -#define DUK_STRIDX_JSON_EXT_POSINF 113 /* '{"_inf":true}' */ +#define DUK_STRIDX_JSON_EXT_POSINF 117 /* '{"_inf":true}' */ #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF) #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF) -#define DUK_STRIDX_JSON_EXT_NEGINF 114 /* '{"_ninf":true}' */ +#define DUK_STRIDX_JSON_EXT_NEGINF 118 /* '{"_ninf":true}' */ #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF) #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF) -#define DUK_STRIDX_JSON_EXT_FUNCTION1 115 /* '{"_func":true}' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION1 119 /* '{"_func":true}' */ #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1) #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1) -#define DUK_STRIDX_JSON_EXT_FUNCTION2 116 /* '{_func:true}' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION2 120 /* '{_func:true}' */ #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2) #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2) -#define DUK_STRIDX_BREAK 117 /* 'break' */ +#define DUK_STRIDX_BREAK 121 /* 'break' */ #define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK) #define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK) -#define DUK_STRIDX_CASE 118 /* 'case' */ +#define DUK_STRIDX_CASE 122 /* 'case' */ #define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE) #define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE) -#define DUK_STRIDX_CATCH 119 /* 'catch' */ +#define DUK_STRIDX_CATCH 123 /* 'catch' */ #define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH) #define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH) -#define DUK_STRIDX_CONTINUE 120 /* 'continue' */ +#define DUK_STRIDX_CONTINUE 124 /* 'continue' */ #define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE) #define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE) -#define DUK_STRIDX_DEBUGGER 121 /* 'debugger' */ +#define DUK_STRIDX_DEBUGGER 125 /* 'debugger' */ #define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER) #define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER) -#define DUK_STRIDX_DEFAULT 122 /* 'default' */ +#define DUK_STRIDX_DEFAULT 126 /* 'default' */ #define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT) #define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT) -#define DUK_STRIDX_DELETE 123 /* 'delete' */ +#define DUK_STRIDX_DELETE 127 /* 'delete' */ #define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE) #define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE) -#define DUK_STRIDX_DO 124 /* 'do' */ +#define DUK_STRIDX_DO 128 /* 'do' */ #define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO) #define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO) -#define DUK_STRIDX_ELSE 125 /* 'else' */ +#define DUK_STRIDX_ELSE 129 /* 'else' */ #define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE) #define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE) -#define DUK_STRIDX_FINALLY 126 /* 'finally' */ +#define DUK_STRIDX_FINALLY 130 /* 'finally' */ #define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY) #define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY) -#define DUK_STRIDX_FOR 127 /* 'for' */ +#define DUK_STRIDX_FOR 131 /* 'for' */ #define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR) #define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR) -#define DUK_STRIDX_LC_FUNCTION 128 /* 'function' */ +#define DUK_STRIDX_LC_FUNCTION 132 /* 'function' */ #define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION) #define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION) -#define DUK_STRIDX_IF 129 /* 'if' */ +#define DUK_STRIDX_IF 133 /* 'if' */ #define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF) #define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF) -#define DUK_STRIDX_IN 130 /* 'in' */ +#define DUK_STRIDX_IN 134 /* 'in' */ #define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN) #define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN) -#define DUK_STRIDX_INSTANCEOF 131 /* 'instanceof' */ +#define DUK_STRIDX_INSTANCEOF 135 /* 'instanceof' */ #define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF) #define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF) -#define DUK_STRIDX_NEW 132 /* 'new' */ +#define DUK_STRIDX_NEW 136 /* 'new' */ #define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW) #define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW) -#define DUK_STRIDX_RETURN 133 /* 'return' */ +#define DUK_STRIDX_RETURN 137 /* 'return' */ #define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN) #define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN) -#define DUK_STRIDX_SWITCH 134 /* 'switch' */ +#define DUK_STRIDX_SWITCH 138 /* 'switch' */ #define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH) #define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH) -#define DUK_STRIDX_THIS 135 /* 'this' */ +#define DUK_STRIDX_THIS 139 /* 'this' */ #define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS) #define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS) -#define DUK_STRIDX_THROW 136 /* 'throw' */ +#define DUK_STRIDX_THROW 140 /* 'throw' */ #define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW) #define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW) -#define DUK_STRIDX_TRY 137 /* 'try' */ +#define DUK_STRIDX_TRY 141 /* 'try' */ #define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY) #define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY) -#define DUK_STRIDX_TYPEOF 138 /* 'typeof' */ +#define DUK_STRIDX_TYPEOF 142 /* 'typeof' */ #define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF) #define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF) -#define DUK_STRIDX_VAR 139 /* 'var' */ +#define DUK_STRIDX_VAR 143 /* 'var' */ #define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR) #define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR) -#define DUK_STRIDX_CONST 140 /* 'const' */ +#define DUK_STRIDX_CONST 144 /* 'const' */ #define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST) #define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST) -#define DUK_STRIDX_VOID 141 /* 'void' */ +#define DUK_STRIDX_VOID 145 /* 'void' */ #define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID) #define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID) -#define DUK_STRIDX_WHILE 142 /* 'while' */ +#define DUK_STRIDX_WHILE 146 /* 'while' */ #define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE) #define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE) -#define DUK_STRIDX_WITH 143 /* 'with' */ +#define DUK_STRIDX_WITH 147 /* 'with' */ #define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH) #define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH) -#define DUK_STRIDX_CLASS 144 /* 'class' */ +#define DUK_STRIDX_CLASS 148 /* 'class' */ #define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS) #define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS) -#define DUK_STRIDX_ENUM 145 /* 'enum' */ +#define DUK_STRIDX_ENUM 149 /* 'enum' */ #define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM) #define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM) -#define DUK_STRIDX_EXPORT 146 /* 'export' */ +#define DUK_STRIDX_EXPORT 150 /* 'export' */ #define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT) #define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT) -#define DUK_STRIDX_EXTENDS 147 /* 'extends' */ +#define DUK_STRIDX_EXTENDS 151 /* 'extends' */ #define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS) #define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS) -#define DUK_STRIDX_IMPORT 148 /* 'import' */ +#define DUK_STRIDX_IMPORT 152 /* 'import' */ #define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT) #define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT) -#define DUK_STRIDX_SUPER 149 /* 'super' */ +#define DUK_STRIDX_SUPER 153 /* 'super' */ #define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER) #define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER) -#define DUK_STRIDX_LC_NULL 150 /* 'null' */ +#define DUK_STRIDX_LC_NULL 154 /* 'null' */ #define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL) #define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL) -#define DUK_STRIDX_TRUE 151 /* 'true' */ +#define DUK_STRIDX_TRUE 155 /* 'true' */ #define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE) #define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE) -#define DUK_STRIDX_FALSE 152 /* 'false' */ +#define DUK_STRIDX_FALSE 156 /* 'false' */ #define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE) #define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE) -#define DUK_STRIDX_IMPLEMENTS 153 /* 'implements' */ +#define DUK_STRIDX_IMPLEMENTS 157 /* 'implements' */ #define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS) #define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS) -#define DUK_STRIDX_INTERFACE 154 /* 'interface' */ +#define DUK_STRIDX_INTERFACE 158 /* 'interface' */ #define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE) #define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE) -#define DUK_STRIDX_LET 155 /* 'let' */ +#define DUK_STRIDX_LET 159 /* 'let' */ #define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET) #define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET) -#define DUK_STRIDX_PACKAGE 156 /* 'package' */ +#define DUK_STRIDX_PACKAGE 160 /* 'package' */ #define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE) #define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE) -#define DUK_STRIDX_PRIVATE 157 /* 'private' */ +#define DUK_STRIDX_PRIVATE 161 /* 'private' */ #define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE) #define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE) -#define DUK_STRIDX_PROTECTED 158 /* 'protected' */ +#define DUK_STRIDX_PROTECTED 162 /* 'protected' */ #define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED) #define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED) -#define DUK_STRIDX_PUBLIC 159 /* 'public' */ +#define DUK_STRIDX_PUBLIC 163 /* 'public' */ #define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC) #define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC) -#define DUK_STRIDX_STATIC 160 /* 'static' */ +#define DUK_STRIDX_STATIC 164 /* 'static' */ #define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC) #define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC) -#define DUK_STRIDX_YIELD 161 /* 'yield' */ +#define DUK_STRIDX_YIELD 165 /* 'yield' */ #define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD) #define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD) -#define DUK_HEAP_NUM_STRINGS 162 -#define DUK_STRIDX_START_RESERVED 117 -#define DUK_STRIDX_START_STRICT_RESERVED 153 -#define DUK_STRIDX_END_RESERVED 162 /* exclusive endpoint */ +#define DUK_HEAP_NUM_STRINGS 166 +#define DUK_STRIDX_START_RESERVED 121 +#define DUK_STRIDX_START_STRICT_RESERVED 157 +#define DUK_STRIDX_END_RESERVED 166 /* exclusive endpoint */ /* To convert a heap stridx to a token number, subtract * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED. */ #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[892]; +DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[967]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_STRDATA_MAX_STRLEN 17 -#define DUK_STRDATA_DATA_LENGTH 892 +#define DUK_STRDATA_MAX_STRLEN 27 +#define DUK_STRDATA_DATA_LENGTH 967 #endif /* DUK_USE_ROM_STRINGS */ #if defined(DUK_USE_ROM_OBJECTS) @@ -1975,6 +2009,8 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx); @@ -1985,8 +2021,6 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx); -DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx); -DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx); @@ -2058,6 +2092,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_cont DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx); @@ -2140,7 +2175,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_conte DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx); #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176]; +DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[177]; #endif /* !DUK_SINGLE_FILE */ #define DUK_BIDX_GLOBAL 0 #define DUK_BIDX_GLOBAL_ENV 1 @@ -2195,22 +2230,22 @@ DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176]; #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 50 #define DUK_NUM_BUILTINS 51 #define DUK_NUM_BIDX_BUILTINS 51 -#define DUK_NUM_ALL_BUILTINS 76 +#define DUK_NUM_ALL_BUILTINS 78 #if defined(DUK_USE_DOUBLE_LE) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 3972 +#define DUK_BUILTINS_DATA_LENGTH 4116 #elif defined(DUK_USE_DOUBLE_BE) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 3972 +#define DUK_BUILTINS_DATA_LENGTH 4116 #elif defined(DUK_USE_DOUBLE_ME) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972]; +DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 3972 +#define DUK_BUILTINS_DATA_LENGTH 4116 #else #error invalid endianness defines #endif @@ -2535,12 +2570,13 @@ struct duk_bufwriter_ctx { (bw_ctx)->p += duk__enc_len; \ } while (0) /* XXX: add temporary duk__p pointer here too; sharing */ +/* XXX: avoid unsafe variants */ #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); \ + duk_memcpy_unsafe((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 { \ @@ -2548,31 +2584,31 @@ struct duk_bufwriter_ctx { 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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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) @@ -2636,13 +2672,14 @@ struct duk_bufwriter_ctx { DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \ } while (0) /* XXX: add temporary duk__p pointer here too; sharing */ +/* XXX: avoid unsafe */ #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); \ + duk_memcpy_unsafe((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 { \ @@ -2651,35 +2688,35 @@ struct duk_bufwriter_ctx { 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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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); \ + duk_memcpy_unsafe((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) @@ -2708,10 +2745,6 @@ DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256]; DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256]; DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256]; #endif -#if defined(DUK_USE_BASE64_FASTPATH) -DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64]; -DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256]; -#endif #endif /* !DUK_SINGLE_FILE */ /* Note: assumes that duk_util_probe_steps size is 32 */ @@ -2755,17 +2788,138 @@ DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_b DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); /* No duk_bw_remove_ensure_slice(), functionality would be identical. */ -DUK_INTERNAL_DECL DUK_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p); -DUK_INTERNAL_DECL DUK_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p); -DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p); -DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val); -DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val); -DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val); +DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p); +DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p); +DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p); +DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val); +DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val); +DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val); #if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */ DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); #endif +/* memcpy(), memmove() etc wrappers. The plain variants like duk_memcpy() + * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the + * operation size is zero. The unsafe variants like duk_memcpy_safe() deal + * with the zero size case explicitly, and allow NULL pointers in that case + * (which is undefined behavior in C99+). For the majority of actual targets + * a NULL pointer with a zero length is fine in practice. These wrappers are + * macros to force inlining; because there are hundreds of call sites, even a + * few extra bytes per call site adds up to ~1kB footprint. + */ +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) +#define duk_memcpy(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + DUK_ASSERT(duk__src != NULL || duk__len == 0U); \ + (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \ + } while (0) +#define duk_memcpy_unsafe(dst,src,len) duk_memcpy((dst), (src), (len)) +#define duk_memmove(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + DUK_ASSERT(duk__src != NULL || duk__len == 0U); \ + (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \ + } while (0) +#define duk_memmove_unsafe(dst,src,len) duk_memmove((dst), (src), (len)) +#define duk_memset(dst,val,len) do { \ + void *duk__dst = (dst); \ + duk_small_int_t duk__val = (val); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \ + } while (0) +#define duk_memset_unsafe(dst,val,len) duk_memset((dst), (val), (len)) +#define duk_memzero(dst,len) do { \ + void *duk__dst = (dst); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \ + } while (0) +#define duk_memzero_unsafe(dst,len) duk_memzero((dst), (len)) +#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */ +#define duk_memcpy(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL); \ + DUK_ASSERT(duk__src != NULL); \ + (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \ + } while (0) +#define duk_memcpy_unsafe(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + DUK_ASSERT(duk__src != NULL || duk__len == 0U); \ + if (DUK_LIKELY(duk__len > 0U)) { \ + DUK_ASSERT(duk__dst != NULL); \ + DUK_ASSERT(duk__src != NULL); \ + (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \ + } \ + } while (0) +#define duk_memmove(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL); \ + DUK_ASSERT(duk__src != NULL); \ + (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \ + } while (0) +#define duk_memmove_unsafe(dst,src,len) do { \ + void *duk__dst = (dst); \ + const void *duk__src = (src); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + DUK_ASSERT(duk__src != NULL || duk__len == 0U); \ + if (DUK_LIKELY(duk__len > 0U)) { \ + DUK_ASSERT(duk__dst != NULL); \ + DUK_ASSERT(duk__src != NULL); \ + (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \ + } \ + } while (0) +#define duk_memset(dst,val,len) do { \ + void *duk__dst = (dst); \ + duk_small_int_t duk__val = (val); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL); \ + (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \ + } while (0) +#define duk_memset_unsafe(dst,val,len) do { \ + void *duk__dst = (dst); \ + duk_small_int_t duk__val = (val); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + if (DUK_LIKELY(duk__len > 0U)) { \ + DUK_ASSERT(duk__dst != NULL); \ + (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \ + } \ + } while (0) +#define duk_memzero(dst,len) do { \ + void *duk__dst = (dst); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL); \ + (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \ + } while (0) +#define duk_memzero_unsafe(dst,len) do { \ + void *duk__dst = (dst); \ + duk_size_t duk__len = (len); \ + DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \ + if (DUK_LIKELY(duk__len > 0U)) { \ + DUK_ASSERT(duk__dst != NULL); \ + (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \ + } \ + } while (0) +#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */ + +DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len); +DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len); + DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival); DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival); DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x); @@ -2780,6 +2934,33 @@ DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x); DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y); DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y); DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x); +DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x); + +DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y); +DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x); +DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x); +DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x); +DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x); +DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x); + +/* + * Miscellaneous + */ + +/* Example: x = 0x10 = 0b00010000 + * x - 1 = 0x0f = 0b00001111 + * x & (x - 1) == 0 + * + * x = 0x07 = 0b00000111 + * x - 1 = 0x06 = 0b00000110 + * x & (x - 1) != 0 + * + * However, incorrectly true for x == 0 so check for that explicitly. + */ +#define DUK_IS_POWER_OF_TWO(x) \ + ((x) != 0U && ((x) & ((x) - 1U)) == 0U) #endif /* DUK_UTIL_H_INCLUDED */ /* #include duk_strings.h */ @@ -2952,7 +3133,7 @@ DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y); #endif /* DUK_ERRMSG_H_INCLUDED */ /* #include duk_js_bytecode.h */ /* - * Ecmascript bytecode + * ECMAScript bytecode */ #if !defined(DUK_JS_BYTECODE_H_INCLUDED) @@ -3824,7 +4005,7 @@ struct duk_lexer_codepoint { duk_int_t line; }; -/* Lexer context. Same context is used for Ecmascript and Regexp parsing. */ +/* 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' */ @@ -3874,13 +4055,13 @@ DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_ #endif /* DUK_LEXER_H_INCLUDED */ /* #include duk_js_compiler.h */ /* - * Ecmascript compiler. + * ECMAScript compiler. */ #if !defined(DUK_JS_COMPILER_H_INCLUDED) #define DUK_JS_COMPILER_H_INCLUDED -/* ecmascript compiler limits */ +/* ECMAScript compiler limits */ #define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */ /* maximum loopcount for peephole optimization */ @@ -4062,6 +4243,7 @@ struct duk_compiler_func { duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */ duk_uint8_t needs_shuffle; /* function needs shuffle registers */ duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */ + duk_uint8_t allow_regexp_in_adv; /* allow RegExp literal on next advance() call */ }; struct duk_compiler_ctx { @@ -4219,9 +4401,6 @@ DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hack /* XXX: macro for shared header fields (avoids some padding issues) */ -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) -#pragma pack(push, 8) -#endif struct duk_heaphdr { duk_uint32_t h_flags; @@ -4267,16 +4446,7 @@ struct duk_heaphdr { #if defined(DUK_USE_HEAPPTR16) duk_uint16_t h_extra16; #endif -} -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR) -__attribute__ ((aligned (8))) -#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR) -__attribute__ ((aligned (8))) -#endif -; -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) -#pragma pack(pop) -#endif +}; struct duk_heaphdr_string { /* 16 bits would be enough for shared heaphdr flags and duk_hstring @@ -5196,7 +5366,7 @@ struct duk_heaphdr_string { #if defined(DUK_USE_REFERENCE_COUNTING) #if defined(DUK_USE_FINALIZER_SUPPORT) DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr); -DUK_INTERNAL_DECL DUK_INLINE void duk_refzero_check_fast(duk_hthread *thr); +DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr); #endif DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr); DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h); @@ -5251,8 +5421,8 @@ DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) /* Current convention is to use duk_size_t for value stack sizes and global indices, * and duk_idx_t for local frame indices. */ -DUK_INTERNAL_DECL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes); -DUK_INTERNAL_DECL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes); +DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes); +DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes); DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug); DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count); @@ -5373,10 +5543,12 @@ DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx); DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr); DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr); +DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr); + #if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */ DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx); #endif -DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv); +DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects); DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, 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_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval); @@ -5514,6 +5686,8 @@ DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */ +DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx); + DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count); DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx); #if 0 @@ -5550,6 +5724,10 @@ DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr); DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags); +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint); +#endif + /* Raw internal valstack access macros: access is unsafe so call site * must have a guarantee that the index is valid. When that is the case, * using these macro results in faster and smaller code than duk_get_tval(). @@ -5588,7 +5766,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); * strings used as internal property names and raw buffers converted to * strings. In such cases the 'clen' field contains an inaccurate value. * - * Ecmascript requires support for 32-bit long strings. However, since each + * ECMAScript requires support for 32-bit long strings. However, since each * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only * support about 1.4G codepoint long strings in extreme cases. This is not * really a practical issue. @@ -5612,12 +5790,15 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); #define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL) #endif -/* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings), +/* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings), * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not, * regexp bytecode is), and "contains non-BMP characters". These are not * needed right now. */ +/* With lowmem builds the high 16 bits of duk_heaphdr are used for other + * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags. + */ #define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */ #define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */ #define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */ @@ -5626,6 +5807,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */ #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */ #define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */ +#define DUK_HSTRING_FLAG_PINNED_LITERAL DUK_HEAPHDR_USER_FLAG(8) /* string is a literal, and pinned */ #define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) #define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) @@ -5635,6 +5817,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) #define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) +#define DUK_HSTRING_HAS_PINNED_LITERAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL) #define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) #define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) @@ -5644,6 +5827,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) #define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) +#define DUK_HSTRING_SET_PINNED_LITERAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL) #define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII) #define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX) @@ -5653,6 +5837,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD) #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS) #define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA) +#define DUK_HSTRING_CLEAR_PINNED_LITERAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL) #if 0 /* Slightly smaller code without explicit flag, but explicit flag * is very useful when 'clen' is dropped. @@ -5745,9 +5930,6 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr); * Misc */ -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) -#pragma pack(push, 8) -#endif struct duk_hstring { /* Smaller heaphdr than for other objects, because strings are held * in string intern table which requires no link pointers. Much of @@ -5792,16 +5974,7 @@ struct duk_hstring { * for strings, but fields above should guarantee alignment-by-4 * (but not alignment-by-8). */ -} -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR) -__attribute__ ((aligned (8))) -#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR) -__attribute__ ((aligned (8))) -#endif -; -#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) -#pragma pack(pop) -#endif +}; /* The external string struct is defined even when the feature is inactive. */ struct duk_hstring_external { @@ -5832,12 +6005,12 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h); /* * Heap object representation. * - * Heap objects are used for Ecmascript objects, arrays, and functions, + * Heap objects are used for ECMAScript objects, arrays, and functions, * but also for internal control like declarative and object environment * records. Compiled functions, native functions, and threads are also * objects but with an extended C struct. * - * Objects provide the required Ecmascript semantics and exotic behaviors + * Objects provide the required ECMAScript semantics and exotic behaviors * especially for property access. * * Properties are stored in three conceptual parts: @@ -6466,7 +6639,7 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h); #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L /* - * Ecmascript [[Class]] + * ECMAScript [[Class]] */ /* range check not necessary because all 4-bit values are mapped */ @@ -6829,9 +7002,9 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr); #endif /* DUK_HOBJECT_H_INCLUDED */ /* #include duk_hcompfunc.h */ /* - * Heap compiled function (Ecmascript function) representation. + * Heap compiled function (ECMAScript function) representation. * - * There is a single data buffer containing the Ecmascript function's + * There is a single data buffer containing the ECMAScript function's * bytecode, constants, and inner functions. */ @@ -7222,7 +7395,8 @@ struct duk_hboundfunc { } while (0) /* Get the current data pointer (caller must ensure buf != NULL) as a - * duk_uint8_t ptr. + * duk_uint8_t ptr. Note that the result may be NULL if the underlying + * buffer has zero size and is not a fixed buffer. */ #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \ (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ @@ -7540,14 +7714,14 @@ struct duk_activation { duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */ /* bottom_byteoff and retval_byteoff are only used for book-keeping - * of Ecmascript-initiated calls, to allow returning to an Ecmascript + * of ECMAScript-initiated calls, to allow returning to an ECMAScript * function properly. */ /* Bottom of valstack for this activation, used to reset * valstack_bottom on return; offset is absolute. There's * no need to track 'top' because native call handling deals - * with that using locals, and for Ecmascript returns 'nregs' + * with that using locals, and for ECMAScript returns 'nregs' * indicates the necessary top. */ duk_size_t bottom_byteoff; @@ -7712,13 +7886,13 @@ DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr); DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr); DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr); -DUK_INTERNAL_DECL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr); +DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr); DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act); DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr); DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr); DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level); -DUK_INTERNAL_DECL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr); +DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr); DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat); DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act); DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act); @@ -7931,7 +8105,7 @@ struct duk_hobjenv { #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x)) #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v)) -#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1)) +#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1)) #if defined(DUK_USE_HEAPPTR16) #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \ @@ -7986,7 +8160,7 @@ struct duk_hobjenv { DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \ DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \ ) : \ - DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \ + DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \ ) #else /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external @@ -7995,7 +8169,7 @@ struct duk_hobjenv { #define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \ DUK_HBUFFER_HAS_DYNAMIC((x)) ? \ DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \ - DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \ + DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \ ) #endif @@ -8069,7 +8243,10 @@ struct duk_hbuffer_fixed { #if (DUK_USE_ALIGN_BY == 4) duk_uint32_t dummy_for_align4; #elif (DUK_USE_ALIGN_BY == 8) - duk_double_t dummy_for_align8; + duk_double_t dummy_for_align8_1; +#if defined(DUK_USE_64BIT_OPS) + duk_uint64_t dummy_for_align8_2; +#endif #elif (DUK_USE_ALIGN_BY == 1) /* no extra padding */ #else @@ -8484,7 +8661,7 @@ struct duk_breakpoint { * Thus, string caches are now at the heap level now. */ -struct duk_strcache { +struct duk_strcache_entry { duk_hstring *h; duk_uint32_t bidx; duk_uint32_t cidx; @@ -8515,6 +8692,15 @@ struct duk_ljstate { DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \ } while (0) +/* + * Literal intern cache + */ + +struct duk_litcache_entry { + const duk_uint8_t *addr; + duk_hstring *h; +}; + /* * Main heap structure */ @@ -8741,7 +8927,15 @@ struct duk_heap { /* String access cache (codepoint offset -> byte offset) for fast string * character looping; 'weak' reference which needs special handling in GC. */ - duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE]; + duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE]; + +#if defined(DUK_USE_LITCACHE_SIZE) + /* Literal intern cache. When enabled, strings interned as literals + * (e.g. duk_push_literal()) will be pinned and cached for the lifetime + * of the heap. + */ + duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE]; +#endif /* Built-in strings. */ #if defined(DUK_USE_ROM_STRINGS) @@ -8773,6 +8967,9 @@ struct duk_heap { duk_int_t stats_strtab_resize_check; duk_int_t stats_strtab_resize_grow; duk_int_t stats_strtab_resize_shrink; + duk_int_t stats_strtab_litcache_hit; + duk_int_t stats_strtab_litcache_miss; + duk_int_t stats_strtab_litcache_pin; duk_int_t stats_object_realloc_props; duk_int_t stats_object_abandon_array; duk_int_t stats_getownpropdesc_count; @@ -8833,6 +9030,9 @@ DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_t DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen); DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len); +#if defined(DUK_USE_LITCACHE_SIZE) +DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen); +#endif DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val); DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val); #if defined(DUK_USE_REFERENCE_COUNTING) @@ -9234,8 +9434,8 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb); * Error codes: defined in duktape.h * * Error codes are used as a shorthand to throw exceptions from inside - * the implementation. The appropriate Ecmascript object is constructed - * based on the code. Ecmascript code throws objects directly. The error + * the implementation. The appropriate ECMAScript object is constructed + * based on the code. ECMAScript code throws objects directly. The error * codes are defined in the public API header because they are also used * by calling code. */ @@ -9637,7 +9837,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb); #if defined(DUK_USE_ASSERTIONS) #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \ - DUK_MEMSET((void *) (ptr), 0x5a, size); \ + duk_memset_unsafe((void *) (ptr), 0x5a, size); \ } while (0) #else #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0) @@ -9915,13 +10115,13 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d * Automatically generated by extract_chars.py, do not edit! */ -extern const duk_uint8_t duk_unicode_ids_noa[1036]; +extern const duk_uint8_t duk_unicode_ids_noa[1063]; #else /* * Automatically generated by extract_chars.py, do not edit! */ -extern const duk_uint8_t duk_unicode_ids_noabmp[625]; +extern const duk_uint8_t duk_unicode_ids_noabmp[626]; #endif #if defined(DUK_USE_SOURCE_NONBMP) @@ -9943,13 +10143,13 @@ extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24]; * Automatically generated by extract_chars.py, do not edit! */ -extern const duk_uint8_t duk_unicode_idp_m_ids_noa[530]; +extern const duk_uint8_t duk_unicode_idp_m_ids_noa[549]; #else /* * Automatically generated by extract_chars.py, do not edit! */ -extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357]; +extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358]; #endif /* @@ -10090,7 +10290,7 @@ typedef struct { #endif /* DUK_JSON_H_INCLUDED */ /* #include duk_js.h */ /* - * Ecmascript execution, support primitives. + * ECMAScript execution, support primitives. */ #if !defined(DUK_JS_H_INCLUDED) @@ -10134,6 +10334,9 @@ DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuf #endif DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags); DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y); +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y); +#endif DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y); DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x); @@ -10202,7 +10405,7 @@ DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr); /* #include duk_numconv.h */ /* * Number-to-string conversion. The semantics of these is very tightly - * bound with the Ecmascript semantics required for call sites. + * bound with the ECMAScript semantics required for call sites. */ #if !defined(DUK_NUMCONV_H_INCLUDED) @@ -10235,9 +10438,13 @@ DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr); /* Maximum exponent value when parsing numbers. This is not strictly * compliant as there should be no upper limit, but as we parse the - * exponent without a bigint, impose some limit. + * exponent without a bigint, impose some limit. The limit should be + * small enough that multiplying it (or limit-1 to be precise) won't + * overflow signed 32-bit integer range. Exponent is only parsed with + * radix 10, but with maximum radix (36) a safe limit is: + * (10000000*36).toString(16) -> '15752a00' */ -#define DUK_S2N_MAX_EXPONENT 1000000000 +#define DUK_S2N_MAX_EXPONENT 10000000L /* Trim white space (= allow leading and trailing whitespace) */ #define DUK_S2N_FLAG_TRIM_WHITE (1U << 0) @@ -10508,7 +10715,7 @@ DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t lin va_start(ap, fmt); - DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE); + duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE); duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap); arg_level = (long) level; @@ -10539,7 +10746,7 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) { va_start(ap, fmt); - DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE); + duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE); duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap); arg_level = (long) duk_debug_level_stash; @@ -10579,7 +10786,7 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) { #if defined(DUK_USE_ROM_STRINGS) #error ROM support not enabled, rerun configure.py with --rom-support #else /* DUK_USE_ROM_STRINGS */ -DUK_INTERNAL const duk_uint8_t duk_strings_data[892] = { +DUK_INTERNAL const duk_uint8_t duk_strings_data[967] = { 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103, 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31, 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132, @@ -10601,36 +10808,40 @@ DUK_INTERNAL const duk_uint8_t duk_strings_data[892] = { 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190, 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12, 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226, -231,146,51,192,204,73,140,224,145,221,102,241,68,196,157,34,79,143,139,166, -233,225,228,227,138,157,173,167,197,211,118,214,210,38,238,74,113,67,76, -105,187,169,147,154,73,225,228,32,193,48,25,100,105,166,113,200,147,44,166, -1,40,79,18,150,134,147,141,163,2,72,171,115,147,136,4,65,130,96,35,64,194, -32,168,89,56,208,48,135,123,144,217,146,39,220,228,193,19,18,101,220,227, -73,121,167,115,129,196,200,39,12,136,220,225,93,22,1,114,62,231,42,8,176, -15,62,231,36,234,68,68,70,231,30,45,37,161,164,38,231,24,7,159,115,149,4, -72,218,171,115,133,67,64,180,100,145,54,231,42,5,208,135,19,152,244,44,133, -67,95,73,164,145,143,5,18,2,100,65,35,30,76,241,117,134,70,212,103,37,204, -16,72,154,218,130,77,196,145,63,127,123,106,141,25,11,189,243,169,198,132, -251,235,119,247,182,154,6,239,124,234,113,161,62,250,221,253,237,164,52, -187,223,58,156,104,79,190,187,127,123,105,168,105,119,190,117,56,208,159, -125,118,254,246,209,104,209,111,124,234,113,161,62,250,205,253,162,209,162, -249,212,227,66,125,244,161,137,0,162,8,18,33,68,9,136,232,19,155,52,54,132, -64,200,26,24,196,137,198,66,130,139,153,134,69,146,100,16,220,66,46,68,57, -80,208,45,120,25,93,20,22,141,20,208,230,137,5,18,26,164,54,83,3,68,71,20, -109,37,141,18,78,145,105,165,100,76,71,36,206,137,22,103,139,172,57,199,6, -158,30,71,20,117,4,74,39,54,83,37,92,129,150,199,66,200,75,34,103,40,150,9, -72,132,109,24,98,93,238,140,206,75,204,141,28,140,134,61,209,153,101,71, -146,36,109,22,178,78,52,33,74,5,200,138,67,30,178,48,141,156,146,134,204, -145,40,4,65,172,147,59,192,37,0,196,59,226,138,130,100,75,226,233,144,83, -32,204,250,5,104,17,165,48,77,2,46,16,69,140, +231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11, +151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92, +112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74, +113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39, +201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78, +214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240, +242,16,96,152,12,178,52,211,56,228,73,150,83,0,148,39,137,75,67,73,198,209, +129,36,85,185,201,196,2,32,193,48,17,160,97,16,84,44,156,104,24,67,189,200, +108,201,19,238,114,96,137,137,50,238,113,164,188,211,185,192,226,100,19, +134,68,110,112,174,139,0,185,31,115,149,4,88,7,159,115,146,117,34,34,35, +115,143,22,146,208,210,19,115,140,3,207,185,202,130,36,109,85,185,194,161, +160,90,50,72,155,115,149,2,232,67,137,204,122,22,66,161,175,164,210,72,199, +130,137,1,50,32,145,143,38,120,186,195,35,106,51,146,230,8,36,77,109,65,38, +226,72,159,191,189,181,70,140,133,222,249,212,227,66,125,245,187,251,219, +77,3,119,190,117,56,208,159,125,110,254,246,210,26,93,239,157,78,52,39,223, +93,191,189,180,212,52,187,223,58,156,104,79,190,187,127,123,104,180,104, +183,190,117,56,208,159,125,102,254,209,104,209,124,234,113,161,62,250,80, +196,128,81,4,9,16,162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33, +65,69,204,195,34,201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70, +138,104,115,68,130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180, +210,178,38,35,146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37, +19,155,41,146,174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46, +247,70,103,37,230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26, +16,165,2,228,69,33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224, +18,128,98,29,241,69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38, +129,23,8,34,198, }; #endif /* DUK_USE_ROM_STRINGS */ #if defined(DUK_USE_ROM_OBJECTS) #error ROM support not enabled, rerun configure.py with --rom-support #else /* DUK_USE_ROM_OBJECTS */ -/* native functions: 176 */ -DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = { +/* native functions: 177 */ +DUK_INTERNAL const duk_c_function duk_bi_native_functions[177] = { NULL, duk_bi_array_constructor, duk_bi_array_constructor_is_array, @@ -10723,6 +10934,7 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = { duk_bi_nodejs_buffer_tojson, duk_bi_nodejs_buffer_tostring, duk_bi_nodejs_buffer_write, + duk_bi_number_check_shared, duk_bi_number_constructor, duk_bi_number_prototype_to_exponential, duk_bi_number_prototype_to_fixed, @@ -10809,556 +11021,577 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = { duk_bi_uint8array_plainof, }; #if defined(DUK_USE_DOUBLE_LE) -DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = { -144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242, -252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33, +DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = { +144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243, +124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33, 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228, 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46, 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240, 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0, -1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, -33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17, -13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192, -0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188, -0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85, -217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225, -146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,0,0, -0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,172,19,120,71,10,25,196,136, -113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,2, -185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,130, -249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,138, -9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,190,15, -38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,53,64, -243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,124, -35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,116, -88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,240,70, -68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,51,132, -9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,105,27, -60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,117,204, -123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,65,112, -152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,39,199, -89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,58,205, -227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,133,18, -2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,39,31,23, -60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,18,84,141, -159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,194,197, -217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,32,130, -166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,151,21,0, -100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,214,111, -31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,10,62, -46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,52, -156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142, -214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173, -165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6, -143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62, -180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129, -54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0, -178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87, -129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104, -201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71, -132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232, -46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35, -193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194, -133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56, -9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14, -134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184, -64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6, -145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67, -77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113, -110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113, -110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2, -127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4, -33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207, -4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,255,255,255,255, -239,127,19,214,33,187,85,2,232,72,0,32,0,0,0,0,0,0,25,136,0,0,0,0,0,0,31, -15,228,122,247,73,19,69,73,180,134,149,13,68,241,0,0,0,0,0,0,3,193,252,143, -90,67,2,104,169,54,144,210,161,168,158,32,0,0,0,0,0,0,120,127,142,73,78,20, -0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68, -13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205, -222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90, -112,164,0,0,0,0,0,0,124,63,226,117,119,128,25,55,112,96,153,57,41,197,13, -53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16, -22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74, -113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104, -97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22, -190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196, -206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208, -76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49, -39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49, -39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112, -163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229, -100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117, -11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68, -157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149, -178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34, -9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62, -49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17, -34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60, -137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248, -199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200, -147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2, -54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56, -7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49, -89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0, -131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217, -231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232, -228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19, -235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1, -64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93, -168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20, -19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,0,0,0,32,93,105,160, -91,60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12, -168,110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136, -115,36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112, -145,139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161, -166,28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148, -145,92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142, -41,100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103, -177,69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138, -99,68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199, -9,49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20, -98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36, -249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242, -136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229, -16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39, -194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68, -89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,104,71,161,196,201,45,167,146,59, -68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,136,71,161,196,201,45,167,146, -59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,168,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,200,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,232,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,8,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,40,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,72,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,52,102,32,76,72,1,246,136,235, -103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91, -171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13, -158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1, -246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161, -37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79, -75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112, -39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186, -129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237, -17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134, -207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134, -207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38, -78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213, -146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39, -104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208, -146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16, -217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101, -162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201, -77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68, -117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104, -162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123, -102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160, -72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32, -52,171,138,69,133,95,130,160,4,234,219,163,161,0,89,86,214,238,197,172,9,0, -31,86,221,40,29,231,63,95,200,69,220,199,225,122,183,27,72,144,63,160,138, -217,81,197,125,207,195,117,110,54,142,129,32,7,114,147,10,189,229,237,159, -130,235,209,0,96,181,17,83,236,132,37,0,63,101,8,207,71,107,74,6,105,219, -251,52,245,7,49,248,94,202,17,158,148,12,211,183,246,105,234,15,99,242,159, -129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160, -192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152, -27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163, -32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72, -188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29, -13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205, -72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80, -81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128, -153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9, -128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203, -164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113, -120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17, -16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94, -100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14, -108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7, -10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227, -138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43, -80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178, -48,141,156,0,0,0,0,0,0,15,3,243,49,135,16,143,67,137,146,91,79,36,118,136, -178,48,141,156,0,0,0,0,0,0,15,3,245,20,5,173,194,227,214,4,55,0,0,21,196,7, -122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180, -69,145,132,108,224,0,0,0,0,0,0,120,31,153,140,72,132,122,28,76,146,218,121, -35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,80,132,122,28,76,146,218, -121,35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,88,132,122,28,76,146, -218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,96,132,122,28,76, -146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,104,132,122, -28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,112, -132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,16,32,16, -113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224, -104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131, -165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3, -154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232, -147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0, +1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, +33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198, +174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32, +248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215, +128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170, +154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130, +249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145, +136,67,134,19,49,0,0,0,0,0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1, +172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240, +149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68, +141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147, +132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42, +96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242, +243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53, +79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47, +147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139, +121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8, +151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147, +180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52, +78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52, +146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194, +70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31, +55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64, +96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36, +103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178, +1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17, +46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200, +217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140, +241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250, +96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81, +46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104, +194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8, +109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71, +240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173, +174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40, +104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32, +194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62, +16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150, +129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179, +224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255, +248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128, +124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34, +131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231, +192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107, +255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19, +245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161, +163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132, +5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13, +34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80, +211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39, +22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221, +197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2, +127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64, +132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46, +190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,255,255,255, +255,222,254,39,172,67,118,170,5,208,144,0,64,0,0,0,0,0,0,51,16,0,0,0,0,0,0, +62,31,200,245,238,146,38,138,147,105,13,42,26,137,226,0,0,0,0,0,0,7,131, +249,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,0,0,0,0,240,255,15,210, +62,72,91,155,0,0,0,0,0,0,2,192,240,135,88,11,237,72,5,38,210,27,50,24,145, +129,255,255,255,255,255,254,126,134,67,172,67,118,164,2,147,105,13,153,12, +72,192,255,255,255,255,255,255,63,195,16,240,70,68,226,27,51,199,138,120, +35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217, +144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196, +142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119, +224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64, +92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62, +210,98,177,252,3,107,173,88,3,146,211,141,32,0,0,0,0,0,3,225,255,19,175, +188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56, +161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7, +18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222, +8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152, +32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198, +57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96, +153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197, +144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150, +22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161, +166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100, +39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18, +32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72, +68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46, +16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117, +11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178, +36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173, +191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35, +43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4, +201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102, +123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162, +215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192, +131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201, +176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86, +127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0, +57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38, +191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128, +80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69, +220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150, +27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24, +186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64, +28,24,61,73,25,33,205,128,0,0,0,0,1,167,166,129,108,242,151,15,39,8,34,26, +87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140, +130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0, +80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145, +139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0, +0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240, +0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42, +130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137, +62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196, +159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79, +133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137, +62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16, +217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108, +244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192, +158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161, +196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,168,71, +161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,200, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51, +232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52, +8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,40, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,72, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52, +104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155, +52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135, +52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44, +50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209, +214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15, +136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40, +161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75, +171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110, +4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129, +89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209, +29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134, +207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136, +235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29, +108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146, +155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54, +122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134, +218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79, +75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162, +137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209, +131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232, +73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68, +117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100, +226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1, +114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45, +162,137,147,111,2,8,4,16,7,8,96,120,72,13,42,226,145,97,87,224,168,1,58, +182,232,232,64,22,85,181,187,177,107,2,64,7,213,183,74,7,121,207,215,242, +17,119,49,248,94,173,198,210,36,15,232,34,182,84,113,95,115,240,221,91,141, +163,160,72,1,220,164,194,175,121,123,103,224,186,244,64,24,45,68,84,251,33, +9,64,15,217,66,51,209,218,210,129,154,118,254,205,61,65,204,126,23,178,132, +103,165,3,52,237,253,154,122,131,216,254,168,48,6,90,130,1,0,39,75,80,72,8, +9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128, +65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10, +8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141, +168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0, +216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209, +234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192, +115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67, +76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78, +192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147, +182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24, +49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49, +39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35, +100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28, +217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32, +225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76, +156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5, +114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180, +69,145,132,108,224,0,0,0,0,0,0,120,31,153,172,56,132,122,28,76,146,218,121, +35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,30,176,33, +184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180, +242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,88,145,8,244,56,153,37, +180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,161,8,244,56,153,37, +180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,177,8,244,56,153,37, +180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,193,8,244,56,153, +37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,209,8,244,56, +153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,225,8,244, +56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,64,32,227,194,0, +97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73, +29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58, +112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73, +240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32, +148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173, +214,3,192, }; #elif defined(DUK_USE_DOUBLE_BE) -DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = { -144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242, -252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33, +DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = { +144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243, +124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33, 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228, 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46, 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240, 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0, -1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, -33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17, -13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192, -0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188, -0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85, -217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225, -146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,1,255, -224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,172,19,120,71,10,25,196, -136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58, -2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58, -130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180, -138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46, -190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207, -53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94, -124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37, -116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20, -240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153, -51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238, -105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129, -117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0, -65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49, -39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62, -58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129, -133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13, -39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95, -18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37, -194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151, -32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72, -151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113, -214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226, -10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84, -52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142, -214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173, -165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6, -143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62, -180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129, -54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0, -178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87, -129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104, -201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71, -132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232, -46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35, -193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194, -133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56, -9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14, -134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184, -64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6, -145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67, -77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113, -110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113, -110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2, -127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4, -33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207, -4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,127,239,255,255,255,255, -255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,0,0,0,57,136,15,255,0,0,0,0,0, -0,4,122,247,73,19,69,73,180,134,149,13,68,241,1,255,192,0,0,0,0,0,0,143,90, -67,2,104,169,54,144,210,161,168,158,32,127,248,0,0,0,0,0,0,14,73,78,20,0,0, -0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68,13, -155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,222, -17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,112, -164,63,252,0,0,0,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13,53,224, -65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,22,78, -12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,113,67, -77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,97,47, -128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,190, -96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,206, -185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,76, -150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,39, -195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,39, -198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,163, -18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,100,40, -15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,11,90, -36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,157,160, -3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,178,166, -74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,9,205, -28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,49,13, -164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,34,79, -135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,137,62, -12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,199,54, -103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,147,225, -104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,54,223, -224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,7,38, -193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,89, -252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,131, -64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,231, -197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,228, -74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,235,1, -64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,64, -174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,168, -167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,19, -177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,32,105,221,32,0,0,0,0,91, -60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168, -110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115, -36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145, -139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166, -28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145, -92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41, -100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177, -69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99, -68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9, -49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20, -98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36, -249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242, -136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229, -16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39, -194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68, -89,24,70,206,1,255,128,0,0,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59, -68,89,24,70,206,1,255,128,0,0,0,0,0,1,153,51,136,71,161,196,201,45,167,146, -59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,153,51,168,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,200,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,232,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,8,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,40,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,72,71,161,196,201,45,167, -146,59,68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235, -103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91, -171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13, -158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1, -246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161, -37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79, -75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112, -39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186, -129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237, -17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134, -207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134, -207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38, -78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213, -146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39, -104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208, -146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16, -217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101, -162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201, -77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68, -117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104, -162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123, -102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160, -72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32, -32,2,223,133,69,138,43,180,132,234,219,163,161,1,0,9,174,198,238,213,84,88, -31,86,221,40,7,252,197,200,95,223,71,61,225,122,183,27,72,144,15,253,197, -81,217,74,224,191,131,117,110,54,142,129,32,31,237,229,189,138,147,114,135, -2,235,209,1,0,36,135,237,81,16,180,96,63,101,8,207,71,107,74,1,255,53,4, -243,51,249,222,104,94,202,17,158,148,3,255,106,9,230,103,243,188,210,159, -129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160, -192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152, -27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163, -32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72, -188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29, -13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205, -72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80, -81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128, -153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9, -128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203, -164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113, -120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17, -16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94, -100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14, -108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7, -10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227, -138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43, -80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178, -48,141,156,3,255,0,0,0,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136, -178,48,141,156,3,255,0,0,0,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7, -122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180, -69,145,132,108,224,31,248,0,0,0,0,0,0,25,140,72,132,122,28,76,146,218,121, -35,180,69,145,132,108,224,32,0,0,0,0,0,0,0,25,140,80,132,122,28,76,146,218, -121,35,180,69,145,132,108,224,32,0,0,0,0,0,0,0,25,140,88,132,122,28,76,146, -218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,96,132,122,28,76, -146,218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,104,132,122, -28,76,146,218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,112, -132,122,28,76,146,218,121,35,180,69,145,132,108,224,32,16,0,0,0,0,0,0,16, -113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224, -104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131, -165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3, -154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232, -147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0, +1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, +33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198, +174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32, +248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215, +128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170, +154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130, +249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145, +136,67,134,19,49,1,255,224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1, +172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240, +149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68, +141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147, +132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42, +96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242, +243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53, +79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47, +147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139, +121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8, +151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147, +180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52, +78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52, +146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194, +70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31, +55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64, +96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36, +103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178, +1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17, +46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200, +217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140, +241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250, +96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81, +46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104, +194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8, +109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71, +240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173, +174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40, +104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32, +194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62, +16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150, +129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179, +224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255, +248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128, +124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34, +131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231, +192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107, +255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19, +245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161, +163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132, +5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13, +34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80, +211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39, +22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221, +197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2, +127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64, +132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46, +190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,128,255,223,255,255,255, +255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,0,0,0,115,16,31,254,0,0, +0,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,3,255,128,0,0,0,0,0, +1,30,180,134,4,209,82,109,33,165,67,81,60,64,255,240,0,0,0,0,0,0,15,210,62, +72,91,155,0,242,192,0,0,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,128, +134,127,255,255,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,72, +192,195,63,255,255,255,255,255,255,16,240,70,68,226,27,51,199,138,120,35, +34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,144, +196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,142, +224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,224, +3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,92, +221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,210, +98,177,252,3,107,173,88,3,146,211,141,33,255,224,0,0,0,0,0,3,19,175,188,0, +100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,161,166, +188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,18,155, +184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,8,77, +133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,32, +35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,57, +179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96, +153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197, +144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150, +22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161, +166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100, +39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18, +32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72, +68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46, +16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117, +11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178, +36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173, +191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35, +43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4, +201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102, +123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162, +215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192, +131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201, +176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86, +127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0, +57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38, +191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128, +80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69, +220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150, +27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24, +186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64, +28,24,61,73,25,33,205,128,129,167,166,0,0,0,0,1,108,242,151,15,39,8,34,26, +87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140, +130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0, +80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145, +139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0, +0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240, +0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42, +130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137, +62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196, +159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79, +133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137, +62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16, +217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108, +244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192, +158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161, +196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,168,71, +161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,200, +71,161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51, +232,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52, +8,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,40, +71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,72, +71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52, +104,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155, +52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,2,1,0,0,0,0,0,0,1,135, +52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44, +50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209, +214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15, +136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40, +161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75, +171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110, +4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129, +89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209, +29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134, +207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136, +235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29, +108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146, +155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54, +122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134, +218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79, +75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162, +137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209, +131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232, +73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68, +117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100, +226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1, +114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45, +162,137,147,111,2,8,4,16,7,8,96,120,72,8,0,183,225,81,98,138,237,33,58,182, +232,232,64,64,2,107,177,187,181,85,22,7,213,183,74,1,255,49,114,23,247,209, +207,120,94,173,198,210,36,3,255,113,84,118,82,184,47,224,221,91,141,163, +160,72,7,251,121,111,98,164,220,161,192,186,244,64,64,9,33,251,84,68,45,24, +15,217,66,51,209,218,210,128,127,205,65,60,204,254,119,154,23,178,132,103, +165,0,255,218,130,121,153,252,239,54,168,48,6,90,130,1,0,39,75,80,72,8,9, +33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,65, +17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,8, +41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,168, +40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,216, +134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,234, +10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,115,3, +117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,76, +130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,192, +56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,182, +140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,49, +39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,39, +199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,100, +128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,217, +114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,225, +64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,156, +113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,114,1, +18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,69,145, +132,108,224,31,248,0,0,0,0,0,0,25,172,56,132,122,28,76,146,218,121,35,180, +69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,176,33,184,0,0, +175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,242,71, +104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,88,145,8,244,56,153,37,180,242, +71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,161,8,244,56,153,37,180,242, +71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,177,8,244,56,153,37,180,242, +71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,193,8,244,56,153,37,180, +242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,209,8,244,56,153,37, +180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,225,8,244,56,153, +37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,32,227,194,0,97,57, +162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,29,153, +1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,112,28, +211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,240,117, +32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,148,25, +174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,214,3, +192, }; #elif defined(DUK_USE_DOUBLE_ME) -DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = { -144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242, -252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33, +DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = { +144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243, +124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33, 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228, 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46, 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240, 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0, -1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, -33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17, -13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192, -0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188, -0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85, -217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225, -146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,3, -225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,172,19,120,71,10,25,196, -136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58, -2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58, -130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180, -138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46, -190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207, -53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94, -124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37, -116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20, -240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153, -51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238, -105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129, -117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0, -65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49, -39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62, -58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129, -133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13, -39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95, -18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37, -194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151, -32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72, -151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113, -214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226, -10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84, -52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142, -214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173, -165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6, -143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62, -180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129, -54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0, -178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87, -129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104, -201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71, -132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232, -46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35, -193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194, -133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56, -9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14, -134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184, -64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6, -145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67, -77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113, -110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113, -110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2, -127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4, -33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207, -4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,239,127,255,255, -255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,32,0,0,25,136,0,0,31,15,224,0, -0,0,4,122,247,73,19,69,73,180,134,149,13,68,241,0,0,3,193,252,0,0,0,0,143, -90,67,2,104,169,54,144,210,161,168,158,32,0,0,120,127,128,0,0,0,14,73,78, -20,0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247, -68,13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205, -222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90, -112,164,0,0,124,63,128,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13, -53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16, -22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74, -113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104, -97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22, -190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196, -206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208, -76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49, -39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49, -39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112, -163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229, -100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117, -11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68, -157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149, -178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34, -9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62, -49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17, -34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60, -137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248, -199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200, -147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2, -54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56, -7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49, -89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0, -131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217, -231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232, -228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19, -235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1, -64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93, -168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20, -19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,32,93,105,160,0,0,0,0, -91,60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12, -168,110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136, -115,36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112, -145,139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161, -166,28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148, -145,92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142, -41,100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103, -177,69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138, -99,68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199, -9,49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20, -98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36, -249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242, -136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229, -16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39, -194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68, -89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59, -68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,136,71,161,196,201,45,167,146, -59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,168,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,200,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,232,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,8,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,40,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,72,71,161,196,201,45,167, -146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235, -103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91, -171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13, -158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1, -246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161, -37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79, -75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112, -39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186, -129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237, -17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134, -207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134, -207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38, -78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213, -146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39, -104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208, -146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16, -217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101, -162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201, -77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68, -117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104, -162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123, -102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160, -72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,5, -95,130,160,52,171,138,69,132,234,219,163,161,2,197,172,9,0,89,86,214,236, -31,86,221,40,8,69,220,199,253,231,63,95,193,122,183,27,72,144,17,197,125, -207,255,160,138,217,67,117,110,54,142,129,32,61,229,237,159,135,114,147,10, -130,235,209,3,236,132,37,0,96,181,17,80,63,101,8,207,71,107,74,4,245,7,49, -254,105,219,251,48,94,202,17,158,148,9,234,15,99,252,211,183,246,98,159, -129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160, -192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152, -27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163, -32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72, -188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29, -13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205, -72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80, -81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128, -153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9, -128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203, -164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113, -120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17, -16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94, -100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14, -108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7, -10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227, -138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43, -80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178, -48,141,156,0,0,15,3,240,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136, -178,48,141,156,0,0,15,3,240,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7, -122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180, -69,145,132,108,224,0,0,120,31,128,0,0,0,25,140,72,132,122,28,76,146,218, -121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,80,132,122,28,76,146, -218,121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,88,132,122,28,76, -146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,96,132,122, -28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,104, -132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25, -140,112,132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,16,32,0,0, -0,0,16,113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33, -18,224,104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80, -70,131,165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73, -7,78,3,154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154, -232,147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0, +1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132, +33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198, +174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32, +248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215, +128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170, +154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130, +249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145, +136,67,134,19,49,0,0,3,225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1, +172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240, +149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68, +141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147, +132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42, +96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242, +243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53, +79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47, +147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139, +121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8, +151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147, +180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52, +78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52, +146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194, +70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31, +55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64, +96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36, +103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178, +1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17, +46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200, +217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140, +241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250, +96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81, +46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104, +194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8, +109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71, +240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173, +174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40, +104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32, +194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62, +16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150, +129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179, +224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255, +248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128, +124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34, +131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231, +192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107, +255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19, +245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161, +163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132, +5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13, +34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80, +211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39, +22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221, +197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2, +127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64, +132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46, +190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,222,255,255, +255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,64,0,0,51,16,0,0,62,31, +192,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,0,0,7,131,248,0,0, +0,1,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,240,255,0,0,0,0,15,210, +62,72,91,155,0,0,2,192,240,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145, +129,255,254,126,135,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12, +72,192,255,255,63,195,255,255,255,255,16,240,70,68,226,27,51,199,138,120, +35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217, +144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196, +142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119, +224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64, +92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62, +210,98,177,252,3,107,173,88,3,146,211,141,32,0,3,225,252,0,0,0,3,19,175, +188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56, +161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7, +18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222, +8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152, +32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198, +57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96, +153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197, +144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150, +22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161, +166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100, +39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18, +32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72, +68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46, +16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117, +11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178, +36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173, +191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35, +43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4, +201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102, +123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162, +215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192, +131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201, +176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86, +127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0, +57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38, +191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128, +80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69, +220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150, +27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24, +186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64, +28,24,61,73,25,33,205,128,1,167,166,128,0,0,0,1,108,242,151,15,39,8,34,26, +87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140, +130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0, +80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145, +139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0, +0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240, +0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42, +130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137, +62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196, +159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79, +133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137, +62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16, +217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108, +244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192, +158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161, +196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,168,71, +161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,200, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51, +232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52, +8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,40, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,72, +71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52, +104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155, +52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135, +52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44, +50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209, +214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15, +136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40, +161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75, +171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110, +4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129, +89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209, +29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134, +207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136, +235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29, +108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146, +155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54, +122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134, +218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79, +75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162, +137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209, +131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232, +73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68, +117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100, +226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1, +114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45, +162,137,147,111,2,8,4,16,7,8,96,120,72,1,87,224,168,13,42,226,145,97,58, +182,232,232,64,177,107,2,64,22,85,181,187,7,213,183,74,2,17,119,49,255,121, +207,215,240,94,173,198,210,36,4,113,95,115,255,232,34,182,80,221,91,141, +163,160,72,15,121,123,103,225,220,164,194,160,186,244,64,251,33,9,64,24,45, +68,84,15,217,66,51,209,218,210,129,61,65,204,127,154,118,254,204,23,178, +132,103,165,2,122,131,216,255,52,237,253,154,168,48,6,90,130,1,0,39,75,80, +72,8,9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20, +128,65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119, +234,10,8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91, +141,168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211, +47,0,216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168, +209,234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40, +192,115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202, +113,67,76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0, +1,78,192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86, +147,182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186, +188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68, +14,49,39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243, +35,100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146, +28,217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164, +32,225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28, +76,156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5, +114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180, +69,145,132,108,224,0,0,120,31,128,0,0,0,25,172,56,132,122,28,76,146,218, +121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,176, +33,184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37, +180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,88,145,8,244,56,153, +37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,161,8,244,56,153, +37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,177,8,244,56,153, +37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,193,8,244,56, +153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,209,8,244, +56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,225,8, +244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,32,227,194, +0,97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73, +29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58, +112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73, +240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32, +148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173, +214,3,192, }; #else #error invalid endianness defines @@ -11482,10 +11715,18 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms DUK_UNREF(udata); DUK_UNREF(msg); + msg = msg ? msg : "NULL"; + #if defined(DUK_USE_FATAL_HANDLER) /* duk_config.h provided a custom default fatal handler. */ - DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg ? msg : "NULL")); + DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg)); DUK_USE_FATAL_HANDLER(udata, msg); +#elif defined(DUK_USE_CPP_EXCEPTIONS) + /* With C++ use a duk_fatal_exception which user code can catch in + * a natural way. + */ + DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg)); + throw duk_fatal_exception(msg); #else /* Default behavior is to abort() on error. There's no printout * which makes this awkward, so it's always recommended to use an @@ -11502,7 +11743,7 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms * - http://duktape.org/api.html#taglist-protected * ==================================================================== */ - DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg ? msg : "NULL")); + DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg)); DUK_ABORT(); #endif @@ -11657,7 +11898,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_u /* * Unicode codepoints above U+FFFF are encoded as surrogate * pairs here. This ensures that all CESU-8 codepoints are - * 16-bit values as expected in Ecmascript. The surrogate + * 16-bit values as expected in ECMAScript. The surrogate * pairs always get a 3-byte encoding (each) in CESU-8. * See: http://en.wikipedia.org/wiki/Surrogate_pair * @@ -11796,8 +12037,7 @@ DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, return cp; } DUK_ERROR_INTERNAL(thr); - DUK_UNREACHABLE(); - return 0; + DUK_WO_NORETURN(return 0;); } /* Compute (extended) utf-8 length without codepoint encoding validation, @@ -11946,7 +12186,7 @@ DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_si duk_bitdecoder_ctx bd_ctx; duk_codepoint_t prev_re; - DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx)); + duk_memzero(&bd_ctx, sizeof(bd_ctx)); bd_ctx.data = (const duk_uint8_t *) unitab; bd_ctx.length = (duk_size_t) unilen; @@ -12498,7 +12738,7 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, } /* 1:1 or special conversions, but not locale/context specific: script generated rules */ - DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx)); + duk_memzero(&bd_ctx, sizeof(bd_ctx)); if (uppercase) { bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc; bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc); @@ -12697,7 +12937,7 @@ DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = { #endif /* DUK_USE_REGEXP_SUPPORT */ /* - * Misc util stuff + * Misc util stuff. */ /* #include duk_internal.h -> already included */ @@ -12859,45 +13099,6 @@ DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = { }; #endif /* DUK_USE_HEX_FASTPATH */ -/* - * Table for base-64 encoding - */ - -#if defined(DUK_USE_BASE64_FASTPATH) -DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = { - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */ - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */ - 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */ - 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */ -}; -#endif /* DUK_USE_BASE64_FASTPATH */ - -/* - * Table for base-64 decoding - */ - -#if defined(DUK_USE_BASE64_FASTPATH) -DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = { - /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */ - -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */ - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */ - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */ -}; -#endif /* DUK_USE_BASE64_FASTPATH */ - /* * Arbitrary byteswap for potentially unaligned values * @@ -12918,191 +13119,8 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { } } #endif - -/* - * Miscellaneous coercion / clamping helpers. - */ - -/* Check whether a duk_double_t is a whole number in the 32-bit range (reject - * negative zero), and if so, return a duk_int32_t. - * For compiler use: don't allow negative zero as it will cause trouble with - * LDINT+LDINTX, positive zero is OK. - */ -DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) { - duk_int32_t t; - - t = (duk_int32_t) x; - if (!((duk_double_t) t == x)) { - return 0; - } - if (t == 0) { - duk_double_union du; - du.d = x; - if (DUK_DBLUNION_HAS_SIGNBIT(&du)) { - return 0; - } - } - *ival = t; - return 1; -} - -/* Check whether a duk_double_t is a whole number in the 32-bit range, and if - * so, return a duk_int32_t. - */ -DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) { - duk_int32_t t; - - t = (duk_int32_t) x; - if (!((duk_double_t) t == x)) { - return 0; - } - *ival = t; - return 1; -} - -/* - * IEEE double checks - */ - -DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) { - duk_double_union du; - du.d = x; - return DUK_DBLUNION_IS_ANYINF(&du); -} - -DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) { - duk_double_union du; - du.d = x; - return DUK_DBLUNION_IS_POSINF(&du); -} - -DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) { - duk_double_union du; - du.d = x; - return DUK_DBLUNION_IS_NEGINF(&du); -} - -DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) { - duk_double_union du; - du.d = x; - /* Assumes we're dealing with a Duktape internal NaN which is - * NaN normalized if duk_tval requires it. - */ - DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); - return DUK_DBLUNION_IS_NAN(&du); -} - -DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) { - duk_double_union du; - du.d = x; - /* Assumes we're dealing with a Duktape internal NaN which is - * NaN normalized if duk_tval requires it. - */ - DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); - return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du); -} - -DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) { - duk_double_union du; - du.d = x; - /* If exponent is 0x7FF the argument is either a NaN or an - * infinity. We don't need to check any other fields. - */ -#if defined(DUK_USE_64BIT_OPS) -#if defined(DUK_USE_DOUBLE_ME) - return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000); -#else - return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000); -#endif -#else - return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL; -#endif -} - -DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) { - duk_double_union du; -#if defined(DUK_USE_64BIT_OPS) - duk_uint64_t t; -#else - duk_uint32_t t; -#endif - du.d = x; -#if defined(DUK_USE_64BIT_OPS) -#if defined(DUK_USE_DOUBLE_ME) - t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000); - if (t == DUK_U64_CONSTANT(0x0000000000000000)) { - t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000); - return t == 0; - } - if (t == DUK_U64_CONSTANT(0x000000007ff00000)) { - return 1; - } -#else - t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000); - if (t == DUK_U64_CONSTANT(0x0000000000000000)) { - t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000); - return t == 0; - } - if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) { - return 1; - } -#endif -#else - t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL; - if (t == 0x00000000UL) { - return DUK_DBLUNION_IS_ANYZERO(&du); - } - if (t == 0x7ff00000UL) { - return 1; - } -#endif - return 0; -} - -DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) { - duk_double_union du; - du.d = x; - return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du); -} - -DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) { - /* XXX: optimize */ - duk_small_uint_t s = duk_double_signbit(x); - x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */ - if (s) { - x = -x; - } - return x; -} - -DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) { - duk_double_union du1; - duk_double_union du2; - du1.d = x; - du2.d = y; - - return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0); -} - -DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) { - /* Doesn't replicate fmin() behavior exactly: for fmin() if one - * argument is a NaN, the other argument should be returned. - * Duktape doesn't rely on this behavior so the replacement can - * be simplified. - */ - return (x < y ? x : y); -} - -DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) { - /* Doesn't replicate fmax() behavior exactly: for fmax() if one - * argument is a NaN, the other argument should be returned. - * Duktape doesn't rely on this behavior so the replacement can - * be simplified. - */ - return (x > y ? x : y); -} /* - * Hobject Ecmascript [[Class]]. + * Hobject ECMAScript [[Class]]. */ /* #include duk_internal.h -> already included */ @@ -13280,9 +13298,10 @@ DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) { DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE); + DUK_WO_NORETURN(return NULL;); } - /* maximum size check is handled by callee */ + /* Maximum size check is handled by callee. */ duk_hbuffer_resize(thr, h, new_size); return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h); @@ -13300,6 +13319,7 @@ DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) { DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE); + DUK_WO_NORETURN(return NULL;); } /* Forget the previous allocation, setting size to 0 and alloc to @@ -13328,6 +13348,7 @@ DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, if (!DUK_HBUFFER_HAS_EXTERNAL(h)) { DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE); + DUK_WO_NORETURN(return;); } DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h)); @@ -13376,7 +13397,7 @@ DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) { len = DUK_RAW_READ_U32_BE(p); buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len); DUK_ASSERT(buf != NULL); - DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len); + duk_memcpy((void *) buf, (const void *) p, (size_t) len); p += len; return p; } @@ -13391,7 +13412,7 @@ DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) { DUK_ASSERT(len <= 0xffffffffUL); /* string limits */ tmp32 = (duk_uint32_t) len; DUK_RAW_WRITE_U32_BE(p, tmp32); - DUK_MEMCPY((void *) p, + duk_memcpy((void *) p, (const void *) DUK_HSTRING_GET_DATA(h), len); p += len; @@ -13410,9 +13431,10 @@ DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, d 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); + /* When len == 0, buffer data pointer may be NULL. */ + duk_memcpy_unsafe((void *) p, + (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), + len); p += len; return p; } @@ -13624,7 +13646,7 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu ins_end = DUK_HCOMPFUNC_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)); + duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins)); p += (size_t) (ins_end - ins); #else while (ins != ins_end) { @@ -13646,7 +13668,7 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu 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, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p), + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p); *p++ = DUK__SER_STRING; p = duk__dump_hstring_raw(p, h_str); } else { @@ -13810,7 +13832,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t 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, + duk_memcpy((void *) q, (const void *) p, sizeof(duk_instr_t) * count_instr); p += sizeof(duk_instr_t) * count_instr; @@ -13875,15 +13897,12 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL); q = fun_data; - if (count_const > 0) { - /* Explicit zero size check to avoid NULL 'tv1'. */ - DUK_MEMCPY((void *) q, (const void *) tv1, 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); - } - tv1 += count_const; + duk_memcpy_unsafe((void *) q, (const void *) tv1, 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); } + tv1 += count_const; DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q); for (n = count_funcs; n > 0; n--) { @@ -14084,6 +14103,7 @@ DUK_EXTERNAL void duk_load_function(duk_hthread *thr) { format_error: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE); + DUK_WO_NORETURN(return;); } #else /* DUK_USE_BYTECODE_DUMP_SUPPORT */ @@ -14091,11 +14111,13 @@ DUK_EXTERNAL void duk_load_function(duk_hthread *thr) { DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) { DUK_ASSERT_API_ENTRY(thr); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_load_function(duk_hthread *thr) { DUK_ASSERT_API_ENTRY(thr); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */ @@ -14162,7 +14184,7 @@ DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, du idx_func = duk_get_top(thr) - nargs - other; if (DUK_UNLIKELY((idx_func | nargs) < 0)) { /* idx_func < 0 || nargs < 0; OR sign bits */ DUK_ERROR_TYPE_INVALID_ARGS(thr); - /* unreachable */ + DUK_WO_NORETURN(return 0;); } DUK_ASSERT(duk_is_valid_index(thr, idx_func)); return idx_func; @@ -14274,6 +14296,7 @@ DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t n obj_idx = duk_require_normalize_index(thr, obj_idx); /* make absolute */ if (DUK_UNLIKELY(nargs < 0)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return;); } duk__call_prop_prep_stack(thr, obj_idx, nargs); @@ -14310,7 +14333,7 @@ DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) { args.nargs = nargs; if (DUK_UNLIKELY(nargs < 0)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); - return DUK_EXEC_ERROR; /* unreachable */ + DUK_WO_NORETURN(return DUK_EXEC_ERROR;); } args.call_flags = 0; @@ -14345,7 +14368,7 @@ DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, args.nargs = nargs; if (DUK_UNLIKELY(nargs < 0)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); - return DUK_EXEC_ERROR; /* unreachable */ + DUK_WO_NORETURN(return DUK_EXEC_ERROR;); } args.call_flags = call_flags; @@ -14386,7 +14409,7 @@ DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_i args.nargs = nargs; if (DUK_UNLIKELY(nargs < 0)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); - return DUK_EXEC_ERROR; /* unreachable */ + DUK_WO_NORETURN(return DUK_EXEC_ERROR;); } args.call_flags = 0; @@ -14422,7 +14445,7 @@ DUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function fu (long) (thr->valstack_top - thr->valstack), (long) nrets)); DUK_ERROR_TYPE_INVALID_ARGS(thr); - return DUK_EXEC_ERROR; /* unreachable */ + DUK_WO_NORETURN(return DUK_EXEC_ERROR;); } rc = duk_handle_safe_call(thr, /* thread */ @@ -14470,7 +14493,7 @@ DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) { if (DUK_UNLIKELY(nargs < 0)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); - return DUK_EXEC_ERROR; /* unreachable */ + DUK_WO_NORETURN(return DUK_EXEC_ERROR;); } rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/); @@ -14497,6 +14520,7 @@ DUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) { if (!duk_is_constructor_call(thr)) { DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY); + DUK_WO_NORETURN(return;); } } @@ -14507,7 +14531,7 @@ DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) { * because all Duktape/C functions are considered strict, * and strict is also the default when nothing is running. * However, Duktape may call this function internally when - * the current activation is an Ecmascript function, so + * the current activation is an ECMAScript function, so * this cannot be replaced by a 'return 1' without fixing * the internal call sites. */ @@ -14574,7 +14598,7 @@ DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) { /* fall through */ type_error: DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) { @@ -14606,7 +14630,7 @@ DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) { h = DUK_TVAL_GET_OBJECT(tv); DUK_ASSERT(h != NULL); if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) { - duk_push_tval(thr, &((duk_hboundfunc *) h)->target); + duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target); duk_replace(thr, -2); #if 0 DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target); @@ -14636,6 +14660,10 @@ DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) { /* #include duk_internal.h -> already included */ +/* + * Misc helpers + */ + /* Shared handling for encode/decode argument. Fast path handling for * buffer and string values because they're the most common. In particular, * avoid creating a temporary string or buffer when possible. @@ -14657,250 +14685,425 @@ DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx return (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len); } +/* + * Base64 + */ + +#if defined(DUK_USE_BASE64_SUPPORT) +/* Bytes emitted for number of padding characters in range [0,4]. */ +DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = { + 3, /* #### -> 24 bits, emit 3 bytes */ + 2, /* ###= -> 18 bits, emit 2 bytes */ + 1, /* ##== -> 12 bits, emit 1 byte */ + -1, /* #=== -> 6 bits, error */ + 0, /* ==== -> 0 bits, emit 0 bytes */ +}; + #if defined(DUK_USE_BASE64_FASTPATH) -DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) { +DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = { + 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U, /* A...P */ + 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, /* Q...f */ + 0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, /* g...v */ + 0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU /* w.../ */ +}; +#endif /* DUK_USE_BASE64_FASTPATH */ + +#if defined(DUK_USE_BASE64_FASTPATH) +/* Decode table for one byte of input: + * -1 = allowed whitespace + * -2 = padding + * -3 = error + * 0...63 decoded bytes + */ +DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = { + -3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3, /* 0x00...0x0f */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x10...0x1f */ + -1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63, /* 0x20...0x2f */ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3, /* 0x30...0x3f */ + -3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3, /* 0x50...0x5f */ + -3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3, /* 0x70...0x7f */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x80...0x8f */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x90...0x9f */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xa0...0xaf */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xb0...0xbf */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xc0...0xcf */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xd0...0xdf */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xe0...0xef */ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3 /* 0xf0...0xff */ +}; +#endif /* DUK_USE_BASE64_FASTPATH */ + +#if defined(DUK_USE_BASE64_FASTPATH) +DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) { duk_uint_t t; - duk_size_t n_full, n_full3, n_final; - const duk_uint8_t *src_end_fast; - - n_full = srclen / 3; /* full 3-byte -> 4-char conversions */ - n_full3 = n_full * 3; - n_final = srclen - n_full3; - DUK_ASSERT_DISABLE(n_final >= 0); - DUK_ASSERT(n_final <= 2); - - src_end_fast = src + n_full3; - while (DUK_UNLIKELY(src != src_end_fast)) { - t = (duk_uint_t) (*src++); - t = (t << 8) + (duk_uint_t) (*src++); - t = (t << 8) + (duk_uint_t) (*src++); - - *dst++ = duk_base64_enctab[t >> 18]; - *dst++ = duk_base64_enctab[(t >> 12) & 0x3f]; - *dst++ = duk_base64_enctab[(t >> 6) & 0x3f]; - *dst++ = duk_base64_enctab[t & 0x3f]; - -#if 0 /* Tested: not faster on x64 */ - /* aaaaaabb bbbbcccc ccdddddd */ - dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f]; - dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)]; - dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)]; - dst[3] = duk_base64_enctab[src[2] & 0x3f]; - src += 3; dst += 4; -#endif - } - - switch (n_final) { - /* case 0: nop */ - case 1: { - /* XX== */ - t = (duk_uint_t) (*src++); - *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */ - *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */ - *dst++ = DUK_ASC_EQUALS; - *dst++ = DUK_ASC_EQUALS; - break; - } - case 2: { - /* XXX= */ - t = (duk_uint_t) (*src++); - t = (t << 8) + (duk_uint_t) (*src++); - *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */ - *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */ - *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */ - *dst++ = DUK_ASC_EQUALS; - break; - } + + t = (duk_uint_t) src[0]; + t = (t << 8) + (duk_uint_t) src[1]; + t = (t << 8) + (duk_uint_t) src[2]; + + dst[0] = duk__base64_enctab_fast[t >> 18]; + dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU]; + dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU]; + dst[3] = duk__base64_enctab_fast[t & 0x3fU]; + +#if 0 + /* Tested: not faster on x64, most likely due to aliasing between + * output and input index computation. + */ + /* aaaaaabb bbbbcccc ccdddddd */ + dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU]; + dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)]; + dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)]; + dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU]; +#endif +} + +DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) { + duk_uint_t t; + + t = (duk_uint_t) src[0]; + t = (t << 8) + (duk_uint_t) src[1]; + dst[0] = duk__base64_enctab_fast[t >> 10]; /* XXXXXX-- -------- */ + dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU]; /* ------XX XXXX---- */ + dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU]; /* -------- ----XXXX */ + dst[3] = DUK_ASC_EQUALS; +} + +DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) { + duk_uint_t t; + + t = (duk_uint_t) src[0]; + dst[0] = duk__base64_enctab_fast[t >> 2]; /* XXXXXX-- */ + dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU]; /* ------XX */ + dst[2] = DUK_ASC_EQUALS; + dst[3] = DUK_ASC_EQUALS; +} + +DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) { + duk_size_t n; + const duk_uint8_t *p; + duk_uint8_t *q; + + n = srclen; + p = src; + q = dst; + + if (n >= 16U) { + /* Fast path, unrolled by 4, allows interleaving. Process + * 12-byte input chunks which encode to 16-char output chunks. + * Only enter when at least one block is emitted (avoids div+mul + * for short inputs too). + */ + const duk_uint8_t *p_end_fast; + + p_end_fast = p + ((n / 12U) * 12U); + DUK_ASSERT(p_end_fast >= p + 12); + do { + duk__base64_encode_fast_3(p, q); + duk__base64_encode_fast_3(p + 3, q + 4); + duk__base64_encode_fast_3(p + 6, q + 8); + duk__base64_encode_fast_3(p + 9, q + 12); + p += 12; + q += 16; + } while (DUK_LIKELY(p != p_end_fast)); + + DUK_ASSERT(src + srclen >= p); + n = (duk_size_t) (src + srclen - p); + DUK_ASSERT(n < 12U); + } + + /* Remainder. */ + while (n >= 3U) { + duk__base64_encode_fast_3(p, q); + p += 3; + q += 4; + n -= 3U; + } + DUK_ASSERT(n == 0U || n == 1U || n == 2U); + if (n == 1U) { + duk__base64_encode_fast_1(p, q); +#if 0 /* Unnecessary. */ + p += 1; + q += 4; + n -= 1U; +#endif + } else if (n == 2U) { + duk__base64_encode_fast_2(p, q); +#if 0 /* Unnecessary. */ + p += 2; + q += 4; + n -= 2U; +#endif + } else { + DUK_ASSERT(n == 0U); /* nothing to do */ + ; } } #else /* DUK_USE_BASE64_FASTPATH */ DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) { - duk_small_uint_t i, snip; - duk_uint_t t; - duk_uint_fast8_t x, y; - const duk_uint8_t *src_end; + duk_small_uint_t i, npad; + duk_uint_t t, x, y; + const duk_uint8_t *p; + const duk_uint8_t *p_end; + duk_uint8_t *q; - src_end = src + srclen; + p = src; + p_end = src + srclen; + q = dst; + npad = 0U; - while (src < src_end) { - /* read 3 bytes into 't', padded by zero */ - snip = 4; + while (p < p_end) { + /* Read 3 bytes into 't', padded by zero. */ t = 0; for (i = 0; i < 3; i++) { t = t << 8; - if (src >= src_end) { - snip--; + if (p < p_end) { + t += (duk_uint_t) (*p++); } else { - t += (duk_uint_t) (*src++); + /* This only happens on the last loop and we're + * guaranteed to exit on the next loop. + */ + npad++; } } + DUK_ASSERT(npad <= 2U); - /* - * Missing bytes snip base64 example - * 0 4 XXXX - * 1 3 XXX= - * 2 2 XX== + /* Emit 4 encoded characters. If npad > 0, some of the + * chars will be incorrect (zero bits) but we fix up the + * padding after the loop. A straightforward 64-byte + * lookup would be faster and cleaner, but this is shorter. */ - - DUK_ASSERT(snip >= 2 && snip <= 4); - for (i = 0; i < 4; i++) { - x = (duk_uint_fast8_t) ((t >> 18) & 0x3f); + x = ((t >> 18) & 0x3fU); t = t << 6; - /* A straightforward 64-byte lookup would be faster - * and cleaner, but this is shorter. - */ - if (i >= snip) { - y = '='; - } else if (x <= 25) { - y = x + 'A'; - } else if (x <= 51) { - y = x - 26 + 'a'; - } else if (x <= 61) { - y = x - 52 + '0'; - } else if (x == 62) { - y = '+'; + if (x <= 51U) { + if (x <= 25) { + y = x + DUK_ASC_UC_A; + } else { + y = x - 26 + DUK_ASC_LC_A; + } } else { - y = '/'; + if (x <= 61U) { + y = x - 52 + DUK_ASC_0; + } else if (x == 62) { + y = DUK_ASC_PLUS; + } else { + DUK_ASSERT(x == 63); + y = DUK_ASC_SLASH; + } } - *dst++ = (duk_uint8_t) y; + *q++ = (duk_uint8_t) y; } } + + /* Handle padding by rewriting 0-2 bogus characters at the end. + * + * Missing bytes npad base64 example + * 0 0 #### + * 1 1 ###= + * 2 2 ##== + */ + DUK_ASSERT(npad <= 2U); + while (npad > 0U) { + *(q - npad) = DUK_ASC_EQUALS; + npad--; + } } #endif /* DUK_USE_BASE64_FASTPATH */ #if defined(DUK_USE_BASE64_FASTPATH) DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) { duk_int_t x; - duk_int_t t; + duk_uint_t t; duk_small_uint_t n_equal; - duk_small_uint_t n_chars; - const duk_uint8_t *src_end; - const duk_uint8_t *src_end_safe; + duk_int8_t step; + const duk_uint8_t *p; + const duk_uint8_t *p_end; + const duk_uint8_t *p_end_safe; + duk_uint8_t *q; - src_end = src + srclen; - src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */ + p = src; + p_end = src + srclen; + p_end_safe = p_end - 8; /* If 'src <= src_end_safe', safe to read 8 bytes. */ + q = dst; - /* Innermost fast path processes 4 valid base-64 characters at a time - * but bails out on whitespace, padding chars ('=') and invalid chars. - * Once the slow path segment has been processed, we return to the - * inner fast path again. This handles e.g. base64 with newlines - * reasonably well because the majority of a line is in the fast path. + /* Alternate between a fast path which processes clean groups with no + * padding or whitespace, and a slow path which processes one arbitrary + * group and then re-enters the fast path. This handles e.g. base64 + * with newlines reasonably well because the majority of a line is in + * the fast path. */ for (;;) { - /* Fast path, handle units with just actual encoding characters. */ - - while (src <= src_end_safe) { - /* The lookup byte is intentionally sign extended to (at least) - * 32 bits and then ORed. This ensures that is at least 1 byte - * is negative, the highest bit of 't' will be set at the end - * and we don't need to check every byte. + /* Fast path, on each loop handle two 4-char input groups. + * If both are clean, emit 6 bytes and continue. If first + * is clean, emit 3 bytes and drop out; otherwise emit + * nothing and drop out. This approach could be extended to + * more groups per loop, but for inputs with e.g. periodic + * newlines (which are common) it might not be an improvement. + */ + while (DUK_LIKELY(p <= p_end_safe)) { + duk_int_t t1, t2; + + /* The lookup byte is intentionally sign extended to + * (at least) 32 bits and then ORed. This ensures + * that is at least 1 byte is negative, the highest + * bit of the accumulator will be set at the end and + * we don't need to check every byte. + * + * Read all input bytes first before writing output + * bytes to minimize aliasing. */ - DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p", - (const void *) src, (const void *) src_end_safe, (const void *) src_end)); - - t = (duk_int_t) duk_base64_dectab[*src++]; - t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++]; - t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++]; - t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++]; - - if (DUK_UNLIKELY(t < 0)) { - DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit")); - src -= 4; + DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p", + (const void *) p, (const void *) p_end_safe, (const void *) p_end)); + + t1 = (duk_int_t) duk__base64_dectab_fast[p[0]]; + t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]]; + t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]]; + t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]]; + + t2 = (duk_int_t) duk__base64_dectab_fast[p[4]]; + t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]]; + t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]]; + t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]]; + + q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU); + q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU); + q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU); + + q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU); + q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU); + q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU); + + /* Optimistic check using one branch. */ + if (DUK_LIKELY((t1 | t2) >= 0)) { + p += 8; + q += 6; + } else if (t1 >= 0) { + DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group")); + DUK_ASSERT(t2 < 0); + p += 4; + q += 3; + break; + } else { + DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group")); + DUK_ASSERT(t1 < 0); break; } + } /* fast path */ - DUK_ASSERT(t <= 0xffffffL); - DUK_ASSERT((t >> 24) == 0); - *dst++ = (duk_uint8_t) (t >> 16); - *dst++ = (duk_uint8_t) ((t >> 8) & 0xff); - *dst++ = (duk_uint8_t) (t & 0xff); - } - - /* Handle one slow path unit (or finish if we're done). */ - - n_equal = 0; - n_chars = 0; - t = 0; + /* Slow path step 1: try to scan a 4-character encoded group, + * end-of-input, or start-of-padding. We exit with: + * 1. n_chars == 4: full group, no padding, no end-of-input. + * 2. n_chars < 4: partial group (may also be 0), encountered + * padding or end of input. + * + * The accumulator is initialized to 1; this allows us to detect + * a full group by comparing >= 0x1000000 without an extra + * counter variable. + */ + t = 1UL; for (;;) { - DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld", - (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t)); - - if (DUK_UNLIKELY(src >= src_end)) { - goto done; /* two level break */ - } - - x = duk_base64_dectab[*src++]; - if (DUK_UNLIKELY(x < 0)) { - if (x == -2) { + DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu", + (const void *) p, (const void *) p_end, (unsigned long) t)); + + if (DUK_LIKELY(p < p_end)) { + x = duk__base64_dectab_fast[*p++]; + if (DUK_LIKELY(x >= 0)) { + DUK_ASSERT(x >= 0 && x <= 63); + t = (t << 6) + (duk_uint_t) x; + if (t >= 0x1000000UL) { + break; + } + } else if (x == -1) { continue; /* allowed ascii whitespace */ - } else if (x == -3) { - n_equal++; - t <<= 6; + } else if (x == -2) { + p--; + break; /* start of padding */ } else { - DUK_ASSERT(x == -1); + DUK_ASSERT(x == -3); goto decode_error; } } else { - DUK_ASSERT(x >= 0 && x <= 63); - if (n_equal > 0) { - /* Don't allow actual chars after equal sign. */ - goto decode_error; - } - t = (t << 6) + x; + break; /* end of input */ } + } /* slow path step 1 */ - if (DUK_UNLIKELY(n_chars == 3)) { - /* Emit 3 bytes and backtrack if there was padding. There's - * always space for the whole 3 bytes so no check needed. - */ - DUK_ASSERT(t <= 0xffffffL); - DUK_ASSERT((t >> 24) == 0); - *dst++ = (duk_uint8_t) (t >> 16); - *dst++ = (duk_uint8_t) ((t >> 8) & 0xff); - *dst++ = (duk_uint8_t) (t & 0xff); - - if (DUK_UNLIKELY(n_equal > 0)) { - DUK_ASSERT(n_equal <= 4); - - /* There may be whitespace between the equal signs. */ - if (n_equal == 1) { - /* XXX= */ - dst -= 1; - } else if (n_equal == 2) { - /* XX== */ - dst -= 2; - } else { - goto decode_error; /* invalid padding */ - } + /* Complete the padding by simulating pad characters, + * regardless of actual input padding chars. + */ + n_equal = 0; + while (t < 0x1000000UL) { + t = (t << 6) + 0U; + n_equal++; + } - /* Continue parsing after padding, allows concatenated, - * padded base64. - */ - } - break; /* back to fast loop */ + /* Slow path step 2: deal with full/partial group, padding, + * etc. Note that for num chars in [0,3] we intentionally emit + * 3 bytes but don't step forward that much, buffer space is + * guaranteed in setup. + * + * num chars: + * 0 #### no output (= step 0) + * 1 #=== reject, 6 bits of data + * 2 ##== 12 bits of data, output 1 byte (= step 1) + * 3 ###= 18 bits of data, output 2 bytes (= step 2) + * 4 #### 24 bits of data, output 3 bytes (= step 3) + */ + q[0] = (duk_uint8_t) ((t >> 16) & 0xffU); + q[1] = (duk_uint8_t) ((t >> 8) & 0xffU); + q[2] = (duk_uint8_t) (t & 0xffU); + + DUK_ASSERT(n_equal <= 4); + step = duk__base64_decode_nequal_step[n_equal]; + if (DUK_UNLIKELY(step < 0)) { + goto decode_error; + } + q += step; + + /* Slow path step 3: read and ignore padding and whitespace + * until (a) next non-padding and non-whitespace character + * after which we resume the fast path, or (b) end of input. + * This allows us to accept missing, partial, full, and extra + * padding cases uniformly. We also support concatenated + * base-64 documents because we resume scanning afterwards. + * + * Note that to support concatenated documents well, the '=' + * padding found inside the input must also allow for 'extra' + * padding. For example, 'Zm===' decodes to 'f' and has one + * extra padding char. So, 'Zm===Zm' should decode 'ff', even + * though the standard break-up would be 'Zm==' + '=Zm' which + * doesn't make sense. + * + * We also accept prepended padding like '==Zm9', because it + * is equivalent to an empty document with extra padding ('==') + * followed by a valid document. + */ + + for (;;) { + if (DUK_UNLIKELY(p >= p_end)) { + goto done; + } + x = duk__base64_dectab_fast[*p++]; + if (x == -1 || x == -2) { + ; /* padding or whitespace, keep eating */ } else { - n_chars++; + p--; + break; /* backtrack and go back to fast path, even for -1 */ } - } - } - done: - DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld", - (const void *) src, (const void *) src_end, (long) n_chars)); + } /* slow path step 3 */ + } /* outer fast+slow path loop */ - DUK_ASSERT(src == src_end); + done: + DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p", + (const void *) p, (const void *) p_end)); - if (n_chars != 0) { - /* Here we'd have the option of decoding unpadded base64 - * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not - * accepted. - */ - goto decode_error; - } + DUK_ASSERT(p == p_end); - *out_dst_final = dst; + *out_dst_final = q; return 1; decode_error: @@ -14908,94 +15111,138 @@ DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_ } #else /* DUK_USE_BASE64_FASTPATH */ DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) { - duk_uint_t t; - duk_uint_fast8_t x, y; - duk_small_uint_t group_idx; - duk_small_uint_t n_equal; - const duk_uint8_t *src_end; + duk_uint_t t, x; + duk_int_t y; + duk_int8_t step; + const duk_uint8_t *p; + const duk_uint8_t *p_end; + duk_uint8_t *q; + /* 0x09, 0x0a, or 0x0d */ + duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13); - src_end = src + srclen; - t = 0; - group_idx = 0; - n_equal = 0; - - while (src < src_end) { - x = *src++; - - if (x >= 'A' && x <= 'Z') { - y = x - 'A' + 0; - } else if (x >= 'a' && x <= 'z') { - y = x - 'a' + 26; - } else if (x >= '0' && x <= '9') { - y = x - '0' + 52; - } else if (x == '+') { - y = 62; - } else if (x == '/') { - y = 63; - } else if (x == '=') { - /* We don't check the zero padding bytes here right now - * (that they're actually zero). This seems to be common - * behavior for base-64 decoders. + /* 't' tracks progress of the decoded group: + * + * t == 1 no valid chars yet + * t >= 0x40 1x6 = 6 bits shifted in + * t >= 0x1000 2x6 = 12 bits shifted in + * t >= 0x40000 3x6 = 18 bits shifted in + * t >= 0x1000000 4x6 = 24 bits shifted in + * + * By initializing t=1 there's no need for a separate counter for + * the number of characters found so far. + */ + p = src; + p_end = src + srclen; + q = dst; + t = 1UL; + + for (;;) { + duk_small_uint_t n_equal; + + DUK_ASSERT(t >= 1U); + if (p >= p_end) { + /* End of input: if input exists, treat like + * start of padding, finish the block, then + * re-enter here to see we're done. */ + if (t == 1U) { + break; + } else { + goto simulate_padding; + } + } - n_equal++; - t <<= 6; /* shift in zeroes */ - goto skip_add; - } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) { - /* allow basic ASCII whitespace */ - continue; + x = *p++; + + if (x >= 0x41U) { + /* Valid: a-z and A-Z. */ + DUK_ASSERT(x >= 0x41U && x <= 0xffU); + if (x >= 0x61U && x <= 0x7aU) { + y = (duk_int_t) x - 0x61 + 26; + } else if (x <= 0x5aU) { + y = (duk_int_t) x - 0x41; + } else { + goto decode_error; + } + } else if (x >= 0x30U) { + /* Valid: 0-9 and =. */ + DUK_ASSERT(x >= 0x30U && x <= 0x40U); + if (x <= 0x39U) { + y = (duk_int_t) x - 0x30 + 52; + } else if (x == 0x3dU) { + /* Skip padding and whitespace unless we're in the + * middle of a block. Otherwise complete group by + * simulating shifting in the correct padding. + */ + if (t == 1U) { + continue; + } + goto simulate_padding; + } else { + goto decode_error; + } + } else if (x >= 0x20U) { + /* Valid: +, /, and 0x20 whitespace. */ + DUK_ASSERT(x >= 0x20U && x <= 0x2fU); + if (x == 0x2bU) { + y = 62; + } else if (x == 0x2fU) { + y = 63; + } else if (x == 0x20U) { + continue; + } else { + goto decode_error; + } } else { - goto decode_error; + /* Valid: whitespace. */ + duk_uint32_t m; + DUK_ASSERT(x < 0x20U); /* 0x00 to 0x1f */ + m = (1U << x); + if (mask_white & m) { + /* Allow basic ASCII whitespace. */ + continue; + } else { + goto decode_error; + } } - if (n_equal > 0) { - /* Don't allow mixed padding and actual chars. */ - goto decode_error; + DUK_ASSERT(y >= 0 && y <= 63); + t = (t << 6) + (duk_uint_t) y; + if (t < 0x1000000UL) { + continue; } - t = (t << 6) + y; - skip_add: - - if (group_idx == 3) { - /* output 3 bytes from 't' */ - *dst++ = (duk_uint8_t) ((t >> 16) & 0xff); - *dst++ = (duk_uint8_t) ((t >> 8) & 0xff); - *dst++ = (duk_uint8_t) (t & 0xff); - - if (DUK_UNLIKELY(n_equal > 0)) { - /* Backtrack. */ - DUK_ASSERT(n_equal <= 4); - if (n_equal == 1) { - dst -= 1; - } else if (n_equal == 2) { - dst -= 2; - } else { - goto decode_error; /* invalid padding */ - } + /* fall through; no padding will be added */ - /* Here we can choose either to end parsing and ignore - * whatever follows, or to continue parsing in case - * multiple (possibly padded) base64 strings have been - * concatenated. Currently, keep on parsing. - */ - n_equal = 0; - } + simulate_padding: + n_equal = 0; + while (t < 0x1000000UL) { + t = (t << 6) + 0U; + n_equal++; + } - t = 0; - group_idx = 0; - } else { - group_idx++; + /* Output 3 bytes from 't' and advance as needed. */ + q[0] = (duk_uint8_t) ((t >> 16) & 0xffU); + q[1] = (duk_uint8_t) ((t >> 8) & 0xffU); + q[2] = (duk_uint8_t) (t & 0xffU); + + DUK_ASSERT(n_equal <= 4U); + step = duk__base64_decode_nequal_step[n_equal]; + if (step < 0) { + goto decode_error; } - } + q += step; - if (group_idx != 0) { - /* Here we'd have the option of decoding unpadded base64 - * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not - * accepted. + /* Re-enter loop. The actual padding characters are skipped + * by the main loop. This handles cases like missing, partial, + * full, and extra padding, and allows parsing of concatenated + * documents (with extra padding) like: Zm===Zm. Also extra + * prepended padding is accepted: ===Zm9v. */ - goto decode_error; + t = 1U; } + DUK_ASSERT(t == 1UL); - *out_dst_final = dst; + *out_dst_final = q; return 1; decode_error: @@ -15012,15 +15259,12 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); - /* XXX: optimize for string inputs: no need to coerce to a buffer - * which makes a copy of the input. - */ - idx = duk_require_normalize_index(thr, idx); src = duk__prep_codec_arg(thr, idx, &srclen); /* Note: for srclen=0, src may be NULL */ - /* Computation must not wrap; this limit works for 32-bit size_t: + /* Compute exact output length. Computation must not wrap; this + * limit works for 32-bit size_t: * >>> srclen = 3221225469 * >>> '%x' % ((srclen + 2) / 3 * 4) * 'fffffffc' @@ -15028,7 +15272,7 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) { if (srclen > 3221225469UL) { goto type_error; } - dstlen = (srclen + 2) / 3 * 4; + dstlen = (srclen + 2U) / 3U * 4U; dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen); duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst); @@ -15039,7 +15283,7 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) { type_error: DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED); - return NULL; /* never here */ + DUK_WO_NORETURN(return NULL;); } DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) { @@ -15048,31 +15292,24 @@ DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) { duk_size_t dstlen; duk_uint8_t *dst; duk_uint8_t *dst_final; - duk_bool_t retval; DUK_ASSERT_API_ENTRY(thr); - /* XXX: optimize for buffer inputs: no need to coerce to a string - * which causes an unnecessary interning. - */ - idx = duk_require_normalize_index(thr, idx); src = duk__prep_codec_arg(thr, idx, &srclen); - /* Computation must not wrap, only srclen + 3 is at risk of - * wrapping because after that the number gets smaller. - * This limit works for 32-bit size_t: - * 0x100000000 - 3 - 1 = 4294967292 + /* Round up and add safety margin. Avoid addition before division to + * avoid possibility of wrapping. Margin includes +3 for rounding up, + * and +3 for one extra group: the decoder may emit and then backtrack + * a full group (3 bytes) from zero-sized input for technical reasons. + * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then + * backtracked. */ - if (srclen > 4294967292UL) { - goto type_error; - } - dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */ + dstlen = (srclen / 4) * 3 + 6; /* upper limit, assuming no whitespace etc */ dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen); /* Note: for dstlen=0, dst may be NULL */ - retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final); - if (!retval) { + if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) { goto type_error; } @@ -15083,8 +15320,27 @@ DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) { type_error: DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED); + DUK_WO_NORETURN(return;); +} +#else /* DUK_USE_BASE64_SUPPORT */ +DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) { + DUK_UNREF(idx); + DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); +} + +DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) { + DUK_UNREF(idx); + DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } +#endif /* DUK_USE_BASE64_SUPPORT */ + +/* + * Hex + */ +#if defined(DUK_USE_HEX_SUPPORT) DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) { const duk_uint8_t *inp; duk_size_t len; @@ -15195,8 +15451,12 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) { } } for (; i < len; i += 2) { - t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) | - ((duk_int_t) duk_hex_dectab[inp[i + 1]]); + /* First cast to duk_int_t to sign extend, second cast to + * duk_uint_t to avoid signed left shift, and final cast to + * duk_int_t result type. + */ + t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) | + ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]])); if (DUK_UNLIKELY(t < 0)) { goto type_error; } @@ -15208,8 +15468,8 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) { * at least 16 bits. If either nybble is invalid, the * resulting 't' will be < 0. */ - t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) | - ((duk_int_t) duk_hex_dectab[inp[i + 1]]); + t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) | + ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]])); if (DUK_UNLIKELY(t < 0)) { goto type_error; } @@ -15222,7 +15482,24 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) { type_error: DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED); + DUK_WO_NORETURN(return;); } +#else /* DUK_USE_HEX_SUPPORT */ +DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) { + DUK_UNREF(idx); + DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); +} +DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) { + DUK_UNREF(idx); + DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); +} +#endif /* DUK_USE_HEX_SUPPORT */ + +/* + * JSON + */ #if defined(DUK_USE_JSON_SUPPORT) DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) { @@ -15275,12 +15552,14 @@ DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(idx); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return NULL;); } DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(idx); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_JSON_SUPPORT */ /* @@ -15374,6 +15653,7 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) { if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */ (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */ DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE); + DUK_WO_NORETURN(return 0;); } DUK_ASSERT(h_sourcecode != NULL); comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode); @@ -15498,6 +15778,7 @@ DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) { DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) { DUK_ASSERT_API_ENTRY(thr); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_JSON_SUPPORT */ @@ -15609,7 +15890,7 @@ DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) top = duk_get_top(thr); if (top < nvalues) { DUK_ERROR_RANGE(thr, "not enough stack values for notify"); - return ret; /* unreachable */ + DUK_WO_NORETURN(return 0;); } if (duk_debug_is_attached(thr->heap)) { duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY); @@ -15676,11 +15957,13 @@ DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr, DUK_UNREF(detached_cb); DUK_UNREF(udata); DUK_ERROR_TYPE(thr, "no debugger support"); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) { DUK_ASSERT_API_ENTRY(thr); DUK_ERROR_TYPE(thr, "no debugger support"); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) { @@ -15697,7 +15980,7 @@ DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) top = duk_get_top(thr); if (top < nvalues) { DUK_ERROR_RANGE_INVALID_COUNT(thr); - return 0; /* unreachable */ + DUK_WO_NORETURN(return 0;); } /* No debugger support, just pop values. */ @@ -15819,7 +16102,7 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) { duk_push_tval(thr, &lj->value2); /* XXX: creating_error == 0 is asserted above, so no need to store. */ - DUK_MEMCPY((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate)); + duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate)); snapshot->creating_error = heap->creating_error; snapshot->curr_thread = heap->curr_thread; snapshot->call_recursion_depth = heap->call_recursion_depth; @@ -15849,7 +16132,7 @@ DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) { heap = thr->heap; - DUK_MEMCPY((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate)); + duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate)); heap->creating_error = snapshot->creating_error; heap->curr_thread = snapshot->curr_thread; heap->call_recursion_depth = snapshot->call_recursion_depth; @@ -15985,7 +16268,7 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); /* Assume two's complement and set everything to -1. */ - DUK_MEMSET((void *) &vals, (int) 0xff, sizeof(vals)); + duk_memset((void *) &vals, (int) 0xff, sizeof(vals)); DUK_ASSERT(vals[DUK__IDX_TYPE] == -1); /* spot check one */ tv = duk_get_tval_or_unused(thr, idx); @@ -16001,12 +16284,12 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) { goto finish; } duk_push_pointer(thr, (void *) h); - duk_put_prop_string(thr, -2, "hptr"); + duk_put_prop_literal(thr, -2, "hptr"); #if 0 /* Covers a lot of information, e.g. buffer and string variants. */ duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h)); - duk_put_prop_string(thr, -2, "hflags"); + duk_put_prop_literal(thr, -2, "hflags"); #endif #if defined(DUK_USE_REFERENCE_COUNTING) @@ -16051,7 +16334,7 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) { } vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj); - vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj), + vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj); vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj); vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj); vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj); @@ -16252,7 +16535,7 @@ DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) { * Property handling * * The API exposes only the most common property handling functions. - * The caller can invoke Ecmascript built-ins for full control (e.g. + * The caller can invoke ECMAScript built-ins for full control (e.g. * defineProperty, getOwnPropertyDescriptor). */ @@ -16284,7 +16567,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_string(thr, key); + (void) duk_push_string(thr, key); return duk_get_prop(thr, obj_idx); } @@ -16293,9 +16576,21 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_lstring(thr, key, key_len); + (void) duk_push_lstring(thr, key, key_len); + return duk_get_prop(thr, obj_idx); +} + +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) { + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(key != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + obj_idx = duk_require_normalize_index(thr, obj_idx); + (void) duk_push_literal_raw(thr, key, key_len); return duk_get_prop(thr, obj_idx); } +#endif DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) { DUK_ASSERT_API_ENTRY(thr); @@ -16309,7 +16604,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT_API_ENTRY(thr); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ + (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ return duk_get_prop(thr, obj_idx); } @@ -16318,7 +16613,7 @@ DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, DUK_ASSERT_STRIDX_VALID(stridx); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx)); + (void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx)); return duk_get_prop(thr, obj_idx); } @@ -16337,10 +16632,7 @@ DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t if (out_has_prop) { *out_has_prop = rc; } - rc = duk_to_boolean(thr, -1); - DUK_ASSERT(rc == 0 || rc == 1); - duk_pop(thr); - return rc; + return duk_to_boolean_top_pop(thr); } DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) { @@ -16400,6 +16692,18 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx return duk__put_prop_shared(thr, obj_idx, -1); } +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) { + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(key != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + obj_idx = duk_normalize_index(thr, obj_idx); + (void) duk_push_literal_raw(thr, key, key_len); + return duk__put_prop_shared(thr, obj_idx, -1); +} +#endif + DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) { DUK_ASSERT_API_ENTRY(thr); @@ -16412,7 +16716,7 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT_API_ENTRY(thr); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ + (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ return duk__put_prop_shared(thr, obj_idx, -1); } @@ -16459,7 +16763,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_string(thr, key); + (void) duk_push_string(thr, key); return duk_del_prop(thr, obj_idx); } @@ -16468,9 +16772,21 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_lstring(thr, key, key_len); + (void) duk_push_lstring(thr, key, key_len); + return duk_del_prop(thr, obj_idx); +} + +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) { + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(key != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + obj_idx = duk_require_normalize_index(thr, obj_idx); + (void) duk_push_literal_raw(thr, key, key_len); return duk_del_prop(thr, obj_idx); } +#endif DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) { DUK_ASSERT_API_ENTRY(thr); @@ -16484,7 +16800,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT_API_ENTRY(thr); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ + (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ return duk_del_prop(thr, obj_idx); } @@ -16530,7 +16846,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_string(thr, key); + (void) duk_push_string(thr, key); return duk_has_prop(thr, obj_idx); } @@ -16539,9 +16855,21 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT(key != NULL); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_lstring(thr, key, key_len); + (void) duk_push_lstring(thr, key, key_len); + return duk_has_prop(thr, obj_idx); +} + +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) { + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(key != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + obj_idx = duk_require_normalize_index(thr, obj_idx); + (void) duk_push_literal_raw(thr, key, key_len); return duk_has_prop(thr, obj_idx); } +#endif DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) { DUK_ASSERT_API_ENTRY(thr); @@ -16555,7 +16883,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx DUK_ASSERT_API_ENTRY(thr); obj_idx = duk_require_normalize_index(thr, obj_idx); - duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ + (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */ return duk_has_prop(thr, obj_idx); } @@ -16755,17 +17083,17 @@ DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t f fail_invalid_desc: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR); - return; + DUK_WO_NORETURN(return;); fail_not_callable: DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE); - return; + DUK_WO_NORETURN(return;); } /* * Object related * - * Note: seal() and freeze() are accessible through Ecmascript bindings, + * Note: seal() and freeze() are accessible through ECMAScript bindings, * and are not exposed through the API. */ @@ -16857,6 +17185,7 @@ DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_b fail_cannot_freeze: DUK_ERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */ + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) { @@ -16940,6 +17269,38 @@ DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key return ret; } +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) { + duk_bool_t ret; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + /* XXX: direct implementation */ + + duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]); + ret = duk_get_prop_literal_raw(thr, -1, key, key_len); + duk_remove_m2(thr); + return ret; +} +#endif + +DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) { + duk_bool_t ret; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); + + /* XXX: direct implementation */ + + duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]); + ret = duk_get_prop_heapptr(thr, -1, ptr); + duk_remove_m2(thr); + return ret; +} + + DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) { duk_bool_t ret; @@ -16970,6 +17331,56 @@ DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key return ret; } +#if !defined(DUK_USE_PREFER_SIZE) +DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) { + duk_bool_t ret; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); + DUK_ASSERT(key[key_len] == (char) 0); + + /* XXX: direct implementation */ + + duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]); + duk_insert(thr, -2); + ret = duk_put_prop_literal_raw(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */ + duk_pop(thr); + return ret; +} +#endif + +DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) { + duk_bool_t ret; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); + + /* XXX: direct implementation */ + + duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]); + duk_insert(thr, -2); + ret = duk_put_prop_heapptr(thr, -2, ptr); /* [ ... global val ] -> [ ... global ] */ + duk_pop(thr); + return ret; +} + +/* + * ES2015 GetMethod() + */ + +DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) { + (void) duk_get_prop_stridx(thr, idx, stridx); + if (duk_is_null_or_undefined(thr, -1)) { + duk_pop_nodecref_unsafe(thr); + return 0; + } + if (!duk_is_callable(thr, -1)) { + DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE); + DUK_WO_NORETURN(return 0;); + } + return 1; +} + /* * Object prototype */ @@ -17008,7 +17419,7 @@ DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) { #if defined(DUK_USE_ROM_OBJECTS) if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */ - return; + DUK_WO_NORETURN(return;); } #endif @@ -17065,14 +17476,25 @@ DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(idx); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(idx); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_FINALIZER_SUPPORT */ +/* + * Random numbers + */ + +/* #include duk_internal.h -> already included */ + +DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) { + return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr); +} /* * API calls related to general value stack manipulation: resizing the value * stack, pushing and popping values, type checking and reading values, @@ -17247,7 +17669,7 @@ DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int if (require) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER); - /* not reachable */ + DUK_WO_NORETURN(return 0;); } return def_value; @@ -17298,7 +17720,7 @@ DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_u if (require) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER); - /* not reachable */ + DUK_WO_NORETURN(return 0;); } return def_value; @@ -17373,7 +17795,7 @@ DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t i return (duk_idx_t) uidx; } DUK_ERROR_RANGE_INDEX(thr, idx); - return 0; /* unreachable */ + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) { @@ -17449,7 +17871,7 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) { return thr->valstack_bottom + uidx; } DUK_ERROR_RANGE_INDEX(thr, idx); - return NULL; + DUK_WO_NORETURN(return NULL;); } /* Non-critical. */ @@ -17467,7 +17889,7 @@ DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) { if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) { DUK_ERROR_RANGE_INDEX(thr, idx); - return; /* unreachable */ + DUK_WO_NORETURN(return;); } } @@ -17492,6 +17914,7 @@ DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_t ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); if (DUK_UNLIKELY(ret < min_top)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return 0;); } return ret; } @@ -17536,7 +17959,7 @@ DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) { #else if (DUK_UNLIKELY(uidx > vs_limit)) { DUK_ERROR_RANGE_INDEX(thr, idx); - return; /* unreachable */ + DUK_WO_NORETURN(return;); } #endif DUK_ASSERT(uidx <= vs_limit); @@ -17719,7 +18142,7 @@ DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) { ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1; if (DUK_UNLIKELY(ret < 0)) { DUK_ERROR_RANGE_INDEX(thr, -1); - return 0; /* unreachable */ + DUK_WO_NORETURN(return 0;); } return ret; } @@ -17920,6 +18343,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, */ if (throw_on_error) { DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT); + DUK_WO_NORETURN(return 0;); } return 0; } @@ -17927,6 +18351,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, if (duk__resize_valstack(thr, new_size) == 0) { if (throw_on_error) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return 0;); } return 0; } @@ -18187,7 +18612,7 @@ DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) { if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) { DUK_ERROR_RANGE_INDEX(thr, -1); - return; /* unreachable */ + DUK_WO_NORETURN(return;); } tv_from = thr->valstack_top - 1; tv_to = thr->valstack_top++; @@ -18249,18 +18674,12 @@ DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) { DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu", (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes)); - /* No net refcount changes. */ - - if (nbytes > 0) { - DUK_TVAL_SET_TVAL(&tv_tmp, q); - DUK_ASSERT(nbytes > 0); - DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes); - DUK_TVAL_SET_TVAL(p, &tv_tmp); - } else { - /* nop: insert top to top */ - DUK_ASSERT(nbytes == 0); - DUK_ASSERT(p == q); - } + /* No net refcount changes. No need to special case nbytes == 0 + * (p == q). + */ + DUK_TVAL_SET_TVAL(&tv_tmp, q); + duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes); + DUK_TVAL_SET_TVAL(p, &tv_tmp); } DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) { @@ -18352,7 +18771,7 @@ DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) { #endif nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */ - DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */ + duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes); DUK_TVAL_SET_UNDEFINED(q); thr->valstack_top--; @@ -18405,7 +18824,7 @@ DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) DUK_TVAL_DECREF_NORZ(thr, tv); } - DUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, bytes); + duk_memmove((void *) tv_dst, (const void *) tv_src, bytes); tv_newtop = thr->valstack_top - count; for (tv = tv_newtop; tv < thr->valstack_top; tv++) { @@ -18444,14 +18863,14 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, if (DUK_UNLIKELY(to_thr == from_thr)) { DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT); - return; + DUK_WO_NORETURN(return;); } if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) { /* Maximum value check ensures 'nbytes' won't wrap below. * Also handles negative count. */ DUK_ERROR_RANGE_INVALID_COUNT(to_thr); - return; + DUK_WO_NORETURN(return;); } DUK_ASSERT(count >= 0); @@ -18462,17 +18881,19 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end); if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) { DUK_ERROR_RANGE_PUSH_BEYOND(to_thr); + DUK_WO_NORETURN(return;); } src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes); if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) { DUK_ERROR_RANGE_INVALID_COUNT(to_thr); + DUK_WO_NORETURN(return;); } - /* copy values (no overlap even if to_thr == from_thr; that's not - * allowed now anyway) + /* Copy values (no overlap even if to_thr == from_thr; that's not + * allowed now anyway). */ DUK_ASSERT(nbytes > 0); - DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes); + duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes); p = to_thr->valstack_top; to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes); @@ -18521,7 +18942,7 @@ DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes); copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src); thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes); - DUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, copy_bytes); + duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes); /* Values in the gap are left as garbage: caller must fill them in * and INCREF them before any side effects. @@ -18542,6 +18963,7 @@ DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED); + DUK_WO_NORETURN(return;); } } @@ -18554,6 +18976,7 @@ DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL); + DUK_WO_NORETURN(return;); } } @@ -18602,6 +19025,7 @@ DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) { return ret; } else { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN); + DUK_WO_NORETURN(return 0;); } } @@ -18663,6 +19087,7 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER); + DUK_WO_NORETURN(return 0.0;); } ret.d = DUK_TVAL_GET_NUMBER(tv); @@ -18894,6 +19319,7 @@ DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT); + DUK_WO_NORETURN(return;); } } @@ -18945,6 +19371,7 @@ DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER); + DUK_WO_NORETURN(return NULL;); } p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */ return p; @@ -18992,6 +19419,7 @@ DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size } else { if (throw_flag) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER); + DUK_WO_NORETURN(return NULL;); } len = def_size; ret = def_ptr; @@ -19095,6 +19523,7 @@ DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_ if (throw_flag) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER); + DUK_WO_NORETURN(return NULL;); } return def_ptr; } @@ -19174,6 +19603,7 @@ DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) { h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING); if (DUK_UNLIKELY(h == NULL)) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING); + DUK_WO_NORETURN(return NULL;); } return h; } @@ -19186,6 +19616,7 @@ DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_id h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING); if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING); + DUK_WO_NORETURN(return NULL;); } return h; } @@ -19203,6 +19634,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) { h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT); if (DUK_UNLIKELY(h == NULL)) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT); + DUK_WO_NORETURN(return NULL;); } return h; } @@ -19220,6 +19652,7 @@ DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) { h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER); if (DUK_UNLIKELY(h == NULL)) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER); + DUK_WO_NORETURN(return NULL;); } return h; } @@ -19244,6 +19677,7 @@ DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) { h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT); if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD); + DUK_WO_NORETURN(return NULL;); } return (duk_hthread *) h; } @@ -19268,6 +19702,7 @@ DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t id h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT); if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC); + DUK_WO_NORETURN(return NULL;); } return (duk_hcompfunc *) h; } @@ -19292,6 +19727,7 @@ DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT); if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC); + DUK_WO_NORETURN(return NULL;); } return (duk_hnatfunc *) h; } @@ -19350,6 +19786,7 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t i ret = duk_get_c_function(thr, idx); if (DUK_UNLIKELY(!ret)) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC); + DUK_WO_NORETURN(return ret;); } return ret; } @@ -19358,6 +19795,7 @@ DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT_API_ENTRY(thr); if (DUK_UNLIKELY(!duk_is_function(thr, idx))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION); + DUK_WO_NORETURN(return;); } } @@ -19369,6 +19807,7 @@ DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) { h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC); if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE); + DUK_WO_NORETURN(return;); } /* Lightfuncs (h == NULL) are constructable. */ } @@ -19456,6 +19895,7 @@ DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(tv != NULL); if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE); + DUK_WO_NORETURN(return NULL;); } ret = (void *) DUK_TVAL_GET_HEAPHDR(tv); @@ -19489,6 +19929,7 @@ DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_i if (type_mask & DUK_TYPE_MASK_THROW) { DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT); + DUK_WO_NORETURN(return NULL;); } return NULL; } @@ -19549,6 +19990,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_i DUK_UNREF(h_class); DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE); + DUK_WO_NORETURN(return NULL;); } return h; } @@ -19741,49 +20183,43 @@ DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) { } /* E5 Section 9.1 */ -DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) { - /* inline initializer for coercers[] is not allowed by old compilers like BCC */ +DUK_LOCAL const char * const duk__toprim_hint_strings[3] = { + "default", "string", "number" +}; +DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) { + /* Inline initializer for coercers[] is not allowed by old compilers like BCC. */ duk_small_uint_t coercers[2]; - duk_small_uint_t class_number; DUK_ASSERT_API_ENTRY(thr); DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING); idx = duk_require_normalize_index(thr, idx); + /* If already primitive, return as is. */ if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) { - /* Any other values stay as is. */ DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */ return; } - class_number = duk_get_class_number(thr, idx); - - /* XXX: Symbol objects normally coerce via the ES2015-revised ToPrimitive() - * algorithm which consults value[@@toPrimitive] and avoids calling - * .valueOf() and .toString(). Before that is implemented, special - * case Symbol objects to behave as if they had the default @@toPrimitive - * algorithm of E6 Section 19.4.3.4, i.e. return the plain symbol value - * with no further side effects. + /* @@toPrimitive lookup. Also do for plain buffers and lightfuncs + * which mimic objects. */ - - if (class_number == DUK_HOBJECT_CLASS_SYMBOL) { - duk_hobject *h_obj; - duk_hstring *h_str; - - /* XXX: pretty awkward, index based API for internal value access? */ - h_obj = duk_known_hobject(thr, idx); - h_str = duk_hobject_get_internal_value_string(thr->heap, h_obj); - if (h_str) { - duk_push_hstring(thr, h_str); - duk_replace(thr, idx); - return; + if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) { + DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *)); + duk_dup(thr, idx); + duk_push_string(thr, duk__toprim_hint_strings[hint]); + duk_call_method(thr, 1); /* [ ... method value hint ] -> [ ... res] */ + if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | + DUK_TYPE_MASK_LIGHTFUNC | + DUK_TYPE_MASK_BUFFER)) { + goto fail; } + duk_replace(thr, idx); + return; } - /* Objects are coerced based on E5 specification. * Lightfuncs are coerced because they behave like * objects even if they're internally a primitive @@ -19791,17 +20227,29 @@ DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hi * like ArrayBuffer objects since Duktape 2.x. */ - coercers[0] = DUK_STRIDX_VALUE_OF; - coercers[1] = DUK_STRIDX_TO_STRING; - + /* Hint magic for Date is unnecessary in ES2015 because of + * Date.prototype[@@toPrimitive]. However, it is needed if + * symbol support is not enabled. + */ +#if defined(DUK_USE_SYMBOL_BUILTIN) + if (hint == DUK_HINT_NONE) { + hint = DUK_HINT_NUMBER; + } +#else /* DUK_USE_SYMBOL_BUILTIN */ if (hint == DUK_HINT_NONE) { + duk_small_uint_t class_number; + + class_number = duk_get_class_number(thr, idx); if (class_number == DUK_HOBJECT_CLASS_DATE) { hint = DUK_HINT_STRING; } else { hint = DUK_HINT_NUMBER; } } +#endif /* DUK_USE_SYMBOL_BUILTIN */ + coercers[0] = DUK_STRIDX_VALUE_OF; + coercers[1] = DUK_STRIDX_TO_STRING; if (hint == DUK_HINT_STRING) { coercers[0] = DUK_STRIDX_TO_STRING; coercers[1] = DUK_STRIDX_VALUE_OF; @@ -19817,9 +20265,21 @@ DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hi return; } + fail: DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED); + DUK_WO_NORETURN(return;); } +DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) { + duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/); +} + +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) { + duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/); +} +#endif + /* E5 Section 9.2 */ DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) { duk_tval *tv; @@ -19840,6 +20300,22 @@ DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) { return val; } +DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) { + duk_tval *tv; + duk_bool_t val; + + DUK_ASSERT_API_ENTRY(thr); + + tv = duk_require_tval(thr, -1); + DUK_ASSERT(tv != NULL); + + val = duk_js_toboolean(tv); + DUK_ASSERT(val == 0 || val == 1); + + duk_pop_unsafe(thr); + return val; +} + DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) { duk_tval *tv; duk_double_t d; @@ -20119,68 +20595,67 @@ DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) { #endif /* Push Object.prototype.toString() output for 'tv'. */ -DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv) { - duk_small_uint_t stridx; - duk_hstring *h_strclass; +#if 0 /* See XXX note why this variant doesn't work. */ +DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) { + duk_uint_t stridx_bidx = 0; /* (prototype_bidx << 16) + default_tag_stridx */ DUK_ASSERT_API_ENTRY(thr); + /* Conceptually for any non-undefined/null value we should do a + * ToObject() coercion and look up @@toStringTag (from the object + * prototype) to see if a custom tag should be used. Avoid the + * actual conversion by doing a prototype lookup without the object + * coercion. However, see problem below. + */ + + duk_push_literal(thr, "[object "); /* -> [ ... "[object" ] */ + switch (DUK_TVAL_GET_TAG(tv)) { case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */ case DUK_TAG_UNDEFINED: { - stridx = DUK_STRIDX_UC_UNDEFINED; - break; + stridx_bidx = DUK_STRIDX_UC_UNDEFINED; + goto use_stridx; } case DUK_TAG_NULL: { - stridx = DUK_STRIDX_UC_NULL; - break; + stridx_bidx = DUK_STRIDX_UC_NULL; + goto use_stridx; } case DUK_TAG_BOOLEAN: { - stridx = DUK_STRIDX_UC_BOOLEAN; - break; + stridx_bidx = (DUK_BIDX_BOOLEAN_PROTOTYPE << 16) + DUK_STRIDX_UC_BOOLEAN; + goto use_proto_bidx; } case DUK_TAG_POINTER: { - stridx = DUK_STRIDX_UC_POINTER; - break; + stridx_bidx = (DUK_BIDX_POINTER_PROTOTYPE << 16) + DUK_STRIDX_UC_POINTER; + goto use_proto_bidx; } case DUK_TAG_LIGHTFUNC: { - stridx = DUK_STRIDX_UC_FUNCTION; - break; + stridx_bidx = (DUK_BIDX_FUNCTION_PROTOTYPE << 16) + DUK_STRIDX_UC_FUNCTION; + goto use_proto_bidx; } case DUK_TAG_STRING: { duk_hstring *h; h = DUK_TVAL_GET_STRING(tv); DUK_ASSERT(h != NULL); if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) { - stridx = DUK_STRIDX_UC_SYMBOL; + /* Even without DUK_USE_SYMBOL_BUILTIN the Symbol + * prototype exists so we can lookup @@toStringTag + * and provide [object Symbol] for symbol values + * created from C code. + */ + stridx_bidx = (DUK_BIDX_SYMBOL_PROTOTYPE << 16) + DUK_STRIDX_UC_SYMBOL; } else { - stridx = DUK_STRIDX_UC_STRING; + stridx_bidx = (DUK_BIDX_STRING_PROTOTYPE << 16) + DUK_STRIDX_UC_STRING; } - break; + goto use_proto_bidx; } case DUK_TAG_OBJECT: { - duk_hobject *h; - duk_small_uint_t classnum; - - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h); - stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum); - - /* XXX: This is not entirely correct anymore; in ES2015 the - * default lookup should use @@toStringTag to come up with - * e.g. [object Symbol], [object Uint8Array], etc. See - * ES2015 Section 19.1.3.6. The downside of implementing that - * directly is that the @@toStringTag lookup may have side - * effects, so all call sites must be checked for that. - * Some may need a side-effect free lookup, e.g. avoiding - * getters which are not typical. - */ - break; + duk_push_tval(thr, tv); + stridx_bidx = 0xffffffffUL; /* Marker value. */ + goto use_pushed_object; } case DUK_TAG_BUFFER: { - stridx = DUK_STRIDX_UINT8_ARRAY; - break; + stridx_bidx = (DUK_BIDX_UINT8ARRAY_PROTOTYPE << 16) + DUK_STRIDX_UINT8_ARRAY; + goto use_proto_bidx; } #if defined(DUK_USE_FASTINT) case DUK_TAG_FASTINT: @@ -20188,14 +20663,142 @@ DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv) { #endif default: { DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* number (maybe fastint) */ - stridx = DUK_STRIDX_UC_NUMBER; - break; + stridx_bidx = (DUK_BIDX_NUMBER_PROTOTYPE << 16) + DUK_STRIDX_UC_NUMBER; + goto use_proto_bidx; + } + } + DUK_ASSERT(0); /* Never here. */ + + use_proto_bidx: + DUK_ASSERT_BIDX_VALID((stridx_bidx >> 16) & 0xffffUL); + duk_push_hobject(thr, thr->builtins[(stridx_bidx >> 16) & 0xffffUL]); + /* Fall through. */ + + use_pushed_object: + /* [ ... "[object" obj ] */ + +#if defined(DUK_USE_SYMBOL_BUILTIN) + /* XXX: better handling with avoid_side_effects == 1; lookup tval + * without Proxy or getter side effects, and use it in sanitized + * form if it's a string. + */ + if (!avoid_side_effects) { + /* XXX: The problem with using the prototype object as the + * lookup base is that if @@toStringTag is a getter, its + * 'this' binding must be the ToObject() coerced input value, + * not the prototype object of the type. + */ + (void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG); + if (duk_is_string_notsymbol(thr, -1)) { + duk_remove_m2(thr); + goto finish; + } + duk_pop_unsafe(thr); } +#endif + + if (stridx_bidx == 0xffffffffUL) { + duk_hobject *h_obj; + duk_small_uint_t classnum; + + h_obj = duk_known_hobject(thr, -1); + DUK_ASSERT(h_obj != NULL); + classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj); + stridx_bidx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum); + } else { + /* stridx_bidx already has the desired fallback stridx. */ + ; + } + duk_pop_unsafe(thr); + /* Fall through. */ + + use_stridx: + /* [ ... "[object" ] */ + duk_push_hstring_stridx(thr, stridx_bidx & 0xffffUL); + + finish: + /* [ ... "[object" tag ] */ + duk_push_literal(thr, "]"); + duk_concat(thr, 3); /* [ ... "[object" tag "]" ] -> [ ... res ] */ +} +#endif /* 0 */ + +DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) { + duk_hobject *h_obj; + duk_small_uint_t classnum; + duk_small_uint_t stridx; + duk_tval tv_tmp; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(tv != NULL); + + /* Stabilize 'tv', duk_push_literal() may trigger side effects. */ + DUK_TVAL_SET_TVAL(&tv_tmp, tv); + tv = &tv_tmp; + + /* Conceptually for any non-undefined/null value we should do a + * ToObject() coercion and look up @@toStringTag (from the object + * prototype) to see if a custom result should be used. We'd like to + * avoid the actual conversion, but even for primitive types the + * prototype may have @@toStringTag. What's worse, the @@toStringTag + * property may be a getter that must get the object coerced value + * (not the prototype) as its 'this' binding. + * + * For now, do an actual object coercion. This could be avoided by + * doing a side effect free lookup to see if a getter would be invoked. + * If not, the value can be read directly and the object coercion could + * be avoided. This may not be worth it in practice, because + * Object.prototype.toString() is usually not performance critical. + */ + + duk_push_literal(thr, "[object "); /* -> [ ... "[object" ] */ + + switch (DUK_TVAL_GET_TAG(tv)) { + case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */ + case DUK_TAG_UNDEFINED: { + duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED); + goto finish; + } + case DUK_TAG_NULL: { + duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL); + goto finish; + } + } + + duk_push_tval(thr, tv); + tv = NULL; /* Invalidated by ToObject(). */ + duk_to_object(thr, -1); + + /* [ ... "[object" obj ] */ + +#if defined(DUK_USE_SYMBOL_BUILTIN) + /* XXX: better handling with avoid_side_effects == 1; lookup tval + * without Proxy or getter side effects, and use it in sanitized + * form if it's a string. + */ + if (!avoid_side_effects) { + (void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG); + if (duk_is_string_notsymbol(thr, -1)) { + duk_remove_m2(thr); + goto finish; + } + duk_pop_unsafe(thr); } - h_strclass = DUK_HTHREAD_GET_STRING(thr, stridx); - DUK_ASSERT(h_strclass != NULL); +#else + DUK_UNREF(avoid_side_effects); +#endif + + h_obj = duk_known_hobject(thr, -1); + DUK_ASSERT(h_obj != NULL); + classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj); + stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum); + duk_pop_unsafe(thr); + duk_push_hstring_stridx(thr, stridx); - duk_push_sprintf(thr, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass)); + finish: + /* [ ... "[object" tag ] */ + duk_push_literal(thr, "]"); + duk_concat(thr, 3); /* [ ... "[object" tag "]" ] -> [ ... res ] */ } /* XXX: other variants like uint, u32 etc */ @@ -20255,6 +20858,7 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, d /* coerced value is updated to value stack even when RangeError thrown */ if (clamped) { DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE); + DUK_WO_NORETURN(return 0;); } } @@ -20312,12 +20916,14 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) { DUK_ASSERT(h != NULL); if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) { DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL); + DUK_WO_NORETURN(goto skip_replace;); } else { goto skip_replace; } #else goto skip_replace; #endif + break; } case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */ case DUK_TAG_OBJECT: { @@ -20468,14 +21074,9 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t } dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/); - if (DUK_LIKELY(src_size > 0)) { - /* When src_size == 0, src_data may be NULL (if source - * buffer is dynamic), and dst_data may be NULL (if - * target buffer is dynamic). Avoid zero-size memcpy() - * with an invalid pointer. - */ - DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size); - } + /* dst_data may be NULL if size is zero. */ + duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size); + duk_replace(thr, idx); skip_copy: @@ -20591,6 +21192,7 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) { case DUK_TAG_UNDEFINED: case DUK_TAG_NULL: { DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE); + DUK_WO_NORETURN(return;); break; } case DUK_TAG_BOOLEAN: { @@ -20898,7 +21500,7 @@ DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk } if (mask & DUK_TYPE_MASK_THROW) { DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return 0;); } return 0; } @@ -21371,21 +21973,22 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk DUK_ASSERT_API_ENTRY(thr); - /* check stack before interning (avoid hanging temp) */ + /* Check stack before interning (avoid hanging temp). */ DUK__CHECK_SPACE(); /* NULL with zero length represents an empty string; NULL with higher - * length is also now trated like an empty string although it is + * length is also now treated like an empty string although it is * a bit dubious. This is unlike duk_push_string() which pushes a * 'null' if the input string is a NULL. */ - if (!str) { - len = 0; + if (DUK_UNLIKELY(str == NULL)) { + len = 0U; } - /* Check for maximum string length */ + /* Check for maximum string length. */ if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) { DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG); + DUK_WO_NORETURN(return NULL;); } h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len); @@ -21409,6 +22012,42 @@ DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) { } } +#if !defined(DUK_USE_PREFER_SIZE) +#if defined(DUK_USE_LITCACHE_SIZE) +DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) { + duk_hstring *h; + duk_tval *tv_slot; + + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(str != NULL); + DUK_ASSERT(str[len] == (char) 0); + + /* Check for maximum string length. */ + if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) { + DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG); + DUK_WO_NORETURN(return NULL;); + } + + h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len); + DUK_ASSERT(h != NULL); + + tv_slot = thr->valstack_top++; + DUK_TVAL_SET_STRING(tv_slot, h); + DUK_HSTRING_INCREF(thr, h); /* no side effects */ + + return (const char *) DUK_HSTRING_GET_DATA(h); +} +#else /* DUK_USE_LITCACHE_SIZE */ +DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) { + DUK_ASSERT_API_ENTRY(thr); + DUK_ASSERT(str != NULL); + DUK_ASSERT(str[len] == (char) 0); + + return duk_push_lstring(thr, str, len); +} +#endif /* DUK_USE_LITCACHE_SIZE */ +#endif /* !DUK_USE_PREFER_SIZE */ + DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) { duk_tval *tv_slot; @@ -21462,6 +22101,7 @@ DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_ob type_error: DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_push_this(duk_hthread *thr) { @@ -21505,6 +22145,46 @@ DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) { return thr->valstack_bottom - 1; } +DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) { + duk_activation *act; + + DUK_ASSERT_API_ENTRY(thr); + + /* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation + * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget + * + * No newTarget support now, so as a first approximation + * use the resolved (non-bound) target function. + * + * Check CONSTRUCT flag from current function, or if running + * direct eval, from a non-direct-eval parent (with possibly + * more than one nested direct eval). An alternative to this + * would be to store [[NewTarget]] as a hidden symbol of the + * lexical scope, and then just look up that variable. + * + * Calls from the application will either be for an empty + * call stack, or a Duktape/C function as the top activation. + */ + + act = thr->callstack_curr; + for (;;) { + if (act == NULL) { + break; + } + + if (act->flags & DUK_ACT_FLAG_CONSTRUCT) { + duk_push_tval(thr, &act->tv_func); + return; + } else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) { + act = act->parent; + } else { + break; + } + } + + duk_push_undefined(thr); +} + DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) { duk_activation *act; @@ -21565,7 +22245,7 @@ DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_th DUK_ASSERT_API_ENTRY(thr); if (DUK_UNLIKELY(target_thr == NULL)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); - return; /* not reached */ + DUK_WO_NORETURN(return;); } duk_push_hobject(thr, (duk_hobject *) target_thr); duk__push_stash(thr); @@ -21641,6 +22321,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va sz = sz * 2; if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) { DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG); + DUK_WO_NORETURN(return NULL;); } } @@ -21829,6 +22510,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) { /* important to do this *after* pushing, to make the thread reachable for gc */ if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return 0;); } /* initialize built-ins - either by copying or creating new ones */ @@ -21870,6 +22552,7 @@ DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) { DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION)); if (DUK_UNLIKELY(obj == NULL)) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags)); @@ -21901,6 +22584,7 @@ DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) { DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION)); if (!obj) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } tv_slot = thr->valstack_top++; @@ -21957,7 +22641,7 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function fu api_error: DUK_ERROR_TYPE_INVALID_ARGS(thr); - return 0; /* not reached */ + DUK_WO_NORETURN(return 0;); } DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) { @@ -22049,7 +22733,7 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function fun api_error: DUK_ERROR_TYPE_INVALID_ARGS(thr); - return 0; /* not reached */ + DUK_WO_NORETURN(return 0;); } #if defined(DUK_USE_BUFFEROBJECT_SUPPORT) @@ -22201,11 +22885,11 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, range_error: DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS); - return; /* not reached */ + DUK_WO_NORETURN(return;); arg_error: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS); - return; /* not reached */ + DUK_WO_NORETURN(return;); } #else /* DUK_USE_BUFFEROBJECT_SUPPORT */ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) { @@ -22215,6 +22899,7 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, DUK_UNREF(byte_length); DUK_UNREF(flags); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ @@ -22252,7 +22937,7 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcod duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC); } else { /* If no explicit message given, put error code into message field - * (as a number). This is not fully in keeping with the Ecmascript + * (as a number). This is not fully in keeping with the ECMAScript * error model because messages are supposed to be strings (Error * constructors use ToString() on their argument). However, it's * probably more useful than having a separate 'code' property. @@ -22314,11 +22999,13 @@ DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_sm /* Check for maximum buffer length. */ if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) { DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG); + DUK_WO_NORETURN(return NULL;); } h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data); if (DUK_UNLIKELY(h == NULL)) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } tv_slot = thr->valstack_top; @@ -22340,11 +23027,12 @@ DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) DUK_ASSERT_API_ENTRY(thr); ptr = duk_push_buffer_raw(thr, len, 0); + DUK_ASSERT(ptr != NULL); #if !defined(DUK_USE_ZERO_BUFFER_DATA) /* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA * is not set. */ - DUK_MEMZERO((void *) ptr, (size_t) len); + duk_memzero((void *) ptr, (size_t) len); #endif return ptr; } @@ -22441,12 +23129,14 @@ DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) fail_args: DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return 0;); } #else /* DUK_USE_ES6_PROXY */ DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) { DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(proxy_flags); DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return 0;); } #endif /* DUK_USE_ES6_PROXY */ @@ -22744,7 +23434,7 @@ DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) { if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) { DUK_ERROR_RANGE_INVALID_COUNT(thr); - return; + DUK_WO_NORETURN(return;); } DUK_ASSERT(count >= 0); @@ -22832,6 +23522,7 @@ DUK_EXTERNAL void duk_pop(duk_hthread *thr) { DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) { DUK_ERROR_RANGE_INVALID_COUNT(thr); + DUK_WO_NORETURN(return;); } duk__pop_unsafe_raw(thr); @@ -22920,6 +23611,7 @@ DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) { DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) { DUK_ERROR_RANGE_INVALID_COUNT(thr); + DUK_WO_NORETURN(return;); } duk__pop_2_unsafe_raw(thr); @@ -22977,7 +23669,7 @@ DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) { if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) { /* Also handles negative count. */ DUK_ERROR_RANGE_INVALID_COUNT(thr); - return; + DUK_WO_NORETURN(return;); } DUK_ASSERT(count >= 0); @@ -22994,9 +23686,8 @@ DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) { /* Copy value stack values directly to the array part without * any refcount updates: net refcount changes are zero. */ - tv_src = thr->valstack_top - count - 1; - DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval)); + duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval)); /* Overwrite result array to final value stack location and wipe * the rest; no refcount operations needed. @@ -23114,11 +23805,11 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) { } DUK_ERROR_TYPE_INVALID_ARGS(thr); - return 0; + DUK_WO_NORETURN(return 0;); fail_over_2g: DUK_ERROR_RANGE_INVALID_LENGTH(thr); - return 0; + DUK_WO_NORETURN(return 0;); } /* @@ -23135,6 +23826,7 @@ DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) { if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return;); } /* Errors are augmented when they are created, not when they are @@ -23198,6 +23890,7 @@ DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, con duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap); (void) duk_throw(thr); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) { @@ -23209,6 +23902,7 @@ DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap); va_end(ap); (void) duk_throw(thr); + DUK_WO_NORETURN(return;); } #if !defined(DUK_USE_VARIADIC_MACROS) @@ -23227,6 +23921,7 @@ DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_c duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap); (void) duk_throw(thr); + DUK_WO_NORETURN(return;); } #define DUK__ERROR_STASH_SHARED(code) do { \ @@ -23234,7 +23929,7 @@ DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_c va_start(ap, fmt); \ duk__throw_error_from_stash(thr, (code), fmt, ap); \ va_end(ap); \ - /* Never reached; if return 0 here, gcc/clang will complain. */ \ + DUK_WO_NORETURN(return 0;); \ } while (0) DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) { @@ -23364,7 +24059,7 @@ DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function f DUK_ASSERT_API_ENTRY(thr); - duk_push_sprintf(thr, "light_"); + duk_push_literal(thr, "light_"); duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func)); duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags); duk_concat(thr, 3); @@ -23389,9 +24084,9 @@ DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) { DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv)); DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); /* read before 'tv' potentially invalidated */ - duk_push_string(thr, "function "); + duk_push_literal(thr, "function "); duk_push_lightfunc_name_raw(thr, func, lf_flags); - duk_push_string(thr, "() { [lightfunc code] }"); + duk_push_literal(thr, "() { [lightfunc code] }"); duk_concat(thr, 3); } @@ -23503,7 +24198,7 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval /* 'tv' may be NULL */ if (tv == NULL) { - duk_push_string(thr, "none"); + duk_push_literal(thr, "none"); } else { switch (DUK_TVAL_GET_TAG(tv)) { case DUK_TAG_STRING: { @@ -23512,11 +24207,11 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval /* XXX: string summary produces question marks * so this is not very ideal. */ - duk_push_string(thr, "[Symbol "); + duk_push_literal(thr, "[Symbol "); duk_push_string(thr, duk__get_symbol_type_string(h)); - duk_push_string(thr, " "); + duk_push_literal(thr, " "); duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS); - duk_push_string(thr, "]"); + duk_push_literal(thr, "]"); duk_concat(thr, 5); break; } @@ -23546,7 +24241,7 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval break; } } - duk_push_class_string_tval(thr, tv); + duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/); break; } case DUK_TAG_BUFFER: { @@ -23601,7 +24296,7 @@ DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstri DUK_ASSERT_API_ENTRY(thr); /* .toString() */ - duk_push_string(thr, "Symbol("); + duk_push_literal(thr, "Symbol("); p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h); p_end = p + DUK_HSTRING_GET_BYTELEN(h); DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80); @@ -23617,7 +24312,7 @@ DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstri } } duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p)); - duk_push_string(thr, ")"); + duk_push_literal(thr, ")"); duk_concat(thr, 3); } @@ -23653,7 +24348,8 @@ DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_ DUK_ASSERT_API_ENTRY(thr); DUK_UNREF(thr); DUK_ASSERT(count * sizeof(duk_tval) >= count); /* no wrap */ - DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval)); + + duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval)); tv = tv_dst; while (count-- > 0) { @@ -23689,7 +24385,7 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, if (DUK_UNLIKELY(count_in <= 0)) { if (count_in < 0) { DUK_ERROR_RANGE_INVALID_COUNT(thr); - return; + DUK_WO_NORETURN(return;); } DUK_ASSERT(count_in == 0); duk_push_hstring_empty(thr); @@ -23745,11 +24441,11 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, for (i = count; i >= 1; i--) { if (is_join && i != count) { h = duk_require_hstring(thr, -((duk_idx_t) count) - 2); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); + duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); idx += DUK_HSTRING_GET_BYTELEN(h); } h = duk_require_hstring(thr, -((duk_idx_t) i) - 1); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); + duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); idx += DUK_HSTRING_GET_BYTELEN(h); } @@ -23776,6 +24472,7 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, error_overflow: DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG); + DUK_WO_NORETURN(return;); } DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) { @@ -23813,8 +24510,8 @@ DUK_INTERNAL void duk_concat_2(duk_hthread *thr) { buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len); DUK_ASSERT(buf != NULL); - DUK_MEMCPY((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1); - DUK_MEMCPY((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2); + duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1); + duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2); (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */ /* [ ... str1 str2 buf ] */ @@ -23825,6 +24522,7 @@ DUK_INTERNAL void duk_concat_2(duk_hthread *thr) { error_overflow: DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG); + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_PREFER_SIZE */ @@ -24053,7 +24751,7 @@ DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, d /* #include duk_internal.h -> already included */ DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) { - /* Ecmascript time, with millisecond fractions. Exposed via + /* ECMAScript time, with millisecond fractions. Exposed via * duk_get_now() for example. */ DUK_UNREF(thr); @@ -24061,7 +24759,7 @@ DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) { } DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) { - /* Ecmascript time without millisecond fractions. Exposed via + /* ECMAScript time without millisecond fractions. Exposed via * the Date built-in which doesn't allow fractions. */ DUK_UNREF(thr); @@ -24104,7 +24802,7 @@ DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, DUK_UNREF(thr); /* Convert as one-based, but change month to zero-based to match the - * Ecmascript Date built-in behavior 1:1. + * ECMAScript Date built-in behavior 1:1. */ flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO; @@ -24159,9 +24857,9 @@ DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_comp /* * Array built-ins * - * Most Array built-ins are intentionally generic in Ecmascript, and are + * Most Array built-ins are intentionally generic in ECMAScript, and are * intended to work even when the 'this' binding is not an Array instance. - * This Ecmascript feature is also used by much real world code. For this + * This ECMAScript feature is also used by much real world code. For this * reason the implementations here don't assume exotic Array behavior or * e.g. presence of a .length property. However, some algorithms have a * fast path for duk_harray backed actual Array instances, enabled when @@ -24235,6 +24933,7 @@ DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) { duk_uint32_t ret = duk__push_this_obj_len_u32(thr); if (DUK_UNLIKELY(ret >= 0x80000000UL)) { DUK_ERROR_RANGE_INVALID_LENGTH(thr); + DUK_WO_NORETURN(return 0U;); } return ret; } @@ -24387,11 +25086,17 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) { DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) { duk_idx_t i, n; - duk_uarridx_t idx, idx_last; - duk_uarridx_t j, len; + duk_uint32_t j, idx, len; duk_hobject *h; + duk_size_t tmp_len; + + /* XXX: In ES2015 Array .length can be up to 2^53-1. The current + * implementation is limited to 2^32-1. + */ - /* XXX: the insert here is a bit expensive if there are a lot of items. + /* XXX: Fast path for array 'this' and array element. */ + + /* XXX: The insert here is a bit expensive if there are a lot of items. * It could also be special cased in the outermost for loop quite easily * (as the element is dup()'d anyway). */ @@ -24409,59 +25114,97 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) { */ idx = 0; - idx_last = 0; for (i = 0; i < n; i++) { + duk_bool_t spreadable; + duk_bool_t need_has_check; + DUK_ASSERT_TOP(thr, n + 1); /* [ ToObject(this) item1 ... itemN arr ] */ - duk_dup(thr, i); - h = duk_get_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_ARRAY); - if (!h) { - duk_xdef_prop_index_wec(thr, -2, idx++); - idx_last = idx; + h = duk_get_hobject(thr, i); + + if (h == NULL) { + spreadable = 0; + } else { +#if defined(DUK_USE_SYMBOL_BUILTIN) + duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE); + if (duk_is_undefined(thr, -1)) { + spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY); + } else { + spreadable = duk_to_boolean(thr, -1); + } + duk_pop_nodecref_unsafe(thr); +#else + spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY); +#endif + } + + if (!spreadable) { + duk_dup(thr, i); + duk_xdef_prop_index_wec(thr, -2, idx); + idx++; + if (DUK_UNLIKELY(idx == 0U)) { + /* Index after update is 0, and index written + * was 0xffffffffUL which is no longer a valid + * array index. + */ + goto fail_wrap; + } continue; } - /* [ ToObject(this) item1 ... itemN arr item(i) ] */ + DUK_ASSERT(duk_is_object(thr, i)); + need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0); /* Always 0 w/o Proxy support. */ - /* XXX: an array can have length higher than 32 bits; this is not handled - * correctly now. - */ - len = (duk_uarridx_t) duk_get_length(thr, -1); + /* [ ToObject(this) item1 ... itemN arr ] */ + + tmp_len = duk_get_length(thr, i); + len = (duk_uint32_t) tmp_len; + if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) { + goto fail_wrap; + } + if (DUK_UNLIKELY(idx + len < idx)) { + /* Result length must be at most 0xffffffffUL to be + * a valid 32-bit array index. + */ + goto fail_wrap; + } for (j = 0; j < len; j++) { - if (duk_get_prop_index(thr, -1, j)) { - /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */ - duk_xdef_prop_index_wec(thr, -3, idx++); - idx_last = idx; + /* For a Proxy element, an explicit 'has' check is + * needed to allow the Proxy to present gaps. + */ + if (need_has_check) { + if (duk_has_prop_index(thr, i, j)) { + duk_get_prop_index(thr, i, j); + duk_xdef_prop_index_wec(thr, -2, idx); + } } else { - idx++; - duk_pop_undefined(thr); -#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER) - /* According to E5.1 Section 15.4.4.4 nonexistent trailing - * elements do not affect 'length' of the result. Test262 - * and other engines disagree, so update idx_last here too. - */ - idx_last = idx; -#else - /* Strict standard behavior, ignore trailing elements for - * result 'length'. - */ -#endif + if (duk_get_prop_index(thr, i, j)) { + duk_xdef_prop_index_wec(thr, -2, idx); + } else { + duk_pop_undefined(thr); + } } + idx++; + DUK_ASSERT(idx != 0U); /* Wrap check above. */ } - duk_pop_unsafe(thr); } - /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly - * in the end, but because we're operating with an internal value which - * is known to be an array, this should be equivalent. + /* ES5.1 has a specification "bug" in that nonexistent trailing + * elements don't affect the result .length. Test262 and other + * engines disagree, and the specification bug was fixed in ES2015 + * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat). */ - duk_push_uarridx(thr, idx_last); + duk_push_uarridx(thr, idx); duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); DUK_ASSERT_TOP(thr, n + 1); return 1; + + fail_wrap: + DUK_ERROR_RANGE_INVALID_LENGTH(thr); + DUK_WO_NORETURN(return 0;); } /* @@ -25583,20 +26326,12 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) { DUK_ASSERT_TOP(thr, 5); if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) { -#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER) - /* Real world behavior for map(): trailing non-existent - * elements don't invoke the user callback, but are still - * counted towards result 'length'. + /* For 'map' trailing missing elements don't invoke the + * callback but count towards the result length. */ if (iter_type == DUK__ITER_MAP) { res_length = i + 1; } -#else - /* Standard behavior for map(): trailing non-existent - * elements don't invoke the user callback and are not - * counted towards result 'length'. - */ -#endif duk_pop_undefined(thr); continue; } @@ -26021,6 +26756,7 @@ DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_u if (flags & DUK__BUFOBJ_FLAG_THROW) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER); + DUK_WO_NORETURN(return NULL;); } return NULL; } @@ -26062,7 +26798,7 @@ DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx } DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER); - return NULL; /* not reachable */ + DUK_WO_NORETURN(return NULL;); } DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) { @@ -26137,6 +26873,7 @@ DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr, fail_range: DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS); + DUK_WO_NORETURN(return;); } /* Shared lenient buffer length clamping helper. No negative indices, no @@ -26287,7 +27024,8 @@ DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_h DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) { duk_double_union du; - DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size); + DUK_ASSERT(elem_size > 0); + duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size); switch (h_bufobj->elem_type) { case DUK_HBUFOBJ_ELEM_UINT8: @@ -26355,7 +27093,11 @@ DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_b du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1); break; case DUK_HBUFOBJ_ELEM_FLOAT32: - du.f[0] = (duk_float_t) duk_to_number_m1(thr); + /* A double-to-float cast is undefined behavior in C99 if + * the cast is out-of-range, so use a helper. Example: + * runtime error: value -1e+100 is outside the range of representable values of type 'float' + */ + du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr)); break; case DUK_HBUFOBJ_ELEM_FLOAT64: du.d = (duk_double_t) duk_to_number_m1(thr); @@ -26364,7 +27106,8 @@ DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_b DUK_UNREACHABLE(); } - DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size); + DUK_ASSERT(elem_size > 0); + duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size); } /* Helper to create a fixed buffer from argument value at index 0. @@ -26400,12 +27143,14 @@ DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) { h_bufobj = (duk_hbufobj *) h; if (DUK_UNLIKELY(h_bufobj->buf == NULL)) { DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return NULL;); } if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) { /* No support for ArrayBuffers with slice * offset/length. */ DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return NULL;); } duk_push_hbuffer(thr, h_bufobj->buf); return h_bufobj->buf; @@ -26421,6 +27166,7 @@ DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) { } default: DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return NULL;); } done: @@ -26462,7 +27208,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) { duk_push_buffer_object(thr, -1, 0, - DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) h_buf), + DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf), DUK_BUFOBJ_UINT8ARRAY); duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE); duk_set_prototype(thr, -2); @@ -26790,7 +27536,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) { 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); + duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length); break; } case 1: { @@ -27026,7 +27772,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) { h_this = duk__get_bufobj_this(thr); if (h_this == NULL) { /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */ - duk_push_string(thr, "[object Object]"); + duk_push_literal(thr, "[object Object]"); return 1; } DUK_ASSERT_HBUFOBJ_VALID(h_this); @@ -27057,9 +27803,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) { */ DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)); - DUK_MEMCPY((void *) buf_slice, - (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset), - (size_t) slice_length); + duk_memcpy_unsafe((void *) buf_slice, + (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset), + (size_t) slice_length); /* Use the equivalent of: new TextEncoder().encode(this) to convert the * string. Result will be valid UTF-8; non-CESU-8 inputs are currently @@ -27221,7 +27967,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) { /* 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); + duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length); } else if (fill_str_len > 1) { duk_size_t i, n, t; @@ -27272,9 +28018,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) { if (DUK_HBUFOBJ_VALID_SLICE(h_this)) { /* Cannot overlap. */ - DUK_MEMCPY((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset), - (const void *) str_data, - (size_t) length); + duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_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")); } @@ -27370,9 +28116,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) { /* Must use memmove() because copy area may overlap (source and target * buffer may be the same, or from different slices. */ - DUK_MEMMOVE((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart), - (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart), - (size_t) copy_size); + duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart), + (const void *) (DUK_HBUFOBJ_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")); } @@ -27558,7 +28304,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) { 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); + duk_memmove_unsafe((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")); @@ -27601,7 +28347,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) { DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source")); p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length); DUK_ASSERT(p_src_copy != NULL); - DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length); + duk_memcpy_unsafe((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 */ } @@ -27728,9 +28474,9 @@ DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val DUK_ASSERT(p_copy != NULL); copy_length = slice_length; - DUK_MEMCPY((void *) p_copy, - (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset), - copy_length); + duk_memcpy_unsafe((void *) p_copy, + (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset), + copy_length); } #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ @@ -27852,9 +28598,9 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) { * is left as zero. */ copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length); - DUK_MEMCPY((void *) p_copy, - (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset), - copy_length); + duk_memcpy_unsafe((void *) p_copy, + (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset), + copy_length); h_val = duk_known_hbuffer(thr, -1); @@ -28046,9 +28792,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) { if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) { - DUK_MEMCPY((void *) p, - (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj), - copy_size); + duk_memcpy_unsafe((void *) p, + (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj), + copy_size); } else { /* Just skip, leaving zeroes in the result. */ ; @@ -28198,7 +28944,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) { if (offset + 2U > check_length) { goto fail_bounds; } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2); + duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2); tmp = du.us[0]; if (endswap) { tmp = DUK_BSWAP16(tmp); @@ -28215,7 +28961,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) { if (offset + 4U > check_length) { goto fail_bounds; } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); + duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4); tmp = du.ui[0]; if (endswap) { tmp = DUK_BSWAP32(tmp); @@ -28232,7 +28978,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) { if (offset + 4U > check_length) { goto fail_bounds; } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); + duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4); if (endswap) { tmp = du.ui[0]; tmp = DUK_BSWAP32(tmp); @@ -28245,7 +28991,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) { if (offset + 8U > check_length) { goto fail_bounds; } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8); + duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8); if (endswap) { DUK_DBLUNION_BSWAP64(&du); } @@ -28302,9 +29048,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) { } while (i != i_end); if (magic_signed) { - /* Shift to sign extend. */ + /* Shift to sign extend. Left shift must be unsigned + * to avoid undefined behavior; right shift must be + * signed to sign extend properly. + */ shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U); - tmp = (tmp << shift_tmp) >> shift_tmp; + tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp; } duk_push_i64(thr, tmp); @@ -28480,7 +29229,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) { } du.us[0] = tmp; /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2); + duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2); break; } case DUK__FLD_32BIT: { @@ -28494,7 +29243,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) { } du.ui[0] = tmp; /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); + duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4); break; } case DUK__FLD_FLOAT: { @@ -28509,7 +29258,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) { du.ui[0] = tmp; } /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); + duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4); break; } case DUK__FLD_DOUBLE: { @@ -28521,7 +29270,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) { DUK_DBLUNION_BSWAP64(&du); } /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8); + duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8); break; } case DUK__FLD_VARINT: { @@ -28967,7 +29716,7 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch duk_small_uint_t i; /* During parsing, month and day are one-based; set defaults here. */ - DUK_MEMZERO(parts, sizeof(parts)); + duk_memzero(parts, sizeof(parts)); 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; @@ -29194,13 +29943,13 @@ DUK_LOCAL duk_uint8_t duk__days_in_month[12] = { }; /* Maximum iteration count for computing UTC-to-local time offset when - * creating an Ecmascript time value from local parts. + * creating an ECMAScript time value from local parts. */ #define DUK__LOCAL_TZOFFSET_MAXITER 4 /* Because 'day since epoch' can be negative and is used to compute weekday * using a modulo operation, add this multiple of 7 to avoid negative values - * when year is below 1970 epoch. Ecmascript time values are restricted to + * when year is below 1970 epoch. ECMAScript time values are restricted to * +/- 100 million days from epoch, so this adder fits nicely into 32 bits. * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin. */ @@ -29391,10 +30140,10 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, d = DUK_FLOOR(d); /* remove fractions if present */ DUK_ASSERT(DUK_FLOOR(d) == d); - /* The timevalue must be in valid Ecmascript range, but since a local + /* The timevalue must be in valid ECMAScript range, but since a local * time offset can be applied, we need to allow a +/- 24h leeway to * the value. In other words, although the UTC time is within the - * Ecmascript range, the local part values can be just outside of it. + * ECMAScript range, the local part values can be just outside of it. */ DUK_UNREF(duk_bi_date_timeval_in_leeway_range); DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d)); @@ -29437,7 +30186,7 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, (long) parts[DUK_DATE_IDX_MILLISECOND])); /* This assert depends on the input parts representing time inside - * the Ecmascript range. + * the ECMAScript range. */ DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0); parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */ @@ -29557,7 +30306,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dpar * computation happens with intermediate results coerced to * double values (instead of using something more accurate). * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754 - * rules (= Ecmascript '+' and '*' operators). + * rules (= ECMAScript '+' and '*' operators). * * Without 'volatile' even this approach fails on some platform * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu @@ -29664,6 +30413,7 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk h = duk_get_hobject(thr, -1); /* XXX: getter with class check, useful in built-ins */ if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) { DUK_ERROR_TYPE(thr, "expected Date"); + DUK_WO_NORETURN(return 0.0;); } duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE); @@ -29676,6 +30426,7 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk } if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) { DUK_ERROR_RANGE(thr, "Invalid Date"); + DUK_WO_NORETURN(return 0.0;); } } /* if no NaN handling flag, may still be NaN here, but not Inf */ @@ -30292,7 +31043,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) { * Notes: * * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are - * required to be the same Ecmascript function object (!), so it is + * required to be the same ECMAScript function object (!), so it is * omitted from here. * * - Date.prototype.toUTCString(): E5.1 specification does not require a @@ -30488,6 +31239,41 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) { return 1; } +/* + * Misc. + */ + +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) { + duk_size_t hintlen; + const char *hintstr; + duk_int_t hint; + + /* Invokes OrdinaryToPrimitive() with suitable hint. Note that the + * method is generic, and works on non-Date arguments too. + * + * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive + */ + + duk_push_this(thr); + duk_require_object(thr, -1); + DUK_ASSERT_TOP(thr, 2); + + hintstr = duk_require_lstring(thr, 0, &hintlen); + if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) || + (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) { + hint = DUK_HINT_STRING; + } else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) { + hint = DUK_HINT_NUMBER; + } else { + DUK_DCERROR_TYPE_INVALID_ARGS(thr); + } + + duk_to_primitive_ordinary(thr, -1, hint); + return 1; +} +#endif /* DUK_USE_SYMBOL_BUILTIN */ + #endif /* DUK_USE_DATE_BUILTIN */ /* automatic undefs */ @@ -30555,7 +31341,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) { #define DUK__STRFTIME_BUF_SIZE 64 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY) -/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */ +/* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */ DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) { struct timeval tv; duk_double_t d; @@ -30603,7 +31389,7 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { return 0; } - /* If not within Ecmascript range, some integer time calculations + /* 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 @@ -30654,10 +31440,10 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { * 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 + * 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. + * full ECMAScript range. * * The following has useful discussion and links: * @@ -30672,7 +31458,7 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { t = (time_t) (d / 1000.0); DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t)); - DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2); + duk_memzero((void *) tms, sizeof(struct tm) * 2); #if defined(DUK_USE_DATE_TZO_GMTIME_R) (void) gmtime_r(&t, &tms[0]); @@ -30682,9 +31468,9 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { (void) localtime_s(&t, &tms[1]); #elif defined(DUK_USE_DATE_TZO_GMTIME) tm_ptr = gmtime(&t); - DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm)); + duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm)); tm_ptr = localtime(&t); - DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm)); + duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm)); #else #error internal error #endif @@ -30745,13 +31531,13 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, cons /* Copy to buffer with slack to avoid Valgrind gripes from strptime. */ DUK_ASSERT(str != NULL); - DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */ + 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)); + 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}", @@ -30782,7 +31568,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const * convenient for an embeddable interpreter. */ - DUK_MEMZERO(&tm, sizeof(struct tm)); + duk_memzero(&tm, sizeof(struct tm)); rc = (duk_small_int_t) getdate_r(str, &tm); DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc)); @@ -30807,16 +31593,16 @@ DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_ DUK_UNREF(tzoffset); - /* If the platform doesn't support the entire Ecmascript range, we need + /* 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 + * 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). + * 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)) { @@ -30824,7 +31610,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_ return 0; } - DUK_MEMZERO(&tm, sizeof(tm)); + 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]; @@ -30834,7 +31620,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_ tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY]; tm.tm_isdst = 0; - DUK_MEMZERO(buf, sizeof(buf)); + 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) { @@ -30892,13 +31678,15 @@ DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEG } } +#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS) DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) { res->LowPart = ft->dwLowDateTime; res->HighPart = ft->dwHighDateTime; } +#endif /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */ DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) { - DUK_MEMZERO((void *) st, sizeof(*st)); + duk_memzero((void *) st, sizeof(*st)); st->wYear = 1970; st->wMonth = 1; st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */ @@ -30963,10 +31751,11 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) { ULARGE_INTEGER tmp2; ULARGE_INTEGER tmp3; FILETIME ft1; + BOOL ret; /* XXX: handling of timestamps outside Windows supported range. * How does Windows deal with dates before 1600? Does windows - * support all Ecmascript years (like -200000 and +200000)? + * 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). */ @@ -30982,7 +31771,11 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) { ft1.dwLowDateTime = tmp2.LowPart; ft1.dwHighDateTime = tmp2.HighPart; - FileTimeToSystemTime((const FILETIME *) &ft1, &st2); + ret = FileTimeToSystemTime((const FILETIME *) &ft1, &st2); + if (!ret) { + DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0")); + return 0; + } if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) { DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0")); return 0; @@ -31002,6 +31795,7 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_ FILETIME ft2; ULARGE_INTEGER tmp1; ULARGE_INTEGER tmp2; + BOOL ret; /* Do a similar computation to duk_bi_date_get_local_tzoffset_windows * but without accounting for daylight savings time. Use this on @@ -31017,9 +31811,17 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_ ft1.dwLowDateTime = tmp1.LowPart; ft1.dwHighDateTime = tmp1.HighPart; - FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2); + ret = FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2); + if (!ret) { + DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0")); + return 0; + } - FileTimeToSystemTime((const FILETIME *) &ft2, &st2); + ret = FileTimeToSystemTime((const FILETIME *) &ft2, &st2); + if (!ret) { + DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0")); + return 0; + } duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2); return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */ @@ -31055,7 +31857,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) { * * Size optimization note: it might seem that vararg multipurpose functions * like fin(), enc(), and dec() are not very size optimal, but using a single - * user-visible Ecmascript function saves a lot of run-time footprint; each + * user-visible ECMAScript function saves a lot of run-time footprint; each * Function instance takes >100 bytes. Using a shared native helper and a * 'magic' value won't save much if there are multiple Function instances * anyway. @@ -31449,7 +32251,7 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER | DUK_TYPE_MASK_OBJECT); - if (duk_get_prop_string(thr, 1, "stream")) { + if (duk_get_prop_literal(thr, 1, "stream")) { stream = duk_to_boolean(thr, -1); } } @@ -31464,6 +32266,7 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de */ if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) { DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG); + DUK_WO_NORETURN(return 0;); } output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len)); /* used parts will be always manually written over */ @@ -31541,7 +32344,7 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de fail_type: DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return 0;); } /* @@ -31559,7 +32362,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) { } DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) { - duk_push_string(thr, "utf-8"); + duk_push_literal(thr, "utf-8"); return 1; } @@ -31581,6 +32384,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) { len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input); if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) { DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG); + DUK_WO_NORETURN(return 0;); } } @@ -31600,14 +32404,14 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) { DUK_ASSERT(duk_is_string(thr, 0)); /* True if len > 0. */ /* XXX: duk_decode_string() is used to process the input - * string. For standard Ecmascript strings, represented + * string. For standard ECMAScript strings, represented * internally as CESU-8, this is fine. However, behavior * beyond CESU-8 is not very strict: codepoints using an * extended form of UTF-8 are also accepted, and invalid * codepoint sequences (which are allowed in Duktape strings) * are not handled as well as they could (e.g. invalid * continuation bytes may mask following codepoints). - * This is how Ecmascript code would also see such strings. + * This is how ECMAScript code would also see such strings. * Maybe replace duk_decode_string() with an explicit strict * CESU-8 decoder here? */ @@ -31635,7 +32439,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) { /* Standard WHATWG output is a Uint8Array. Here the Uint8Array will * be backed by a dynamic buffer which differs from e.g. Uint8Arrays - * created as 'new Uint8Array(N)'. Ecmascript code won't see the + * created as 'new Uint8Array(N)'. ECMAScript code won't see the * difference but C code will. When bufferobjects are not supported, * returns a plain dynamic buffer. */ @@ -31657,10 +32461,10 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) { duk_to_string(thr, 0); } if (!duk_is_null_or_undefined(thr, 1)) { - if (duk_get_prop_string(thr, 1, "fatal")) { + if (duk_get_prop_literal(thr, 1, "fatal")) { fatal = duk_to_boolean(thr, -1); } - if (duk_get_prop_string(thr, 1, "ignoreBOM")) { + if (duk_get_prop_literal(thr, 1, "ignoreBOM")) { ignore_bom = duk_to_boolean(thr, -1); } } @@ -31675,7 +32479,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) { dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom; duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */ - duk_put_prop_string(thr, -2, DUK_INTERNAL_SYMBOL("Context")); + duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context")); return 0; } @@ -31683,7 +32487,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) { DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) { duk__decode_context *dec_ctx; duk_push_this(thr); - duk_get_prop_string(thr, -1, DUK_INTERNAL_SYMBOL("Context")); + duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context")); dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL); DUK_ASSERT(dec_ctx != NULL); return dec_ctx; @@ -31700,7 +32504,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *t /* Encoding is now fixed, so _Context lookup is only needed to * validate the 'this' binding (TypeError if not TextDecoder-like). */ - duk_push_string(thr, "utf-8"); + duk_push_literal(thr, "utf-8"); break; case 1: duk_push_boolean(thr, dec_ctx->fatal); @@ -31800,7 +32604,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) { duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME); if (duk_is_undefined(thr, -1)) { duk_pop(thr); - duk_push_string(thr, "Error"); + duk_push_literal(thr, "Error"); } else { duk_to_string(thr, -1); } @@ -31830,7 +32634,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) { duk_pop(thr); return 1; } - duk_push_string(thr, ": "); + duk_push_literal(thr, ": "); duk_insert(thr, -2); /* ... name ': ' message */ duk_concat(thr, 3); @@ -31899,13 +32703,13 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i); duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1)); d = duk_to_number_m1(thr); - pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32); - flags = (duk_uint_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32); + pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32)); + flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32)); t = (duk_small_int_t) duk_get_type(thr, -2); if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) { /* - * Ecmascript/native function call or lightfunc call + * ECMAScript/native function call or lightfunc call */ count_func++; @@ -32174,7 +32978,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) { duk_push_hstring_empty(thr); } else { duk_insert(thr, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */ - duk_push_string(thr, ","); + duk_push_literal(thr, ","); duk_insert(thr, 1); duk_join(thr, nargs - 1); } @@ -32186,11 +32990,11 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) { /* XXX: this placeholder is not always correct, but use for now. * It will fail in corner cases; see test-dev-func-cons-args.js. */ - duk_push_string(thr, "function("); + duk_push_literal(thr, "function("); duk_dup_1(thr); - duk_push_string(thr, "){"); + duk_push_literal(thr, "){"); duk_dup_0(thr); - duk_push_string(thr, "\n}"); /* Newline is important to handle trailing // comment. */ + duk_push_literal(thr, "\n}"); /* Newline is important to handle trailing // comment. */ duk_concat(thr, 5); /* [ body formals source ] */ @@ -32208,7 +33012,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) { comp_flags); /* Force .name to 'anonymous' (ES2015). */ - duk_push_string(thr, "anonymous"); + duk_push_literal(thr, "anonymous"); duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C); func = (duk_hcompfunc *) duk_known_hobject(thr, -1); @@ -32420,7 +33224,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) { if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) { duk_hboundfunc *h_boundtarget; - h_boundtarget = (duk_hboundfunc *) h_target; + h_boundtarget = (duk_hboundfunc *) (void *) h_target; /* The final function should always be non-bound, unless * there's a bug in the internals. Assert for it. @@ -32454,7 +33258,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) { DUK_DCERROR_RANGE_INVALID_COUNT(thr); } tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval)); - DUK_ASSERT(tv_res != NULL); + DUK_ASSERT(tv_res != NULL || bound_nargs == 0); DUK_ASSERT(h_bound->args == NULL); DUK_ASSERT(h_bound->nargs == 0); h_bound->args = tv_res; @@ -32494,7 +33298,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) { duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS); /* Function name and fileName (non-standard). */ - duk_push_string(thr, "bound "); /* ES2015 19.2.3.2. */ + duk_push_literal(thr, "bound "); /* ES2015 19.2.3.2. */ duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME); if (!duk_is_string_notsymbol(thr, -1)) { /* ES2015 has requirement to check that .name of target is a string @@ -32578,6 +33382,17 @@ DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) { fail_type: DUK_DCERROR_TYPE_INVALID_ARGS(thr); } + +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) { + /* This binding: RHS, stack index 0: LHS. */ + duk_bool_t ret; + + ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr)); + duk_push_boolean(thr, ret); + return 1; +} +#endif /* DUK_USE_SYMBOL_BUILTIN */ /* * Global object built-ins */ @@ -32780,6 +33595,7 @@ DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ct uri_error: DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) { @@ -32918,6 +33734,7 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct uri_error: DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT); + DUK_WO_NORETURN(return;); } #if defined(DUK_USE_SECTION_B) @@ -32958,6 +33775,7 @@ DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, c esc_error: DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) { @@ -32990,7 +33808,7 @@ DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, * Eval needs to handle both a "direct eval" and an "indirect eval". * Direct eval handling needs access to the caller's activation so that its * lexical environment can be accessed. A direct eval is only possible from - * Ecmascript code; an indirect eval call is possible also from C code. + * ECMAScript code; an indirect eval call is possible also from C code. * When an indirect eval call is made from C code, there may not be a * calling activation at all which needs careful handling. */ @@ -33029,7 +33847,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) { #if defined(DUK_USE_DEBUGGER_SUPPORT) /* NOTE: level is used only by the debugger and should never be present - * for an Ecmascript eval(). + * for an ECMAScript eval(). */ DUK_ASSERT(level == -2); /* by default, use caller's environment */ if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) { @@ -33522,6 +34340,7 @@ DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) { */ DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON, (long) (js_ctx->p - js_ctx->p_start)); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) { @@ -33937,7 +34756,7 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) { src_len = (duk_size_t) (p - js_ctx->p); buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len); DUK_ASSERT(buf != NULL); - DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len); + duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len); duk_hex_decode(thr, -1); js_ctx->p = p + 1; /* skip '|' */ @@ -34028,6 +34847,7 @@ DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) { DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT); + DUK_WO_NORETURN(return;); } js_ctx->recursion_depth++; } @@ -34604,9 +35424,9 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st /* 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 + * 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. * @@ -34743,7 +35563,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2. * For platforms where unaligned accesses are not allowed, shift 'dst' - * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result + * ahead by 1 byte to get alignment and then duk_memmove() the result * in place. The faster encoding loop makes up the difference. * There's always space for one extra byte because a terminator always * follows the hex data and that's been accounted for by the caller. @@ -34776,7 +35596,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE) if (shift_dst) { q--; - DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe); + duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe); DUK_ASSERT(dst + 2 * len_safe == q); } #endif @@ -34852,7 +35672,7 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d #if defined(DUK_USE_JC) { DUK_ASSERT(js_ctx->flag_ext_compatible); - DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */ + duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */ q += 9; q = duk__enc_buffer_data_hex(buf_data, buf_len, q); *q++ = DUK_ASC_DOUBLEQUOTE; @@ -34925,7 +35745,7 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */ DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible); - DUK_MEMZERO(buf, sizeof(buf)); + duk_memzero(buf, sizeof(buf)); /* The #if defined() clutter here needs to handle the three * cases: (1) JX+JC, (2) JX only, (3) JC only. @@ -35015,21 +35835,21 @@ DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t dept p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes); p_start = p; - DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len); + duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len); p += gap_len; avail_bytes = gap_len; DUK_ASSERT(need_bytes >= gap_len); need_bytes -= gap_len; while (need_bytes >= avail_bytes) { - DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes); + duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes); p += avail_bytes; need_bytes -= avail_bytes; avail_bytes <<= 1; } DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */ - DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes); + duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes); p += need_bytes; /*avail_bytes += need_bytes*/ @@ -35061,6 +35881,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) { DUK_DD(DUK_DDPRINT("slow path loop detect")); DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT); + DUK_WO_NORETURN(return;); } } if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { @@ -35070,6 +35891,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ duk_dup_top(thr); /* -> [ ... voidp voidp ] */ if (duk_has_prop(thr, js_ctx->idx_loop)) { DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT); + DUK_WO_NORETURN(return;); } duk_push_true(thr); /* -> [ ... voidp true ] */ duk_put_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */ @@ -35081,6 +35903,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT); + DUK_WO_NORETURN(return;); } js_ctx->recursion_depth++; @@ -35678,12 +36501,14 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { DUK_DD(DUK_DDPRINT("fast path recursion limit")); DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT); + DUK_WO_NORETURN(return 0;); } for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) { if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) { DUK_DD(DUK_DDPRINT("fast path loop detect")); DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT); + DUK_WO_NORETURN(return 0;); } } @@ -36064,7 +36889,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du /* Error message doesn't matter: the error is ignored anyway. */ DUK_DD(DUK_DDPRINT("aborting fast path")); DUK_ERROR_INTERNAL(js_ctx->thr); - return 0; /* unreachable */ + DUK_WO_NORETURN(return 0;); } DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) { @@ -36113,7 +36938,7 @@ void duk_bi_json_parse_helper(duk_hthread *thr, (unsigned long) flags, (long) duk_get_top(thr))); - DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc)); + duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc)); js_ctx->thr = thr; #if defined(DUK_USE_EXPLICIT_NULL_INIT) /* nothing now */ @@ -36223,7 +37048,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr, * Context init */ - DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc)); + duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc)); js_ctx->thr = thr; #if defined(DUK_USE_EXPLICIT_NULL_INIT) js_ctx->h_replacer = NULL; @@ -36621,7 +37446,7 @@ DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk DUK_LOCAL double duk__fmin_fixed(double x, double y) { /* fmin() with args -0 and +0 is not guaranteed to return - * -0 as Ecmascript requires. + * -0 as ECMAScript requires. */ if (x == 0 && y == 0) { duk_double_union du1, du2; @@ -36648,7 +37473,7 @@ DUK_LOCAL double duk__fmin_fixed(double x, double y) { DUK_LOCAL double duk__fmax_fixed(double x, double y) { /* fmax() with args -0 and +0 is not guaranteed to return - * +0 as Ecmascript requires. + * +0 as ECMAScript requires. */ if (x == 0 && y == 0) { if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) { @@ -37111,6 +37936,7 @@ DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) { (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) { DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1))); DUK_ERROR_TYPE(thr, "number expected"); + DUK_WO_NORETURN(return 0.0;); } duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE); DUK_ASSERT(duk_is_number(thr, -1)); @@ -37217,8 +38043,11 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) { duk_small_int_t c; duk_small_uint_t n2s_flags; - frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20); + /* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number + * value' check is done first. + */ d = duk__push_this_number_plain(thr); + frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20); c = (duk_small_int_t) DUK_FPCLASSIFY(d); if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) { @@ -37325,6 +38154,42 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) { return 1; } +/* + * ES2015 isFinite() etc + */ + +#if defined(DUK_USE_ES6) +DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) { + duk_int_t magic; + duk_bool_t ret = 0; + + if (duk_is_number(thr, 0)) { + duk_double_t d; + + magic = duk_get_current_magic(thr); + d = duk_get_number(thr, 0); + + switch (magic) { + case 0: /* isFinite() */ + ret = duk_double_is_finite(d); + break; + case 1: /* isInteger() */ + ret = duk_double_is_integer(d); + break; + case 2: /* isNaN() */ + ret = duk_double_is_nan(d); + break; + default: /* isSafeInteger() */ + DUK_ASSERT(magic == 3); + ret = duk_double_is_safe_integer(d); + } + } + + duk_push_boolean(thr, ret); + return 1; +} +#endif /* DUK_USE_ES6 */ + #endif /* DUK_USE_NUMBER_BUILTIN */ /* * Object built-ins @@ -37335,12 +38200,9 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) { /* Needed even when Object built-in disabled. */ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) { duk_tval *tv; + tv = DUK_HTHREAD_THIS_PTR(thr); - /* XXX: This is not entirely correct anymore; in ES2015 the - * default lookup should use @@toStringTag to come up with - * e.g. [object Symbol]. - */ - duk_push_class_string_tval(thr, tv); + duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/); return 1; } @@ -37845,7 +38707,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *th DUK_ASSERT(duk_get_hobject(thr, 2) != NULL); /* - * Validate and convert argument property descriptor (an Ecmascript + * Validate and convert argument property descriptor (an ECMAScript * object) into a set of defprop_flags and possibly property value, * getter, and/or setter values on the value stack. * @@ -38123,6 +38985,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) if (DUK_UNLIKELY(sanity-- == 0)) { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } duk_get_prototype(thr, -1); @@ -38247,37 +39110,37 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) { DUK_ERROR_TYPE(thr, "unimplemented"); - return 0; + DUK_WO_NORETURN(return 0;); } #endif /* DUK_USE_PROMISE_BUILTIN */ @@ -38311,6 +39174,7 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h h = duk_get_hstring(thr, -1); if (h == NULL) { DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr); + DUK_WO_NORETURN(return;); } if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) { @@ -38418,6 +39282,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) { if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) { /* XXX: [[Get]] receiver currently unsupported */ DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return 0;); } /* [ target key receiver? ...? ] */ @@ -38461,6 +39326,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) { if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) { /* XXX: [[Set]] receiver currently unsupported */ DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return 0;); } /* [ target key value receiver? ...? ] */ @@ -38594,7 +39460,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) { /* This must be generic in ES2015 and later. */ DUK_ASSERT_TOP(thr, 0); duk_push_this(thr); - duk_push_string(thr, "/"); + duk_push_literal(thr, "/"); duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE); duk_dup_m2(thr); /* another "/" */ duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS); @@ -38658,7 +39524,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) { if (magic != 16 /* .source */) { return 0; } - duk_push_string(thr, "(?:)"); /* .source handled by switch-case */ + duk_push_literal(thr, "(?:)"); /* .source handled by switch-case */ re_flags = 0; } else { DUK_DCERROR_TYPE_INVALID_ARGS(thr); @@ -38729,6 +39595,7 @@ DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t i if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) { DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return NULL;); } h = duk_to_hstring(thr, idx); DUK_ASSERT(h != NULL); @@ -38775,14 +39642,14 @@ DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this while (p <= p_end && p >= p_start) { t = *p; - /* For Ecmascript strings, this check can only match for + /* For ECMAScript strings, this check can only match for * initial UTF-8 bytes (not continuation bytes). For other * strings all bets are off. */ if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) { - DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */ - if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { + DUK_ASSERT(q_blen > 0); + if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { return cpos; } } @@ -38964,13 +39831,37 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) { */ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) { + duk_hstring *h; duk_int_t pos; /* XXX: faster implementation */ - (void) duk_push_this_coercible_to_string(thr); + h = duk_push_this_coercible_to_string(thr); + DUK_ASSERT(h != NULL); + pos = duk_to_int(thr, 0); - duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) (pos + 1)); + + if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) { + /* Cast to duk_size_t works in this case: + * - If pos < 0, (duk_size_t) pos will always be + * >= max_charlen, and result will be the empty string + * (see duk_substring()). + * - If pos >= 0, pos + 1 cannot wrap. + */ + DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN); + DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX); + duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U); + } else { + /* If size_t is smaller than int, explicit bounds checks + * are needed because an int may wrap multiple times. + */ + if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) { + duk_push_hstring_empty(thr); + } else { + duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U); + } + } + return 1; } @@ -39360,7 +40251,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) { while (p <= p_end) { DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input)); - if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { + if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { duk_dup_0(thr); h_match = duk_known_hstring(thr, -1); #if defined(DUK_USE_REGEXP_SUPPORT) @@ -39741,7 +40632,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) { while (p <= p_end) { DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input)); DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */ - if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { + if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) { /* never an empty match, so step 13.c.iii can't be triggered */ goto found; } @@ -40054,12 +40945,14 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) { /* Temporary fixed buffer, later converted to string. */ buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len); + DUK_ASSERT(buf != NULL); src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); + DUK_ASSERT(src != NULL); #if defined(DUK_USE_PREFER_SIZE) p = buf; while (count-- > 0) { - DUK_MEMCPY((void *) p, (const void *) src, input_blen); /* copy size may be zero */ + duk_memcpy((void *) p, (const void *) src, input_blen); /* copy size may be zero, but pointers are valid */ p += input_blen; } #else /* DUK_USE_PREFER_SIZE */ @@ -40076,12 +40969,12 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) { (long) result_len)); if (remain <= copy_size) { /* If result_len is zero, this case is taken and does - * a zero size copy. + * a zero size copy (with valid pointers). */ - DUK_MEMCPY((void *) p, (const void *) src, remain); + duk_memcpy((void *) p, (const void *) src, remain); break; } else { - DUK_MEMCPY((void *) p, (const void *) src, copy_size); + duk_memcpy((void *) p, (const void *) src, copy_size); p += copy_size; } @@ -40136,8 +41029,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2); prefix_len = (h1_len <= h2_len ? h1_len : h2_len); - /* Zero size compare not an issue with DUK_MEMCMP. */ - rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1), + rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) prefix_len); @@ -40187,7 +41079,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread * if (duk_is_undefined(thr, 1)) { if (magic) { - p_cmp_start += DUK_HSTRING_GET_BYTELEN(h) - blen_search; + p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search; } else { /* p_cmp_start already OK */ } @@ -40218,7 +41110,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread * result = 0; if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) && (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) { - if (DUK_MEMCMP((const void *) p_cmp_start, + if (duk_memcmp((const void *) p_cmp_start, (const void *) DUK_HSTRING_GET_DATA(h_search), (size_t) blen_search) == 0) { result = 1; @@ -40292,9 +41184,10 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { * +1 0xff after unique suffix for symbols with undefined description */ buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1); + DUK_ASSERT(buf != NULL); p = buf + 1; DUK_ASSERT(desc != NULL || len == 0); /* may be NULL if len is 0 */ - DUK_MEMCPY((void *) p, (const void *) desc, len); + duk_memcpy_unsafe((void *) p, (const void *) desc, len); p += len; if (magic == 0) { /* Symbol(): create unique symbol. Use two 32-bit values @@ -40465,7 +41358,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) { * * The thread must be in resumable state, either (a) new thread which hasn't * yet started, or (b) a thread which has previously yielded. This method - * must be called from an Ecmascript function. + * must be called from an ECMAScript function. * * Args: * - thread @@ -40491,8 +41384,9 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) { DUK_ASSERT(thr->heap->curr_thread == thr); thr_resume = duk_require_hthread(thr, 0); - is_error = (duk_small_uint_t) duk_to_boolean(thr, 2); - duk_set_top(thr, 2); + DUK_ASSERT(duk_get_top(thr) == 3); + is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr); + DUK_ASSERT(duk_get_top(thr) == 2); /* [ thread value ] */ @@ -40512,7 +41406,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) { caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent); if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) { - DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code")); + DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code")); goto state_error; } @@ -40540,7 +41434,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) { DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE); - /* The initial function must be an Ecmascript function (but + /* The initial function must be an ECMAScript function (but * can be bound). We must make sure of that before we longjmp * because an error in the RESUME handler call processing will * not be handled very cleanly. @@ -40619,7 +41513,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) { * The thread must be in yieldable state: it must have a resumer, and there * must not be any yield-preventing calls (native calls and constructor calls, * currently) in the thread's call stack (otherwise a resume would not be - * possible later). This method must be called from an Ecmascript function. + * possible later). This method must be called from an ECMAScript function. * * Args: * - value @@ -40640,8 +41534,9 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) { DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); DUK_ASSERT(thr->heap->curr_thread == thr); - is_error = (duk_small_uint_t) duk_to_boolean(thr, 1); - duk_set_top(thr, 1); + DUK_ASSERT(duk_get_top(thr) == 2); + is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr); + DUK_ASSERT(duk_get_top(thr) == 1); /* [ value ] */ @@ -40667,7 +41562,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) { caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent); if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) { - DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code")); + DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code")); goto state_error; } @@ -40764,7 +41659,7 @@ DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffe } else { copylen = length; } - DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen); + duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen); fb->offset += copylen; } @@ -40850,7 +41745,7 @@ DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) { * (excluding the null terminator). If retval == buffer size, * output was truncated (except for corner cases). * - * * Output format is intentionally different from Ecmascript + * * Output format is intentionally different from ECMAScript * formatting requirements, as formatting here serves debugging * of internals. * @@ -41636,7 +42531,7 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha const char *p_end = p + DUK_STRLEN(format); duk_int_t retval; - DUK_MEMZERO(&fb, sizeof(fb)); + duk_memzero(&fb, sizeof(fb)); fb.buffer = (duk_uint8_t *) str; fb.length = size; fb.offset = 0; @@ -41661,7 +42556,7 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha * understand. See man 3 printf. */ - DUK_MEMZERO(&st, sizeof(st)); + duk_memzero(&st, sizeof(st)); st.fb = &fb; st.depth = 0; st.depth_limit = 1; @@ -41728,8 +42623,8 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha /* format is too large, abort */ goto format_error; } - DUK_MEMZERO(fmtbuf, sizeof(fmtbuf)); - DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen); + duk_memzero(fmtbuf, sizeof(fmtbuf)); + duk_memcpy(fmtbuf, p_begfmt, fmtlen); /* assume exactly 1 arg, which is why '*' is forbidden; arg size still * depends on type though. @@ -41834,7 +42729,8 @@ DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_u duk_uint8_t *p = (duk_uint8_t *) buf; duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1); - DUK_MEMZERO(buf, buf_size); + DUK_ASSERT(buf != NULL); + duk_memzero(buf, buf_size); for (i = 0; i < fptr_size; i++) { duk_int_t left = (duk_int_t) (p_end - p); @@ -42172,6 +43068,7 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_ DUK_ASSERT(thr != NULL); heap = thr->heap; DUK_ASSERT(heap != NULL); + DUK_ASSERT(data != NULL); if (heap->dbg_read_cb == NULL) { DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length)); @@ -42209,7 +43106,7 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_ return; fail: - DUK_MEMZERO((void *) data, (size_t) length); + duk_memzero((void *) data, (size_t) length); } DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) { @@ -42822,7 +43719,7 @@ DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) { (unsigned int) du2.uc[4], (unsigned int) du2.uc[5], (unsigned int) du2.uc[6], (unsigned int) du2.uc[7])); - if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) { + if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) { duk_debug_write_int(thr, i32); } else { DUK_DBLUNION_DOUBLE_HTON(&du1); @@ -42931,9 +43828,9 @@ DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) { duk_debug_write_int(thr, 0); } else { duk_push_tval(thr, &act->tv_func); - duk_get_prop_string(thr, -1, "fileName"); + duk_get_prop_literal(thr, -1, "fileName"); duk__debug_write_hstring_safe_top(thr); - duk_get_prop_string(thr, -2, "name"); + duk_get_prop_literal(thr, -2, "name"); duk__debug_write_hstring_safe_top(thr); duk_pop_3(thr); /* Report next pc/line to be executed. */ @@ -42978,7 +43875,7 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) { act = thr->callstack_curr; if (act != NULL) { duk_push_tval(thr, &act->tv_func); - duk_get_prop_string(thr, -1, "fileName"); + duk_get_prop_literal(thr, -1, "fileName"); duk__debug_write_hstring_safe_top(thr); pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act); duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc)); @@ -43455,7 +44352,7 @@ DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) { fun = DUK_ACT_GET_FUNC(act); if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) { /* Direct eval requires that there's a current - * activation and it is an Ecmascript function. + * activation and it is an ECMAScript function. * When Eval is executed from e.g. cooperate API * call we'll need to do an indirect eval instead. */ @@ -44121,7 +45018,7 @@ DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *h if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) { duk_hboundfunc *h_bfun; - h_bfun = (duk_hboundfunc *) h_obj; + h_bfun = (duk_hboundfunc *) (void *) h_obj; duk__debug_getinfo_flags_key(thr, "target"); duk_debug_write_tval(thr, &h_bfun->target); @@ -44598,7 +45495,7 @@ DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act); /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is - * guaranteed to be a non-NULL Ecmascript function. + * guaranteed to be a non-NULL ECMAScript function. */ DUK_ASSERT(act->curr_pc == NULL || (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun))); @@ -44694,11 +45591,10 @@ DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_ DUK_ASSERT(h != NULL); move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1); - if (move_size > 0) { - DUK_MEMMOVE((void *) b, - (const void *) (b + 1), - (size_t) move_size); - } + duk_memmove((void *) b, + (const void *) (b + 1), + (size_t) move_size); + heap->dbg_breakpoint_count--; heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL; @@ -44784,7 +45680,7 @@ DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) { * * Error augmentation may throw an internal error (e.g. alloc error). * - * Ecmascript allows throwing any values, so all values cannot be + * ECMAScript allows throwing any values, so all values cannot be * augmented. Currently, the built-in augmentation at error creation * only augments error values which are Error instances (= have the * built-in Error.prototype in their prototype chain) and are also @@ -45124,7 +46020,6 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c DUK_UNREF(pc); DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */ DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */ - act = NULL; /* invalidated by pushes, so get out of the way */ duk_push_hobject(thr, func); @@ -45339,12 +46234,15 @@ DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) { /* #include duk_internal.h -> already included */ #if defined(DUK_USE_PREFER_SIZE) +DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr)); DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) { (void) duk_fatal(thr, "uncaught error"); + DUK_WO_NORETURN(return;); } #endif #if 0 +DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr)); DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) { const char *summary; char buf[DUK_USE_FATAL_MAXLEN]; @@ -45353,10 +46251,12 @@ DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) { DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary); buf[sizeof(buf) - 1] = (char) 0; (void) duk_fatal(thr, (const char *) buf); + DUK_WO_NORETURN(return;); } #endif #if !defined(DUK_USE_PREFER_SIZE) +DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr)); DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) { const char *summary; char buf[DUK_USE_FATAL_MAXLEN]; @@ -45366,6 +46266,7 @@ DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) { DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary); buf[sizeof(buf) - 1] = (char) 0; (void) duk_fatal(thr, (const char *) buf); + DUK_WO_NORETURN(return;); } #endif @@ -45403,14 +46304,9 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) { DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count)); -#if !defined(DUK_USE_CPP_EXCEPTIONS) /* If we don't have a jmpbuf_ptr, there is little we can do except * cause a fatal error. The caller's expectation is that we never * return. - * - * With C++ exceptions we now just propagate an uncaught error - * instead of invoking the fatal error handler. Because there's - * a dummy jmpbuf for C++ exceptions now, this could be changed. */ if (!thr->heap->lj.jmpbuf_ptr) { DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T", @@ -45424,16 +46320,12 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) { #endif DUK_UNREACHABLE(); } -#endif /* DUK_USE_CPP_EXCEPTIONS */ #if defined(DUK_USE_CPP_EXCEPTIONS) - { - duk_internal_exception exc; /* dummy */ - throw exc; - } -#else /* DUK_USE_CPP_EXCEPTIONS */ + throw duk_internal_exception(); /* dummy */ +#else DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb); -#endif /* DUK_USE_CPP_EXCEPTIONS */ +#endif DUK_UNREACHABLE(); } @@ -45612,10 +46504,10 @@ DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_t DUK_ASSERT_LJSTATE_SET(heap); } /* - * Create and throw an Ecmascript error object based on a code and a message. + * Create and throw an ECMAScript error object based on a code and a message. * - * Used when we throw errors internally. Ecmascript generated error objects - * are created by Ecmascript code, and the throwing is handled by the bytecode + * Used when we throw errors internally. ECMAScript generated error objects + * are created by ECMAScript code, and the throwing is handled by the bytecode * executor. */ @@ -45771,7 +46663,7 @@ DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t r */ duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return;); } /* * duk_hbuffer allocation and freeing. @@ -45822,10 +46714,10 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk /* zero everything unless requested not to do so */ #if defined(DUK_USE_ZERO_BUFFER_DATA) - DUK_MEMZERO((void *) res, + duk_memzero((void *) res, (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size); #else - DUK_MEMZERO((void *) res, header_size); + duk_memzero((void *) res, header_size); #endif if (flags & DUK_BUF_FLAG_EXTERNAL) { @@ -45872,7 +46764,7 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL); } } else { - *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1); + *out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1); } DUK_HBUFFER_SET_SIZE(res, size); @@ -45931,6 +46823,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, if (new_size > DUK_HBUFFER_MAX_BYTELEN) { DUK_ERROR_RANGE(thr, "buffer too long"); + DUK_WO_NORETURN(return;); } /* @@ -45959,7 +46852,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, if (new_size > prev_size) { DUK_ASSERT(new_size - prev_size > 0); #if defined(DUK_USE_ZERO_BUFFER_DATA) - DUK_MEMZERO((void *) ((char *) res + prev_size), + duk_memzero((void *) ((char *) res + prev_size), (duk_size_t) (new_size - prev_size)); #endif } @@ -45968,6 +46861,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res); } else { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return;); } DUK_ASSERT(res != NULL || new_size == 0); @@ -46069,7 +46963,7 @@ DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) { * functions in the callstack. */ } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) { - duk_hboundfunc *f = (duk_hboundfunc *) h; + duk_hboundfunc *f = (duk_hboundfunc *) (void *) h; DUK_FREE(heap, f->args); } @@ -46467,7 +47361,7 @@ DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) { duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */ duk_small_uint_t i; - DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx)); + duk_memzero(&bd_ctx, sizeof(bd_ctx)); bd->data = (const duk_uint8_t *) duk_strings_data; bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH; @@ -46688,7 +47582,8 @@ DUK_LOCAL void duk__dump_type_sizes(void) { DUK__DUMPSZ(duk_heap); DUK__DUMPSZ(duk_activation); DUK__DUMPSZ(duk_catcher); - DUK__DUMPSZ(duk_strcache); + DUK__DUMPSZ(duk_strcache_entry); + DUK__DUMPSZ(duk_litcache_entry); DUK__DUMPSZ(duk_ljstate); DUK__DUMPSZ(duk_fixedbuffer); DUK__DUMPSZ(duk_bitdecoder_ctx); @@ -46897,7 +47792,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, * Zero the struct, and start initializing roughly in order */ - DUK_MEMZERO(res, sizeof(*res)); + duk_memzero(res, sizeof(*res)); #if defined(DUK_USE_ASSERTIONS) res->heap_initializing = 1; #endif @@ -46982,7 +47877,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, /* XXX: use the pointer as a seed for now: mix in time at least */ - /* The casts through duk_intptr_t is to avoid the following GCC warning: + /* The casts through duk_uintptr_t is to avoid the following GCC warning: * * warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] * @@ -46993,7 +47888,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED)); res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED; #else /* DUK_USE_ROM_STRINGS */ - res->hash_seed = (duk_uint32_t) (duk_intptr_t) res; + res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res; #if !defined(DUK_USE_STRHASH_DENSE) res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */ #endif @@ -47033,17 +47928,17 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, #if defined(DUK_USE_STRTAB_PTRCOMP) /* zero assumption */ - DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * st_initsize); + duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize); #else #if defined(DUK_USE_EXPLICIT_NULL_INIT) { - duk_small_uint_t i; + duk_uint32_t i; for (i = 0; i < st_initsize; i++) { res->strtable[i] = NULL; } } #else - DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * st_initsize); + duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize); #endif /* DUK_USE_EXPLICIT_NULL_INIT */ #endif /* DUK_USE_STRTAB_PTRCOMP */ @@ -47053,13 +47948,30 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, #if defined(DUK_USE_EXPLICIT_NULL_INIT) { - duk_small_uint_t i; + duk_uint_t i; for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) { res->strcache[i].h = NULL; } } #endif + /* + * Init litcache + */ +#if defined(DUK_USE_LITCACHE_SIZE) + DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0); + DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE)); +#if defined(DUK_USE_EXPLICIT_NULL_INIT) + { + duk_uint_t i; + for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) { + res->litcache[i].addr = NULL; + res->litcache[i].h = NULL; + } + } +#endif +#endif /* DUK_USE_LITCACHE_SIZE */ + /* XXX: error handling is incomplete. It would be cleanest if * there was a setjmp catchpoint, so that all init code could * freely throw errors. If that were the case, the return code @@ -47131,7 +48043,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, { duk_uint64_t tmp_u64; tmp_u64 = 0; - DUK_MEMCPY((void *) &tmp_u64, + duk_memcpy((void *) &tmp_u64, (const void *) &res, (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *))); res->rnd_state[1] ^= tmp_u64; @@ -47886,7 +48798,7 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) { duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop); #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) { - duk_hboundfunc *f = (duk_hboundfunc *) h; + duk_hboundfunc *f = (duk_hboundfunc *) (void *) h; DUK_ASSERT_HBOUNDFUNC_VALID(f); duk__mark_tval(heap, &f->target); duk__mark_tval(heap, &f->this_binding); @@ -48360,7 +49272,8 @@ DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep duk_hstring *next; next = h->hdr.h_next; - if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) { + if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) + { DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h); count_keep++; prev = h; @@ -48369,13 +49282,26 @@ DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep count_free++; #endif + /* For pinned strings the refcount has been + * bumped. We could unbump it here before + * freeing, but that's actually not necessary + * except for assertions. + */ +#if 0 + if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) { + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U); + DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h); + DUK_HSTRING_CLEAR_PINNED_LITERAL(h); + } +#endif #if defined(DUK_USE_REFERENCE_COUNTING) /* Non-zero refcounts should not happen for unreachable strings, * because we refcount finalize all unreachable objects which * should have decreased unreachable string refcounts to zero - * (even for cycles). + * (even for cycles). However, pinned strings have a +1 bump. */ - DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0); + DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == + DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U); #endif /* Deal with weak references first. */ @@ -48578,6 +49504,26 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_ *out_count_keep = count_keep; } +/* + * Litcache helpers. + */ + +#if defined(DUK_USE_LITCACHE_SIZE) +DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) { + duk_uint_t i; + duk_litcache_entry *e; + + e = heap->litcache; + for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) { + e->addr = NULL; + /* e->h does not need to be invalidated: when e->addr is + * NULL, e->h is considered garbage. + */ + e++; + } +} +#endif /* DUK_USE_LITCACHE_SIZE */ + /* * Object compaction. * @@ -48762,6 +49708,7 @@ DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) { DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) { duk_bool_t count_ok; + duk_size_t expect_refc; /* The refcount check only makes sense for reachable objects on * heap_allocated or string table, after the sweep phase. Prior to @@ -48778,7 +49725,11 @@ DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) { */ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr)); - count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == hdr->h_assert_refcount); + expect_refc = hdr->h_assert_refcount; + if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) { + expect_refc++; + } + count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc); if (!count_ok) { DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO", (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr), @@ -48815,6 +49766,22 @@ DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) { } } #endif /* DUK_USE_REFERENCE_COUNTING */ + +#if defined(DUK_USE_LITCACHE_SIZE) +DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) { + duk_uint_t i; + duk_litcache_entry *e; + + e = heap->litcache; + for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) { + /* Entry addresses were NULLed before mark-and-sweep, check + * that they're still NULL afterwards to ensure no pointers + * were recorded through any side effects. + */ + DUK_ASSERT(e->addr == NULL); + } +} +#endif /* DUK_USE_LITCACHE_SIZE */ #endif /* DUK_USE_ASSERTIONS */ /* @@ -48835,10 +49802,13 @@ DUK_LOCAL void duk__dump_stats(duk_heap *heap) { DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld", (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count, (long) heap->stats_ms_emergency_count)); - DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, resize_check=%ld, resize_grow=%ld, resize_shrink=%ld", + DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, " + "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, " + "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld", (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss, (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow, - (long) heap->stats_strtab_resize_shrink)); + (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit, + (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin)); DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld", (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array)); DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld", @@ -48978,6 +49948,9 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING) duk__clear_assert_refcounts(heap); +#endif +#if defined(DUK_USE_LITCACHE_SIZE) + duk__wipe_litcache(heap); #endif duk__mark_roots_heap(heap); /* Mark main reachability roots. */ #if defined(DUK_USE_REFERENCE_COUNTING) @@ -49084,6 +50057,9 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags */ duk__assert_valid_refcounts(heap); #endif /* DUK_USE_REFERENCE_COUNTING */ +#if defined(DUK_USE_LITCACHE_SIZE) + duk__assert_litcache_nulls(heap); +#endif /* DUK_USE_LITCACHE_SIZE */ #endif /* DUK_USE_ASSERTIONS */ /* @@ -49273,8 +50249,7 @@ DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) { res = DUK_ALLOC(heap, size); if (DUK_LIKELY(res != NULL)) { - /* assume memset with zero size is OK */ - DUK_MEMZERO(res, size); + duk_memzero(res, size); } return res; } @@ -49288,7 +50263,7 @@ DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) return res; } DUK_ERROR_ALLOC_FAILED(thr); - return NULL; + DUK_WO_NORETURN(return NULL;); } DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) { @@ -49300,7 +50275,7 @@ DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_ return res; } DUK_ERROR_ALLOC_FAILED(thr); - return NULL; + DUK_WO_NORETURN(return NULL;); } /* @@ -49863,7 +50838,7 @@ DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop); #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ } else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) { - duk_hboundfunc *f = (duk_hboundfunc *) h; + duk_hboundfunc *f = (duk_hboundfunc *) (void *) h; DUK_ASSERT_HBOUNDFUNC_VALID(f); DUK_TVAL_DECREF_NORZ(thr, &f->target); DUK_TVAL_DECREF_NORZ(thr, &f->this_binding); @@ -50553,9 +51528,9 @@ DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) { */ DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) { - duk_small_int_t i; + duk_uint_t i; for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) { - duk_strcache *c = heap->strcache + i; + duk_strcache_entry *c = heap->strcache + i; if (c->h == h) { DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p", (void *) h, (void *) heap)); @@ -50627,9 +51602,9 @@ DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) { duk_heap *heap; - duk_strcache *sce; + duk_strcache_entry *sce; duk_uint_fast32_t byte_offset; - duk_small_int_t i; + duk_uint_t i; duk_bool_t use_cache; duk_uint_fast32_t dist_start, dist_end, dist_sce; duk_uint_fast32_t char_length; @@ -50680,14 +51655,14 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2) DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):")); for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) { - duk_strcache *c = heap->strcache + i; + duk_strcache_entry *c = heap->strcache + i; DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld", (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx)); } #endif for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) { - duk_strcache *c = heap->strcache + i; + duk_strcache_entry *c = heap->strcache + i; if (c->h == h) { sce = c; @@ -50816,10 +51791,10 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t * C <- sce ==> B * D D */ - duk_strcache tmp; + duk_strcache_entry tmp; tmp = *sce; - DUK_MEMMOVE((void *) (&heap->strcache[1]), + duk_memmove((void *) (&heap->strcache[1]), (const void *) (&heap->strcache[0]), (size_t) (((char *) sce) - ((char *) &heap->strcache[0]))); heap->strcache[0] = tmp; @@ -50829,7 +51804,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2) DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):")); for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) { - duk_strcache *c = heap->strcache + i; + duk_strcache_entry *c = heap->strcache + i; DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld", (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx)); } @@ -50840,7 +51815,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t scan_error: DUK_ERROR_INTERNAL(thr); - return 0; + DUK_WO_NORETURN(return 0;); } /* * Heap string table handling, string interning. @@ -50898,7 +51873,7 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) { return; } - DUK_MEMZERO((void *) count_len, sizeof(count_len)); + duk_memzero((void *) count_len, sizeof(count_len)); for (i = 0; i < heap->st_size; i++) { h = DUK__HEAPPTR_DEC16(heap, strtable[i]); count_chain = 0; @@ -51010,7 +51985,7 @@ DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap, if (DUK_UNLIKELY(res == NULL)) { goto alloc_error; } - DUK_MEMZERO(res, sizeof(duk_hstring_external)); + duk_memzero(res, sizeof(duk_hstring_external)); #if defined(DUK_USE_EXPLICIT_NULL_INIT) DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif @@ -51030,14 +52005,14 @@ DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap, if (DUK_UNLIKELY(res == NULL)) { goto alloc_error; } - DUK_MEMZERO(res, sizeof(duk_hstring)); + duk_memzero(res, sizeof(duk_hstring)); #if defined(DUK_USE_EXPLICIT_NULL_INIT) DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); data_tmp = (duk_uint8_t *) (res + 1); - DUK_MEMCPY(data_tmp, str, blen); + duk_memcpy(data_tmp, str, blen); data_tmp[blen] = (duk_uint8_t) 0; data = (const duk_uint8_t *) data_tmp; } @@ -51530,11 +52505,12 @@ DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_ui } lookup_hash &= 0xff; - curr = DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]); + curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]); while (curr != NULL) { + /* Unsafe memcmp() because for zero blen, str may be NULL. */ if (strhash == DUK_HSTRING_GET_HASH(curr) && blen == DUK_HSTRING_GET_BYTELEN(curr) && - DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) { + duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) { DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx", curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr))); return curr; @@ -51554,6 +52530,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uin /* Preliminaries. */ + /* XXX: maybe just require 'str != NULL' even for zero size? */ DUK_ASSERT(heap != NULL); DUK_ASSERT(blen == 0 || str != NULL); DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN); /* Caller is responsible for ensuring this. */ @@ -51572,7 +52549,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uin while (h != NULL) { if (DUK_HSTRING_GET_HASH(h) == strhash && DUK_HSTRING_GET_BYTELEN(h) == blen && - DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) { + duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) { /* Found existing entry. */ DUK_STATS_INC(heap, stats_strtab_intern_hit); return h; @@ -51645,10 +52622,67 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, con res = duk_heap_strtable_intern(thr->heap, str, blen); if (DUK_UNLIKELY(res == NULL)) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } return res; } +#if defined(DUK_USE_LITCACHE_SIZE) +DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) { + duk_uintptr_t key; + + DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0); + DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE)); + + key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str; + key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1); /* Assumes size is power of 2. */ + /* Due to masking, cast is in 32-bit range. */ + DUK_ASSERT(key <= DUK_UINT_MAX); + return (duk_uint_t) key; +} + +DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) { + duk_uint_t key; + duk_litcache_entry *ent; + duk_hstring *h; + + /* Fast path check: literal exists in literal cache. */ + key = duk__strtable_litcache_key(str, blen); + ent = thr->heap->litcache + key; + if (ent->addr == str) { + DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O", + (const void *) str, (long) blen, (duk_heaphdr *) ent->h)); + DUK_ASSERT(ent->h != NULL); + DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h)); + DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit); + return ent->h; + } + + /* Intern and update (overwrite) cache entry. */ + h = duk_heap_strtable_intern_checked(thr, str, blen); + ent->addr = str; + ent->h = h; + DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss); + + /* Pin the duk_hstring until the next mark-and-sweep. This means + * litcache entries don't need to be invalidated until the next + * mark-and-sweep as their target duk_hstring is not freed before + * the mark-and-sweep happens. The pin remains even if the literal + * cache entry is overwritten, and is still useful to avoid string + * table traffic. + */ + if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) { + DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h)); + DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)); + DUK_HSTRING_INCREF(thr, h); + DUK_HSTRING_SET_PINNED_LITERAL(h); + DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin); + } + + return h; +} +#endif /* DUK_USE_LITCACHE_SIZE */ + DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) { duk_hstring *res; @@ -51658,6 +52692,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, res = duk_heap_strtable_intern_u32(thr->heap, val); if (DUK_UNLIKELY(res == NULL)) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } return res; } @@ -51963,7 +52998,7 @@ DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hob if (!res) { return NULL; } - DUK_MEMZERO(res, sizeof(duk_hboundfunc)); + duk_memzero(res, sizeof(duk_hboundfunc)); duk__init_object_parts(heap, hobject_flags, &res->obj); @@ -52005,7 +53040,7 @@ DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t if (DUK_UNLIKELY(res == NULL)) { return NULL; } - DUK_MEMZERO(res, sizeof(duk_hthread)); + duk_memzero(res, sizeof(duk_hthread)); duk__init_object_parts(heap, hobject_flags, &res->obj); @@ -52047,6 +53082,7 @@ DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags); if (res == NULL) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return NULL;); } return res; } @@ -52262,7 +53298,7 @@ DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk * are very often in order already. */ if (idx != idx_insert) { - DUK_MEMMOVE((void *) (keys + idx_insert + 1), + duk_memmove((void *) (keys + idx_insert + 1), (const void *) (keys + idx_insert), ((size_t) (idx - idx_insert) * sizeof(duk_hstring *))); keys[idx_insert] = h_curr; @@ -52746,7 +53782,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t } /* - * Get enumerated keys in an Ecmascript array. Matches Object.keys() behavior + * Get enumerated keys in an ECMAScript array. Matches Object.keys() behavior * described in E5 Section 15.2.3.14. */ @@ -52832,6 +53868,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, d break; } else { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } } h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h); @@ -52915,7 +53952,7 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr (long) hdr[hdr_index + 1])); #endif - DUK_MEMZERO(be_ctx, sizeof(*be_ctx)); + duk_memzero(be_ctx, sizeof(*be_ctx)); be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset; be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH; @@ -53026,7 +54063,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk * Iterate the bitstream (line diffs) until PC is reached */ - DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx)); + duk_memzero(bd_ctx, sizeof(*bd_ctx)); bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset; bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset); @@ -53086,7 +54123,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i */ duk_get_prop_stridx(thr, idx_func, DUK_STRIDX_INT_PC2LINE); - pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(thr, -1); + pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1); if (pc2line != NULL) { DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line)); line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc); @@ -53154,7 +54191,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i #define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED /* Valstack space that suffices for all local calls, excluding any recursion - * into Ecmascript or Duktape/C calls (Proxy, getters, etc). + * into ECMAScript or Duktape/C calls (Proxy, getters, etc). */ #define DUK__VALSTACK_SPACE 10 @@ -53704,6 +54741,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr, if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) { DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return;); } /* @@ -53907,18 +54945,14 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr, } else { array_copy_size = sizeof(duk_tval) * new_a_size; } - if (array_copy_size > 0) { - /* Avoid zero copy with an invalid pointer. If obj->p is NULL, - * the 'new_a' pointer will be invalid which is not allowed even - * when copy size is zero. - */ - DUK_ASSERT(new_a != NULL); - DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL); - DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0); - DUK_MEMCPY((void *) new_a, - (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), - array_copy_size); - } + + DUK_ASSERT(new_a != NULL || array_copy_size == 0U); + DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U); + DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U); + duk_memcpy_unsafe((void *) new_a, + (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), + array_copy_size); + for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) { duk_tval *tv = &new_a[i]; DUK_TVAL_SET_UNUSED(tv); @@ -53943,7 +54977,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr, /* fill new_h with u32 0xff = UNUSED */ DUK_ASSERT(new_h_size > 0); - DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size); + duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size); DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */ @@ -54053,6 +55087,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr, #endif DUK_ERROR_ALLOC_FAILED(thr); + DUK_WO_NORETURN(return;); } /* @@ -54530,7 +55565,7 @@ DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, /* This is not strictly necessary, but avoids compiler warnings; e.g. * gcc won't reliably detect that no uninitialized data is read below. */ - DUK_MEMZERO((void *) &tv, sizeof(duk_tval)); + duk_memzero((void *) &tv, sizeof(duk_tval)); if (duk_hobject_get_internal_value(heap, obj, &tv)) { duk_hstring *h; @@ -54718,7 +55753,7 @@ DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject } /* - * Ecmascript compliant [[GetOwnProperty]](P), for internal use only. + * ECMAScript compliant [[GetOwnProperty]](P), for internal use only. * * If property is found: * - Fills descriptor fields to 'out_desc' @@ -55093,7 +56128,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobje } /* - * Ecmascript compliant [[GetProperty]](P), for internal use only. + * ECMAScript compliant [[GetProperty]](P), for internal use only. * * If property is found: * - Fills descriptor fields to 'out_desc' @@ -55150,6 +56185,7 @@ DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_h break; } else { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } } curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr); @@ -55431,7 +56467,7 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ /* - * GETPROP: Ecmascript property read. + * GETPROP: ECMAScript property read. */ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) { @@ -55485,7 +56521,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s", duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj)); #endif - return 0; + DUK_WO_NORETURN(return 0;); + break; } case DUK_TAG_BOOLEAN: { @@ -55641,6 +56678,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, !DUK_TVAL_IS_UNDEFINED(tv_hook); if (datadesc_reject || accdesc_reject) { DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } duk_pop_2_unsafe(thr); @@ -55832,6 +56870,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, */ if (DUK_UNLIKELY(sanity-- == 0)) { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr); } while (curr != NULL); @@ -55902,6 +56941,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, DUK_HOBJECT_HAS_STRICT(h)) { /* XXX: sufficient to check 'strict', assert for 'is function' */ DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ); + DUK_WO_NORETURN(return 0;); } } } @@ -55914,7 +56954,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, } /* - * HASPROP: Ecmascript property existence check ("in" operator). + * HASPROP: ECMAScript property existence check ("in" operator). * * Interestingly, the 'in' operator does not do any coercion of * the target object. @@ -55980,6 +57020,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, /* Note: unconditional throw */ DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject")); DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE); + DUK_WO_NORETURN(return 0;); } /* XXX: fast path for arrays? */ @@ -56004,7 +57045,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_push_hobject(thr, h_target); /* target */ duk_push_tval(thr, tv_key); /* P */ duk_call_method(thr, 2 /*nargs*/); - tmp_bool = duk_to_boolean(thr, -1); + tmp_bool = duk_to_boolean_top_pop(thr); if (!tmp_bool) { /* Target object must be checked for a conflicting * non-configurable property. @@ -56023,11 +57064,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */ DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */ DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } } } - duk_pop_2_unsafe(thr); /* [ key trap_result ] -> [] */ + duk_pop_unsafe(thr); /* [ key ] -> [] */ return tmp_bool; } @@ -56119,7 +57161,7 @@ DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tv /* Refuse to update an Array's 'length' to a value outside the * 32-bit range. Negative zero is accepted as zero. */ - res = (duk_uint32_t) d; + res = duk_double_to_uint32_t(d); if ((duk_double_t) res != d) { goto fail_range; } @@ -56128,7 +57170,7 @@ DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tv fail_range: DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH); - return 0; /* unreachable */ + DUK_WO_NORETURN(return 0;); } /* Delete elements required by a smaller length, taking into account @@ -56397,9 +57439,9 @@ DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject } /* - * PUTPROP: Ecmascript property write. + * PUTPROP: ECMAScript property write. * - * Unlike Ecmascript primitive which returns nothing, returns 1 to indicate + * Unlike ECMAScript primitive which returns nothing, returns 1 to indicate * success and 0 to indicate failure (assuming throw is not set). * * This is an extremely tricky function. Some examples: @@ -56486,7 +57528,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s", duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj)); #endif - return 0; + DUK_WO_NORETURN(return 0;); + break; } case DUK_TAG_BOOLEAN: { @@ -56590,8 +57633,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_push_tval(thr, tv_val); /* V */ duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */ duk_call_method(thr, 4 /*nargs*/); - tmp_bool = duk_to_boolean(thr, -1); - duk_pop_nodecref_unsafe(thr); + tmp_bool = duk_to_boolean_top_pop(thr); if (!tmp_bool) { goto fail_proxy_rejected; } @@ -56623,6 +57665,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, (desc.set == NULL); if (datadesc_reject || accdesc_reject) { DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } duk_pop_2_unsafe(thr); @@ -56922,6 +57965,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, */ if (DUK_UNLIKELY(sanity-- == 0)) { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr); } while (curr != NULL); @@ -57271,6 +58315,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } /* Note: no key on stack */ return 0; @@ -57285,6 +58330,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s", duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj)); #endif + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; @@ -57293,6 +58339,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, not extensible")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE); + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; @@ -57301,6 +58348,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, not writable")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE); + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; @@ -57310,6 +58358,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, not writable")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE); + DUK_WO_NORETURN(return 0;); } return 0; #endif @@ -57318,6 +58367,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; @@ -57326,6 +58376,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter")); if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED); + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; @@ -57334,13 +58385,14 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, DUK_DDD(DUK_DDDPRINT("result: error, internal")); if (throw_flag) { DUK_ERROR_INTERNAL(thr); + DUK_WO_NORETURN(return 0;); } duk_pop_unsafe(thr); /* remove key */ return 0; } /* - * Ecmascript compliant [[Delete]](P, Throw). + * ECMAScript compliant [[Delete]](P, Throw). */ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) { @@ -57494,12 +58546,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); + DUK_WO_NORETURN(return 0;); } return 0; } /* - * DELPROP: Ecmascript property deletion. + * DELPROP: ECMAScript property deletion. */ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) { @@ -57554,8 +58607,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_push_hobject(thr, h_target); /* target */ duk_dup_m4(thr); /* P */ duk_call_method(thr, 2 /*nargs*/); - tmp_bool = duk_to_boolean(thr, -1); - duk_pop_nodecref_unsafe(thr); + tmp_bool = duk_to_boolean_top_pop(thr); if (!tmp_bool) { goto fail_proxy_rejected; /* retval indicates delete failed */ } @@ -57580,6 +58632,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, if (desc_reject) { /* unconditional */ DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } } rc = 1; /* success */ @@ -57663,12 +58716,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s", duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj)); #endif - return 0; + DUK_WO_NORETURN(return 0;); #if defined(DUK_USE_ES6_PROXY) fail_proxy_rejected: if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED); + DUK_WO_NORETURN(return 0;); } duk_set_top_unsafe(thr, entry_top); return 0; @@ -57677,6 +58731,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, fail_not_configurable: if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); + DUK_WO_NORETURN(return 0;); } duk_set_top_unsafe(thr, entry_top); return 0; @@ -57816,7 +58871,7 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob error_virtual: /* share error message */ error_internal: DUK_ERROR_INTERNAL(thr); - return; + DUK_WO_NORETURN(return;); } /* @@ -57896,7 +58951,7 @@ DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *ob val = duk_to_number_m1(thr); duk_pop_3_unsafe(thr); - /* This isn't part of Ecmascript semantics; return a value within + /* This isn't part of ECMAScript semantics; return a value within * duk_size_t range, or 0 otherwise. */ if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) { @@ -58007,7 +59062,7 @@ DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *th * NormalizePropertyDescriptor() related helper. * * Internal helper which validates and normalizes a property descriptor - * represented as an Ecmascript object (e.g. argument to defineProperty()). + * represented as an ECMAScript object (e.g. argument to defineProperty()). * The output of this conversion is a set of defprop_flags and possibly * some values pushed on the value stack to (1) ensure borrowed pointers * remain valid, and (2) avoid unnecessary pops for footprint reasons. @@ -58057,7 +59112,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr, if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) { is_data_desc = 1; - if (duk_to_boolean(thr, -1)) { + if (duk_to_boolean_top_pop(thr)) { defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE; } else { defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE; @@ -58109,7 +59164,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr, } if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) { - if (duk_to_boolean(thr, -1)) { + if (duk_to_boolean_top_pop(thr)) { defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE; } else { defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE; @@ -58117,7 +59172,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr, } if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) { - if (duk_to_boolean(thr, -1)) { + if (duk_to_boolean_top_pop(thr)) { defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE; } else { defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE; @@ -58138,6 +59193,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr, type_error: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR); + DUK_WO_NORETURN(return;); } /* @@ -58146,7 +59202,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr, * * Inlines all [[DefineOwnProperty]] exotic behaviors. * - * Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not + * Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not * implemented directly, but Object.defineProperty() serves its purpose. * We don't need the [[DefineOwnProperty]] internally and we don't have a * property descriptor with 'missing values' so it's easier to avoid it @@ -59019,6 +60075,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr, fail_not_extensible: if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE); + DUK_WO_NORETURN(return 0;); } return 0; @@ -59026,6 +60083,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr, fail_not_configurable: if (throw_flag) { DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); + DUK_WO_NORETURN(return 0;); } return 0; } @@ -59081,6 +60139,7 @@ DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_ho if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) { DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject")); DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); + DUK_WO_NORETURN(return;); } #endif @@ -59228,7 +60287,7 @@ DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk (const void *) p_start, (const void *) p_end, (const void *) p)); - /* For invalid UTF-8 (never happens for standard Ecmascript strings) + /* For invalid UTF-8 (never happens for standard ECMAScript strings) * return U+FFFD replacement character. */ if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) { @@ -59384,7 +60443,7 @@ DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const c if (len != DUK_HSTRING_GET_BYTELEN(h)) { return 0; } - if (DUK_MEMCMP((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) { + if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) { return 1; } return 0; @@ -59421,7 +60480,7 @@ DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr if (!thr->valstack) { goto fail; } - DUK_MEMZERO(thr->valstack, alloc_size); + duk_memzero(thr->valstack, alloc_size); thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM; thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE; thr->valstack_bottom = thr->valstack; @@ -59525,7 +60584,7 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) { props = DUK_ALLOC_CHECKED(thr, alloc_size); DUK_ASSERT(props != NULL); DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL); - DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size); + duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size); /* XXX: keep property attributes or tweak them here? * Properties will now be non-configurable even when they're @@ -59652,7 +60711,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS)); - DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx)); + duk_memzero(&bd_ctx, sizeof(bd_ctx)); bd->data = (const duk_uint8_t *) duk_builtins_data; bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH; @@ -59894,11 +60953,9 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { * signaled using a single flag bit in the bitstream. */ - if (duk_bd_decode_flag(bd)) { - defprop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS); - } else { - defprop_flags = DUK_PROPDESC_FLAGS_WC; - } + defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd, + DUK__PROP_FLAGS_BITS, + (duk_uint32_t) DUK_PROPDESC_FLAGS_WC); defprop_flags |= DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | @@ -60003,6 +61060,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { #if defined(DUK_USE_LIGHTFUNC_BUILTINS) duk_small_int_t lightfunc_eligible; #endif + duk_small_uint_t defprop_flags; duk__push_stridx_or_string(thr, bd); h_key = duk_known_hstring(thr, -1); @@ -60122,10 +61180,19 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { lightfunc_skip: #endif - /* XXX: So far all ES builtins are 'wc' but e.g. - * performance.now() should be 'wec'. - */ - duk_xdef_prop(thr, (duk_idx_t) i, DUK_PROPDESC_FLAGS_WC); + defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd, + DUK__PROP_FLAGS_BITS, + (duk_uint32_t) DUK_PROPDESC_FLAGS_WC); + defprop_flags |= DUK_DEFPROP_FORCE | + DUK_DEFPROP_HAVE_VALUE | + DUK_DEFPROP_HAVE_WRITABLE | + DUK_DEFPROP_HAVE_ENUMERABLE | + DUK_DEFPROP_HAVE_CONFIGURABLE; + DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE); + DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE); + DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE); + + duk_def_prop(thr, (duk_idx_t) i, defprop_flags); /* [ (builtin objects) ] */ } @@ -60198,7 +61265,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { "f" #endif " " - /* Low memory options */ + /* Low memory/performance options */ #if defined(DUK_USE_STRTAB_PTRCOMP) "s" #endif @@ -60238,6 +61305,9 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { * are in ROM. */ "Z" +#endif +#if defined(DUK_USE_LITCACHE_SIZE) + "l" #endif " " /* Object property allocation layout */ @@ -60813,8 +61883,8 @@ DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) { /* Use DUK_ALLOC_RAW() to avoid side effects. */ new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size); if (new_ptr != NULL) { - DUK_MEMCPY((void *) new_ptr, (const void *) thr->valstack, alloc_size); - DUK_MEMSET((void *) thr->valstack, 0x55, alloc_size); + duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size); + duk_memset((void *) thr->valstack, 0x55, alloc_size); DUK_FREE_CHECKED(thr, (void *) thr->valstack); thr->valstack = new_ptr; thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off); @@ -60832,7 +61902,7 @@ DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) { /* #include duk_internal.h -> already included */ -/* Ecmascript modulus ('%') does not match IEEE 754 "remainder" operation +/* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation * (implemented by remainder() in C99) but does seem to match ANSI C fmod(). * Compare E5 Section 11.5.3 and "man fmod". */ @@ -60886,9 +61956,9 @@ DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) { /* Shared helper for Math.pow() and exponentiation operator. */ DUK_INTERNAL double duk_js_arith_pow(double x, double y) { - /* The ANSI C pow() semantics differ from Ecmascript. + /* The ANSI C pow() semantics differ from ECMAScript. * - * E.g. when x==1 and y is +/- infinite, the Ecmascript required + * E.g. when x==1 and y is +/- infinite, the ECMAScript required * result is NaN, while at least Linux pow() returns 1. */ @@ -60968,7 +62038,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) { * * duk_handle_call_unprotected(): * - * - Unprotected call to Ecmascript or Duktape/C function, from native + * - Unprotected call to ECMAScript or Duktape/C function, from native * code or bytecode executor. * * - Also handles Ecma-to-Ecma calls which reuses a currently running @@ -61022,6 +62092,7 @@ DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthre DUK_D(DUK_DPRINT("call prevented because C recursion limit reached")); DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT); + DUK_WO_NORETURN(return;); } DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) { @@ -61057,6 +62128,7 @@ DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread */ DUK_D(DUK_DPRINT("call prevented because call stack limit reached")); DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT); + DUK_WO_NORETURN(return;); } DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) { @@ -61470,6 +62542,7 @@ DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uin if (DUK_UNLIKELY(proxy_invariant != 0U)) { /* Proxy 'construct' return value invariant violated. */ DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr); + DUK_WO_NORETURN(return;); } /* XXX: direct value stack access */ duk_pop(thr); @@ -61530,7 +62603,7 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, duk_tval *tv_args; duk_tval *tv_gap; - h_bound = (duk_hboundfunc *) func; + h_bound = (duk_hboundfunc *) (void *) func; tv_args = h_bound->args; len = h_bound->nargs; DUK_ASSERT(len == 0 || tv_args != NULL); @@ -61570,6 +62643,7 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, } else { /* Shouldn't happen, so ugly error is enough. */ DUK_ERROR_INTERNAL(thr); + DUK_WO_NORETURN(return;); } DUK_ASSERT(duk_get_top(thr) >= idx_func + 2); @@ -61745,11 +62819,13 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx if (top < idx_func + 3) { /* argArray is a mandatory argument for Reflect.construct(). */ DUK_ERROR_TYPE_INVALID_ARGS(thr); + DUK_WO_NORETURN(return 0;); } if (top > idx_func + 3) { if (!duk_strict_equals(thr, idx_func, idx_func + 3)) { /* XXX: [[Construct]] newTarget currently unsupported */ DUK_ERROR_UNSUPPORTED(thr); + DUK_WO_NORETURN(return 0;); } duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */ } @@ -62286,6 +63362,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th if (duk_hobject_find_existing_entry_tval_ptr(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_HTHREAD_STRING_INT_TARGET(thr)) != NULL) { duk_push_tval(thr, tv_func); (void) duk_throw(thr); + DUK_WO_NORETURN(return NULL;); } } #endif @@ -62299,8 +63376,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th #else DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE); #endif - DUK_UNREACHABLE(); - return NULL; /* never executed */ + DUK_WO_NORETURN(return NULL;); not_constructable: /* For now GETPROPC delayed error not needed for constructor calls. */ @@ -62313,8 +63389,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th #else DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE); #endif - DUK_UNREACHABLE(); - return NULL; /* never executed */ + DUK_WO_NORETURN(return NULL;); } /* @@ -62338,6 +63413,7 @@ DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_re idx_rcbase = duk_get_top(thr) - num_actual_rets; /* base of known return values */ if (DUK_UNLIKELY(idx_rcbase < 0)) { DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC); + DUK_WO_NORETURN(return;); } DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: " @@ -62641,10 +63717,10 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr, * Update return value stack index of current activation (if any). * * Although it might seem this is not necessary (bytecode executor - * does this for Ecmascript-to-Ecmascript calls; other calls are + * does this for ECMAScript-to-ECMAScript calls; other calls are * handled here), this turns out to be necessary for handling yield - * and resume. For them, an Ecmascript-to-native call happens, and - * the Ecmascript call's retval_byteoff must be set for things to work. + * and resume. For them, an ECMAScript-to-native call happens, and + * the ECMAScript call's retval_byteoff must be set for things to work. */ act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval); @@ -62851,16 +63927,16 @@ DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) { thread_state_error: DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return;); } /* * Main unprotected call handler, handles: * - * - All combinations of native/Ecmascript caller and native/Ecmascript + * - All combinations of native/ECMAScript caller and native/ECMAScript * target. * - * - Optimized Ecmascript-to-Ecmascript call where call handling only + * - Optimized ECMAScript-to-ECMAScript call where call handling only * sets up a new duk_activation but reuses an existing bytecode executor * (the caller) without native recursion. * @@ -62909,7 +63985,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, DUK_STATS_INC(thr->heap, stats_call_all); /* If a tail call: - * - an Ecmascript activation must be on top of the callstack + * - an ECMAScript activation must be on top of the callstack * - there cannot be any catch stack entries that would catch * a return */ @@ -63014,6 +64090,12 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, * Because 'act' is not zeroed, all fields must be filled in. */ + /* Should not be necessary, but initialize to silence warnings. */ + act = NULL; + nargs = 0; + nregs = 0; + vs_min_bytes = 0; + #if defined(DUK_USE_TAILCALL) use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL); if (use_tailcall) { @@ -63061,7 +64143,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, * compiler; the compiled function's parent env will contain * the (immutable) binding already. * - * This handling is now identical for C and Ecmascript functions. + * This handling is now identical for C and ECMAScript functions. * C functions always have the 'NEWENV' flag set, so their * environment record initialization is delayed (which is good). * @@ -63108,7 +64190,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) { /* - * Ecmascript call. + * ECMAScript call. */ DUK_ASSERT(func != NULL); @@ -63202,9 +64284,10 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, ; } else if (rc < 0) { duk_error_throw_from_negative_rc(thr, rc); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return 0;); } else { DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC); + DUK_WO_NORETURN(return 0;); } } DUK_ASSERT(thr->ptr_curr_pc == NULL); @@ -63292,7 +64375,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see * GH-303. Only needed for success path, error path always causes a * breakpoint recheck in the executor. It would be enough to set this - * only when returning to an Ecmascript activation, but setting the flag + * only when returning to an ECMAScript activation, but setting the flag * on every return should have no ill effect. */ #if defined(DUK_USE_DEBUGGER_SUPPORT) @@ -63404,6 +64487,7 @@ DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr, if (DUK_UNLIKELY(rc < 0)) { duk_error_throw_from_negative_rc(thr, rc); + DUK_WO_NORETURN(return;); } DUK_ASSERT(rc >= 0); @@ -63681,7 +64765,10 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr, retval = DUK_EXEC_ERROR; } #if defined(DUK_USE_CPP_EXCEPTIONS) - catch (std::exception &exc) { + catch (duk_fatal_exception &exc) { + DUK_D(DUK_DPRINT("rethrow duk_fatal_exception")); + throw; + } catch (std::exception &exc) { const char *what = exc.what(); DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff); DUK_STATS_INC(thr->heap, stats_safecall_throw); @@ -63691,6 +64778,7 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr, DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)")); try { DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what); + DUK_WO_NORETURN(return 0;); } catch (duk_internal_exception exc) { DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception")); DUK_UNREF(exc); @@ -63713,6 +64801,7 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr, DUK_STATS_INC(thr->heap, stats_safecall_throw); try { DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)"); + DUK_WO_NORETURN(return 0;); } catch (duk_internal_exception exc) { DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception")); DUK_UNREF(exc); @@ -63772,7 +64861,7 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr, /* * Property-based call (foo.noSuch()) error setup: replace target function * on stack top with a specially tagged (hidden Symbol) error which gets - * thrown in call handling at the proper spot to follow Ecmascript semantics. + * thrown in call handling at the proper spot to follow ECMAScript semantics. */ #if defined(DUK_USE_VERBOSE_ERRORS) @@ -63830,7 +64919,7 @@ DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthrea /* automatic undefs */ #undef DUK__AUGMENT_CALL_RELAX_COUNT /* - * Ecmascript compiler. + * ECMAScript compiler. * * Parses an input string and generates a function template result. * Compilation may happen in multiple contexts (global code, eval @@ -64066,9 +65155,9 @@ DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue * DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res); DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem); DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id); -DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof); +DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after); -DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token); +DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token); DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx); DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags); DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags); @@ -64240,6 +65329,7 @@ DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) { DUK_ASSERT(comp_ctx->recursion_depth >= 0); if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) { DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT); + DUK_WO_NORETURN(return;); } comp_ctx->recursion_depth++; } @@ -64294,15 +65384,20 @@ DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t e comp_ctx->curr_func.reject_regexp_in_adv = 0; regexp = 0; } + if (comp_ctx->curr_func.allow_regexp_in_adv) { + comp_ctx->curr_func.allow_regexp_in_adv = 0; + regexp = 1; + } if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) { DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld", (long) expect, (long) comp_ctx->curr_token.t)); DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR); + DUK_WO_NORETURN(return;); } /* make current token the previous; need to fiddle with valstack "backing store" */ - DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token)); + duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token)); duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx); duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx); @@ -64350,7 +65445,7 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) { entry_top = duk_get_top(thr); - DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */ + duk_memzero(func, sizeof(*func)); /* intentional overlap with earlier memzero */ #if defined(DUK_USE_EXPLICIT_NULL_INIT) func->h_name = NULL; func->h_consts = NULL; @@ -64597,7 +65692,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) { (long) code_size, (long) data_size)); duk_push_fixed_buffer_nozero(thr, data_size); - h_data = (duk_hbuffer_fixed *) duk_known_hbuffer(thr, -1); + h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1); DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data); DUK_HEAPHDR_INCREF(thr, h_data); @@ -64802,7 +65897,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) { */ #if 0 - duk_push_string(thr, "XXX"); + duk_push_literal(thr, "XXX"); duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE); #endif } @@ -65001,6 +66096,7 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) { fail_bc_limit: DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT); + DUK_WO_NORETURN(return;); } /* Update function min/max line from current token. Needed to improve @@ -65285,6 +66381,7 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f error_outofregs: DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT); + DUK_WO_NORETURN(return;); } /* For many of the helpers below it'd be technically correct to add @@ -65383,6 +66480,7 @@ DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_fl error_outofregs: DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) { @@ -65417,6 +66515,7 @@ DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, du error_outofregs: DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags) { @@ -65514,6 +66613,7 @@ DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump fail_bc_limit: DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT); + DUK_WO_NORETURN(return;); } /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional @@ -65569,6 +66669,7 @@ DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t 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_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT); + DUK_WO_NORETURN(return;); } instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname); } else { @@ -65760,6 +66861,7 @@ DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_i if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */ DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT); + DUK_WO_NORETURN(return 0;); } /* maintain highest 'used' temporary, needed to figure out nregs of function */ @@ -65819,6 +66921,7 @@ DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) { if (n > DUK__MAX_CONSTS) { DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT); + DUK_WO_NORETURN(return 0;); } DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld", @@ -65992,6 +67095,7 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx, } } } /* end switch */ + goto fail_internal; /* never here */ } case DUK_ISPEC_REGCONST: { if (forced_reg >= 0) { @@ -66024,12 +67128,13 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx, return x->regconst; } default: { - break; + break; /* never here */ } } + fail_internal: DUK_ERROR_INTERNAL(thr); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) { @@ -66102,7 +67207,10 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x break; } case DUK_OP_DIV: { - d3 = d1 / d2; + /* Division-by-zero is undefined + * behavior, so rely on a helper. + */ + d3 = duk_double_div(d1, d2); break; } case DUK_OP_EXP: { @@ -66129,7 +67237,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x } } else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) { /* Inline string concatenation. No need to check for - * symbols, as all inputs are valid Ecmascript strings. + * symbols, as all inputs are valid ECMAScript strings. */ duk_dup(thr, x->x1.valstack_idx); duk_dup(thr, x->x2.valstack_idx); @@ -66227,7 +67335,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x } DUK_ERROR_INTERNAL(thr); - return; + DUK_WO_NORETURN(return;); } /* evaluate to plain value, no forced register (temp/bound reg both ok) */ @@ -66459,6 +67567,7 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) { DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL); + DUK_WO_NORETURN(return;); } } @@ -66588,6 +67697,7 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring */ if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL); + DUK_WO_NORETURN(return;); } else { DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not " "allow a continue -> continue lookup deeper in label stack")); @@ -66597,6 +67707,7 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring /* XXX: match flag is awkward, rework */ if (!match) { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL); + DUK_WO_NORETURN(return;); } DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld", @@ -66786,6 +67897,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL); + DUK_WO_NORETURN(return;); } typedef struct { @@ -67062,13 +68174,14 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r #endif DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY); - duk__advance(comp_ctx); + duk__advance(comp_ctx); /* No RegExp after object literal. */ duk__ivalue_regconst(res, st.reg_obj); return; syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL); + DUK_WO_NORETURN(return;); } /* Parse argument list. Arguments are written to temps starting from @@ -67112,7 +68225,7 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue } /* eat the right paren */ - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */ DUK_DDD(DUK_DDDPRINT("end parsing arguments")); @@ -67245,7 +68358,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */ - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* No RegExp after parenthesized expression. */ comp_ctx->curr_func.allow_in = prev_allow_in; comp_ctx->curr_func.paren_level--; return; @@ -67380,6 +68493,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { if (comp_ctx->curr_func.is_strict) { DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER); + DUK_WO_NORETURN(return;); } DUK__SETTEMP(comp_ctx, temp_at_entry); @@ -67544,7 +68658,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { } /* end switch */ DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR); - return; + DUK_WO_NORETURN(return;); unary: { @@ -67648,10 +68762,12 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { #if defined(DUK_USE_ES6) syntax_error_newtarget: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET); + DUK_WO_NORETURN(return;); #endif syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION); + DUK_WO_NORETURN(return;); } /* XXX: add flag to indicate whether caller cares about return value; this @@ -67706,6 +68822,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i /* NB: must accept reserved words as property name */ if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) { DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER); + DUK_WO_NORETURN(return;); } res->t = DUK_IVAL_PROP; @@ -68135,7 +69252,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok)); DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR); - return; + DUK_WO_NORETURN(return;); #if 0 /* XXX: shared handling for 'duk__expr_lhs'? */ @@ -68365,7 +69482,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i * one instruction, so use explicit PC computation. */ DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based =")); - DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (duk_size_t) (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr)); + DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * (duk_int_t) sizeof(duk_compiler_instr)); reg_src = reg_varbind; } else { DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS")); @@ -68625,11 +69742,11 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION); - return; + DUK_WO_NORETURN(return;); syntax_error_lvalue: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE); - return; + DUK_WO_NORETURN(return;); } DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) { @@ -68694,7 +69811,7 @@ DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_ (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level)); - DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc)); + duk_memzero(&tmp_alloc, sizeof(tmp_alloc)); tmp->x1.valstack_idx = duk_get_top(thr); tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1; duk_push_undefined(thr); @@ -68714,6 +69831,7 @@ DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_ DUK_DDD(DUK_DDDPRINT("empty expression")); if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) { DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED); + DUK_WO_NORETURN(return;); } duk_push_undefined(thr); duk__ivalue_plain_fromstack(comp_ctx, res); @@ -68752,6 +69870,7 @@ DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_sma if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) { DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED); + DUK_WO_NORETURN(return;); } } @@ -68944,6 +70063,7 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) { @@ -69175,7 +70295,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, } DUK__SETTEMP(comp_ctx, temp_reset); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */ pc_l3 = duk__get_current_pc(comp_ctx); duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); @@ -69266,7 +70387,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); DUK__SETTEMP(comp_ctx, temp_reset); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */ pc_l3 = duk__get_current_pc(comp_ctx); duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); @@ -69315,6 +70437,7 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) { @@ -69356,7 +70479,7 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re duk__advance(comp_ctx); duk__advance_expect(comp_ctx, DUK_TOK_LPAREN); rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */ duk__advance_expect(comp_ctx, DUK_TOK_LCURLY); DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch)); @@ -69481,7 +70604,8 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re } DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY); - duk__advance(comp_ctx); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance(comp_ctx); /* Allow RegExp as part of next stmt. */ /* default case control flow patchup; note that if pc_prevcase < 0 * (i.e. no case clauses), control enters default case automatically. @@ -69514,6 +70638,7 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { @@ -69533,7 +70658,8 @@ DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */ DUK__SETTEMP(comp_ctx, temp_reset); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */ duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); @@ -69569,7 +70695,7 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d DUK_DDD(DUK_DDDPRINT("begin parsing do statement")); - duk__advance(comp_ctx); /* eat 'do' */ + duk__advance(comp_ctx); /* Eat 'do'; allow RegExp as part of next stmt. */ pc_start = duk__get_current_pc(comp_ctx); duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); @@ -69583,6 +70709,7 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d duk__emit_jump(comp_ctx, pc_start); /* no need to reset temps, as we're finished emitting code */ + comp_ctx->curr_func.allow_regexp_in_adv = 1; /* Allow RegExp as part of next stmt. */ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */ @@ -69612,7 +70739,8 @@ DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res pc_jump_false = duk__emit_jump_empty(comp_ctx); DUK__SETTEMP(comp_ctx, temp_reset); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */ duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); duk__emit_jump(comp_ctx, pc_start); @@ -69648,6 +70776,7 @@ DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk duk__advance(comp_ctx); } else { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL); + DUK_WO_NORETURN(return;); } /* Use a fast break/continue when possible. A fast break/continue is @@ -69689,6 +70818,7 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re */ if (!comp_ctx->curr_func.is_function) { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN); + DUK_WO_NORETURN(return;); } if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */ @@ -69790,6 +70920,7 @@ DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res if (comp_ctx->curr_token.lineterm) { DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW); + DUK_WO_NORETURN(return;); } reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); @@ -69846,10 +70977,9 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) /* try part */ duk__advance_expect(comp_ctx, DUK_TOK_LCURLY); - duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/); + duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/); /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */ - duk__emit_op_only(comp_ctx, - DUK_OP_ENDTRY); + duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY); if (comp_ctx->curr_token.t == DUK_TOK_CATCH) { /* @@ -69945,7 +71075,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT", (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx))); - duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/); + duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/); /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */ if (varmap_value == -2) { @@ -69987,7 +71117,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) duk__advance(comp_ctx); duk__advance_expect(comp_ctx, DUK_TOK_LCURLY); - duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/); + duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/); /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */ duk__emit_abc(comp_ctx, DUK_OP_ENDFIN, @@ -70030,6 +71160,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) syntax_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) { @@ -70040,6 +71171,7 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) if (comp_ctx->curr_func.is_strict) { DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE); + DUK_WO_NORETURN(return;); } comp_ctx->curr_func.catch_depth++; @@ -70050,7 +71182,8 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) duk__advance_expect(comp_ctx, DUK_TOK_LPAREN); duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch); - duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); + comp_ctx->curr_func.allow_regexp_in_adv = 1; + duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */ pc_trycatch = duk__get_current_pc(comp_ctx); trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING; @@ -70062,8 +71195,7 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) duk__emit_invalid(comp_ctx); /* finished jump */ duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/); - duk__emit_op_only(comp_ctx, - DUK_OP_ENDTRY); + duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY); pc_finished = duk__get_current_pc(comp_ctx); @@ -70230,13 +71362,14 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ break; } else { DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED); + DUK_WO_NORETURN(return;); } break; } case DUK_TOK_LCURLY: { DUK_DDD(DUK_DDDPRINT("block statement")); duk__advance(comp_ctx); - duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/); + duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/); /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */ if (label_id >= 0) { duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */ @@ -70490,7 +71623,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ */ if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 && - DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) { + DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) { #if defined(DUK_USE_STRICT_DECL) DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld", (long) comp_ctx->curr_func.is_strict, (long) 1)); @@ -70499,7 +71632,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring")); #endif } else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 && - DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) { + DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) { DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld", (long) comp_ctx->curr_func.is_notail, (long) 1)); comp_ctx->curr_func.is_notail = 1; @@ -70567,6 +71700,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ "even though no lineterm present before next token)")); } else { DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT); + DUK_WO_NORETURN(return;); } } } else { @@ -70615,7 +71749,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_ * (EOF or closing brace). */ -DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) { +DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after) { duk_hthread *thr = comp_ctx->thr; duk_ivalue res_alloc; duk_ivalue *res = &res_alloc; @@ -70629,7 +71763,7 @@ DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_sou * for nested functions (which may occur inside expressions). */ - DUK_MEMZERO(&res_alloc, sizeof(res_alloc)); + duk_memzero(&res_alloc, sizeof(res_alloc)); res->t = DUK_IVAL_PLAIN; res->x1.t = DUK_ISPEC_VALUE; res->x1.valstack_idx = duk_get_top(thr); @@ -70663,6 +71797,15 @@ DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_sou duk__parse_stmt(comp_ctx, res, allow_source_elem); } + /* RegExp is allowed / not allowed depending on context. For function + * declarations RegExp is allowed because it follows a function + * declaration statement and may appear as part of the next statement. + * For function expressions RegExp is not allowed, and it's possible + * to do something like '(function () {} / 123)'. + */ + if (regexp_after) { + comp_ctx->curr_func.allow_regexp_in_adv = 1; + } duk__advance(comp_ctx); /* Tear down state. */ @@ -70986,13 +72129,11 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct error_outofregs: DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT); - DUK_UNREACHABLE(); - return; + DUK_WO_NORETURN(return;); error_argname: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME); - DUK_UNREACHABLE(); - return; + DUK_WO_NORETURN(return;); } /* @@ -71029,7 +72170,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct * token (EOF or closing brace). */ -DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) { +DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token) { duk_compiler_func *func; duk_hthread *thr; duk_regconst_t reg_stmt_value = -1; @@ -71101,7 +72242,9 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec func->max_line = 0; #endif - /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */ + /* duk__parse_stmts() expects curr_tok to be set; parse in "allow + * regexp literal" mode with current strictness. + */ if (expect_token >= 0) { /* Eating a left curly; regexp mode is allowed by left curly * based on duk__token_lbp[] automatically. @@ -71120,7 +72263,8 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec DUK_DDD(DUK_DDDPRINT("begin 1st pass")); duk__parse_stmts(comp_ctx, 1, /* allow source elements */ - expect_eof); /* expect EOF instead of } */ + expect_eof, /* expect EOF instead of } */ + regexp_after); /* regexp after */ DUK_DDD(DUK_DDDPRINT("end 1st pass")); /* @@ -71227,7 +72371,8 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec DUK_DDD(DUK_DDDPRINT("begin 2nd pass")); duk__parse_stmts(comp_ctx, 1, /* allow source elements */ - expect_eof); /* expect EOF instead of } */ + expect_eof, /* expect EOF instead of } */ + regexp_after); /* regexp after */ DUK_DDD(DUK_DDDPRINT("end 2nd pass")); duk__update_lineinfo_currtoken(comp_ctx); @@ -71240,6 +72385,7 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec /* Should never happen but avoid infinite loop just in case. */ DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen")); DUK_ERROR_INTERNAL(thr); + DUK_WO_NORETURN(return;); } DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round)); } @@ -71283,6 +72429,7 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec error_funcname: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME); + DUK_WO_NORETURN(return;); } /* @@ -71331,6 +72478,7 @@ DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) { if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) { DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER); + DUK_WO_NORETURN(return;); } DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER); DUK_ASSERT(comp_ctx->curr_token.str1 != NULL); @@ -71396,6 +72544,7 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui duk_to_string(thr, -1); } else { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME); + DUK_WO_NORETURN(return;); } comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */ } else { @@ -71413,6 +72562,7 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui no_advance = 1; if (flags & DUK__FUNC_FLAG_DECL) { DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED); + DUK_WO_NORETURN(return;); } } } @@ -71446,6 +72596,7 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui duk__parse_func_body(comp_ctx, 0, /* expect_eof */ 0, /* implicit_return_value */ + flags & DUK__FUNC_FLAG_DECL, /* regexp_after */ DUK_TOK_LCURLY); /* expect_token */ /* @@ -71498,6 +72649,14 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */ comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */ duk__advance(comp_ctx); + + /* RegExp is not allowed after a function expression, e.g. in + * (function () {} / 123). A RegExp *is* allowed after a + * function declaration! + */ + if (flags & DUK__FUNC_FLAG_DECL) { + comp_ctx->curr_func.allow_regexp_in_adv = 1; + } duk__advance_expect(comp_ctx, DUK_TOK_RCURLY); return fnum; @@ -71512,9 +72671,9 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld", (long) entry_top, (long) comp_ctx->curr_token.start_offset)); - DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func)); + duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func)); - DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func)); + duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func)); duk__init_func_valstack_slots(comp_ctx); DUK_ASSERT(comp_ctx->curr_func.num_formals == 0); @@ -71556,6 +72715,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm if (fnum > DUK__MAX_FUNCS) { DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT); + DUK_WO_NORETURN(return 0;); } /* array writes autoincrement length */ @@ -71580,7 +72740,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm } else { duk_set_top(thr, entry_top); } - DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func)); + duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func)); return fnum; } @@ -71589,7 +72749,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm * Compile input string into an executable function template without * arguments. * - * The string is parsed as the "Program" production of Ecmascript E5. + * The string is parsed as the "Program" production of ECMAScript E5. * Compilation context can be either global code or eval code (see E5 * Sections 14 and 15.1.2.1). * @@ -71730,6 +72890,7 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) { duk__parse_func_body(comp_ctx, 1, /* expect_eof */ 1, /* implicit_return_value */ + 1, /* regexp_after (does not matter) */ -1); /* expect_token */ } @@ -71757,7 +72918,7 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer DUK_ASSERT(src_buffer != NULL); /* preinitialize lexer state partially */ - DUK_MEMZERO(&comp_stk, sizeof(comp_stk)); + duk_memzero(&comp_stk, sizeof(comp_stk)); comp_stk.flags = flags; DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex); comp_stk.comp_ctx_alloc.lex.input = src_buffer; @@ -71774,6 +72935,7 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer if (safe_rc != DUK_EXEC_SUCCESS) { DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1))); (void) duk_throw(thr); + DUK_WO_NORETURN(return;); } /* [ ... template ] */ @@ -71864,7 +73026,7 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer #undef DUK__TOKEN_LBP_FLAG_UNUSED #undef DUK__TOKEN_LBP_GET_BP /* - * Ecmascript bytecode executor. + * ECMAScript bytecode executor. */ /* #include duk_internal.h -> already included */ @@ -71915,7 +73077,7 @@ DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, d tv_dst = thr->valstack_top; copy_size = sizeof(duk_tval) * count; - DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, copy_size); + duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size); for (i = 0; i < count; i++) { DUK_TVAL_INCREF(thr, tv_dst); tv_dst++; @@ -72179,7 +73341,10 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv break; } case DUK_OP_DIV >> 2: { - du.d = d1 / d2; + /* Division-by-zero is undefined behavior, so + * rely on a helper. + */ + du.d = duk_double_div(d1, d2); break; } case DUK_OP_MOD >> 2: { @@ -72636,7 +73801,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, * top are combined into one pass. */ -/* Reconfigure value stack for return to an Ecmascript function at +/* Reconfigure value stack for return to an ECMAScript function at * callstack top (caller unwinds). */ DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) { @@ -72652,7 +73817,7 @@ DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) { /* Clamp so that values at 'clamp_top' and above are wiped and won't * retain reachable garbage. Then extend to 'nregs' because we're - * returning to an Ecmascript function. + * returning to an ECMAScript function. */ h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act); @@ -72668,7 +73833,7 @@ DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) { /* XXX: a best effort shrink check would be OK here */ } -/* Reconfigure value stack for an Ecmascript catcher. Use topmost catcher +/* Reconfigure value stack for an ECMAScript catcher. Use topmost catcher * in 'act'. */ DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) { @@ -72904,7 +74069,7 @@ DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tva act_resumer = resumer->callstack_curr; DUK_ASSERT(act_resumer != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL); - DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer))); /* resume caller must be an ecmascript func */ + DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer))); /* resume caller must be an ECMAScript func */ tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff); /* return value from Duktape.Thread.resume() */ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */ /* XXX: avoid side effects */ @@ -72960,7 +74125,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */ DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */ - DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */ + DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */ DUK_ASSERT(thr->callstack_curr != NULL); DUK_ASSERT(thr->callstack_curr->parent != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL && @@ -72978,7 +74143,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE || resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */ DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED || - resumee->callstack_top >= 2); /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */ + resumee->callstack_top >= 2); /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */ DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED || (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL && DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) && @@ -73016,8 +74181,8 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation goto check_longjmp; } else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) { /* Unwind previous Duktape.Thread.yield() call. The - * activation remaining must always be an Ecmascript - * call now (yield() accepts calls from Ecmascript + * activation remaining must always be an ECMAScript + * call now (yield() accepts calls from ECMAScript * only). */ duk_activation *act_resumee; @@ -73025,7 +74190,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation DUK_ASSERT(resumee->callstack_top >= 2); act_resumee = resumee->callstack_curr; /* Duktape.Thread.yield() */ DUK_ASSERT(act_resumee != NULL); - act_resumee = act_resumee->parent; /* Ecmascript call site for yield() */ + act_resumee = act_resumee->parent; /* ECMAScript call site for yield() */ DUK_ASSERT(act_resumee != NULL); tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff); /* return value from Duktape.Thread.yield() */ @@ -73073,6 +74238,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation * executor which can be quite misleading. */ DUK_ERROR_INTERNAL(thr); + DUK_WO_NORETURN(return 0;); } DUK_ASSERT(resumee->resumer == NULL); @@ -73095,7 +74261,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation case DUK_LJ_TYPE_YIELD: { /* * Currently only allowed only if yielding thread has only - * Ecmascript activations (except for the Duktape.Thread.yield() + * ECMAScript activations (except for the Duktape.Thread.yield() * call at the callstack top) and none of them constructor * calls. * @@ -73111,27 +74277,27 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */ #endif DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */ - DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.yield() activation */ + DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.yield() activation */ DUK_ASSERT(thr->callstack_curr != NULL); DUK_ASSERT(thr->callstack_curr->parent != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL && DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) && ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield); DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL && - DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* an Ecmascript function */ + DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* an ECMAScript function */ resumer = thr->resumer; DUK_ASSERT(resumer != NULL); DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */ - DUK_ASSERT(resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */ + DUK_ASSERT(resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */ DUK_ASSERT(resumer->callstack_curr != NULL); DUK_ASSERT(resumer->callstack_curr->parent != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL && DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) && ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume); DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL && - DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent))); /* an Ecmascript function */ + DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent))); /* an ECMAScript function */ if (thr->heap->lj.iserror) { thr->state = DUK_HTHREAD_STATE_YIELDED; @@ -73185,7 +74351,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation * resumer in this case.) * * Note: until we hit the entry level, there can only be - * Ecmascript activations. + * ECMAScript activations. */ duk_activation *act; @@ -73252,11 +74418,11 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation */ DUK_ASSERT(thr->resumer != NULL); - DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */ + DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */ DUK_ASSERT(thr->resumer->callstack_curr != NULL); DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL && - DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an Ecmascript function */ + DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */ resumer = thr->resumer; @@ -73309,8 +74475,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation * infinite loop in this catchpoint. */ DUK_ERROR_INTERNAL(thr); - DUK_UNREACHABLE(); - return retval; + DUK_WO_NORETURN(return 0;); } /* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE @@ -73374,7 +74539,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr /* Should never happen, but be robust. */ DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error")); DUK_ERROR_INTERNAL(thr); - return; + DUK_WO_NORETURN(return;); } /* Handle a RETURN opcode. Avoid using longjmp() for return handling because @@ -73409,7 +74574,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation * * 2. The return happens at the entry level of the bytecode * executor, so return from the executor (in C stack). * - * 3. There is a calling (Ecmascript) activation in the call + * 3. There is a calling (ECMAScript) activation in the call * stack => return to it, in the same executor instance. * * 4. There is no calling activation, and the thread is @@ -73454,16 +74619,16 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation * } if (thr->callstack_top >= 2) { - /* There is a caller; it MUST be an Ecmascript caller (otherwise it would + /* There is a caller; it MUST be an ECMAScript caller (otherwise it would * match entry_act check). */ - DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, retval_byteoff=%ld, lj_value1=%!T", + DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T", (long) (thr->callstack_curr->parent->retval_byteoff), (duk_tval *) &thr->heap->lj.value1)); DUK_ASSERT(thr->callstack_curr != NULL); DUK_ASSERT(thr->callstack_curr->parent != NULL); - DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* must be ecmascript */ + DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* must be ECMAScript */ #if defined(DUK_USE_ES6_PROXY) if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) { @@ -73493,14 +74658,14 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation * DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)")); DUK_ASSERT(thr->resumer != NULL); - DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */ + DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */ DUK_ASSERT(thr->resumer->callstack_curr != NULL); DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL); DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL && DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) && ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */ DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL && - DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an Ecmascript function */ + DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */ DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED); @@ -73547,7 +74712,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation * #else /* Without coroutine support this case should never happen. */ DUK_ERROR_INTERNAL(thr); - return DUK__RETHAND_FINISHED; /* not executed */ + DUK_WO_NORETURN(return 0;); #endif } @@ -73697,7 +74862,7 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_ if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) { /* Monotonic time should not experience time jumps, * but the provider may be missing and we're actually - * using Ecmascript time. So, tolerate negative values + * using ECMAScript time. So, tolerate negative values * so that a time jump works reasonably. * * Same interval is now used for status sending and @@ -73846,6 +75011,7 @@ DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(d thr->interrupt_counter = 0; DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap); DUK_ERROR_RANGE(thr, "execution timeout"); + DUK_WO_NORETURN(return 0;); } #endif /* DUK_USE_EXEC_TIMEOUT_CHECK */ @@ -74531,7 +75697,7 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, } /* - * Ecmascript bytecode executor. + * ECMAScript bytecode executor. * * Resume execution for the current thread from its current activation. * Returns when execution would return from the entry level activation, @@ -74540,7 +75706,7 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, * a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level * setjmp() jmpbuf. * - * Ecmascript function calls and coroutine resumptions are handled + * ECMAScript function calls and coroutine resumptions are handled * internally (by the outer executor function) without recursive C calls. * Other function calls are handled using duk_handle_call(), increasing * C recursion depth. @@ -74633,6 +75799,7 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS) #define DUK__INTERNAL_ERROR(msg) do { \ DUK_ERROR_ERROR(thr, (msg)); \ + DUK_WO_NORETURN(return;); \ } while (0) #else #define DUK__INTERNAL_ERROR(msg) do { \ @@ -74797,7 +75964,10 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { entry_jmpbuf_ptr); } #if defined(DUK_USE_CPP_EXCEPTIONS) - catch (std::exception &exc) { + catch (duk_fatal_exception &exc) { + DUK_D(DUK_DPRINT("rethrow duk_fatal_exception")); + throw; + } catch (std::exception &exc) { const char *what = exc.what(); if (!what) { what = "unknown"; @@ -74807,6 +75977,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { try { DUK_ASSERT(heap->curr_thread != NULL); DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what); + DUK_WO_NORETURN(return;); } catch (duk_internal_exception exc) { DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception")); DUK_UNREF(exc); @@ -74821,6 +75992,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { try { DUK_ASSERT(heap->curr_thread != NULL); DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)"); + DUK_WO_NORETURN(return;); } catch (duk_internal_exception exc) { DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception")); DUK_UNREF(exc); @@ -74833,7 +76005,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { #endif } - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return;); } /* Inner executor, performance critical. */ @@ -75202,7 +76374,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread * /* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */ val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1); #endif - val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */ + val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */ DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */ break; } @@ -76857,7 +78029,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread * case DUK_OP_INVLHS: { DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE); - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return;); break; } @@ -76892,45 +78064,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread * case DUK_OP_INVALID: { DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins)); + DUK_WO_NORETURN(return;); break; } #if defined(DUK_USE_ES6) case DUK_OP_NEWTARGET: { - /* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation - * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget - * - * No newTarget support now, so as a first approximation - * use the resolved (non-bound) target function. - */ - /* XXX: C API: push_new_target()? */ - duk_activation *act; - - act = thr->callstack_curr; - DUK_ASSERT(act != NULL); - - /* Check CONSTRUCT flag from current function, or if running - * direct eval, from a non-direct-eval parent (with possibly - * more than one nested direct eval). An alternative to this - * would be to store [[NewTarget]] as a hidden symbol of the - * lexical scope, and then just look up that variable. - */ - for (;;) { - if (act == NULL) { - duk_push_undefined(thr); - break; - } - if (act->flags & DUK_ACT_FLAG_CONSTRUCT) { - duk_push_tval(thr, &act->tv_func); - break; - } else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) { - act = act->parent; - } else { - duk_push_undefined(thr); - break; - } - } - + duk_push_new_target(thr); DUK__REPLACE_TOP_BC_BREAK(); } #endif /* DUK_USE_ES6 */ @@ -77032,11 +78172,12 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread * continue; #endif } - DUK_UNREACHABLE(); + DUK_WO_NORETURN(return;); #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS) internal_error: DUK_ERROR_INTERNAL(thr); + DUK_WO_NORETURN(return;); #endif } @@ -77105,9 +78246,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread * #undef DUK__SYNC_CURR_PC #undef DUK__TVAL_SHIFT /* - * Ecmascript specification algorithm and conversion helpers. + * ECMAScript specification algorithm and conversion helpers. * - * These helpers encapsulate the primitive Ecmascript operation semantics, + * These helpers encapsulate the primitive ECMAScript operation semantics, * and are used by the bytecode executor and the API (among other places). * Some primitives are only implemented as part of the API and have no * "internal" helper. This is the case when an internal helper would not @@ -77323,6 +78464,7 @@ DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) { duk_hstring *h = DUK_TVAL_GET_STRING(tv); if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) { DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL); + DUK_WO_NORETURN(return 0.0;); } duk_push_hstring(thr, h); return duk__tonumber_string_raw(thr); @@ -77538,7 +78680,7 @@ DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) { return 0; #else /* DUK_USE_PARANOID_MATH */ /* Better equivalent algorithm. If the compiler is compliant, C and - * Ecmascript semantics are identical for this particular comparison. + * ECMAScript semantics are identical for this particular comparison. * In particular, NaNs must never compare equal and zeroes must compare * equal regardless of sign. Could also use a macro, but this inlines * already nicely (no difference on gcc, for instance). @@ -77831,12 +78973,12 @@ DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const prefix_len = (len1 <= len2 ? len1 : len2); - /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length - * inputs so no zero length check is needed. + /* duk_memcmp() is guaranteed to return zero (equal) for zero length + * inputs. */ - rc = DUK_MEMCMP((const void *) buf1, - (const void *) buf2, - (size_t) prefix_len); + rc = duk_memcmp_unsafe((const void *) buf1, + (const void *) buf2, + (size_t) prefix_len); if (rc < 0) { return -1; @@ -78103,22 +79245,19 @@ DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, */ /* - * E5 Section 11.8.6 describes the main algorithm, which uses - * [[HasInstance]]. [[HasInstance]] is defined for only - * function objects: - * - * - Normal functions: - * E5 Section 15.3.5.3 - * - Functions established with Function.prototype.bind(): - * E5 Section 15.3.4.5.3 + * ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm + * which covers both bound and non-bound functions; in effect the algorithm + * includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3. * - * For other objects, a TypeError is thrown. + * ES2015 Section 12.9.4 describes the instanceof operator which first + * checks @@hasInstance well-known symbol and falls back to + * OrdinaryHasInstance(). * * 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) { +DUK_LOCAL duk_bool_t duk__js_instanceof_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_bool_t skip_sym_check) { duk_hobject *func; duk_hobject *val; duk_hobject *proto; @@ -78141,6 +79280,23 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ func = duk_require_hobject(thr, -1); DUK_ASSERT(func != NULL); +#if defined(DUK_USE_SYMBOL_BUILTIN) + /* + * @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4. + */ + if (!skip_sym_check) { + if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) { + /* [ ... lhs rhs func ] */ + duk_insert(thr, -3); /* -> [ ... func lhs rhs ] */ + duk_swap_top(thr, -2); /* -> [ ... func rhs(this) lhs ] */ + duk_call_method(thr, 1); + return duk_to_boolean_top_pop(thr); + } + } +#else + DUK_UNREF(skip_sym_check); +#endif + /* * For bound objects, [[HasInstance]] just calls the target function * [[HasInstance]]. If that is again a bound object, repeat until @@ -78152,7 +79308,7 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ if (!DUK_HOBJECT_IS_CALLABLE(func)) { /* - * Note: of native Ecmascript objects, only Function instances + * Note: of native ECMAScript objects, only Function instances * have a [[HasInstance]] internal property. Custom objects might * also have it, but not in current implementation. * @@ -78162,7 +79318,7 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ } if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) { - duk_push_tval(thr, &((duk_hboundfunc *) func)->target); + duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target); duk_replace(thr, -2); func = duk_require_hobject(thr, -1); /* lightfunc throws */ @@ -78267,6 +79423,7 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ if (DUK_UNLIKELY(sanity == 0)) { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } DUK_UNREACHABLE(); @@ -78284,15 +79441,25 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ error_invalid_rval: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL); - return 0; + DUK_WO_NORETURN(return 0;); #if defined(DUK_USE_VERBOSE_ERRORS) error_invalid_rval_noproto: DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO); - return 0; + DUK_WO_NORETURN(return 0;); #endif } +#if defined(DUK_USE_SYMBOL_BUILTIN) +DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) { + return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/); +} +#endif + +DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) { + return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/); +} + /* * in */ @@ -78543,7 +79710,7 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) { * be used for most identifier accesses. Consequently, these slow path * primitives should be optimized for maximum compactness. * - * Ecmascript environment records (declarative and object) are represented + * ECMAScript environment records (declarative and object) are represented * as internal objects with control keys. Environment records have a * parent record ("outer environment reference") which is represented by * the implicit prototype for technical reasons (in other words, it is a @@ -78585,7 +79752,7 @@ typedef struct { * Create a new function object based on a "template function" which contains * compiled bytecode, constants, etc, but lacks a lexical environment. * - * Ecmascript requires that each created closure is a separate object, with + * ECMAScript requires that each created closure is a separate object, with * its own set of editable properties. However, structured property values * (such as the formal arguments list and the variable map) are shared. * Also the bytecode, constants, and inner functions are shared. @@ -79594,6 +80761,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr, if (DUK_UNLIKELY(sanity-- == 0)) { DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT); + DUK_WO_NORETURN(return 0;); } env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); } @@ -79733,6 +80901,7 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr, DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR, "identifier '%s' undefined", (const char *) DUK_HSTRING_GET_DATA(name)); + DUK_WO_NORETURN(return 0;); } return 0; @@ -79857,6 +81026,7 @@ void duk__putvar_helper(duk_hthread *thr, DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR, "identifier '%s' undefined", (const char *) DUK_HSTRING_GET_DATA(name)); + DUK_WO_NORETURN(return;); } DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global")); @@ -80247,7 +81417,7 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr, fail_existing_attributes: fail_not_extensible: DUK_ERROR_TYPE(thr, "declaration failed"); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_INTERNAL @@ -80292,7 +81462,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * Lexer for source files, ToNumber() string conversions, RegExp expressions, * and JSON. * - * Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer. The + * Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer. The * caller can also rewind the token stream into a certain position which is * needed by the compiler part for multi-pass scanning. Tokens are * represented as duk_token structures, and contain line number information. @@ -80315,14 +81485,14 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * * Token parsing supports the full range of Unicode characters as described * in the E5 specification. Parsing has been optimized for ASCII characters - * because ordinary Ecmascript code consists almost entirely of ASCII + * because ordinary ECMAScript code consists almost entirely of ASCII * characters. Matching of complex Unicode codepoint sets (such as in the * IdentifierStart and IdentifierPart productions) is optimized for size, * and is done using a linear scan of a bit-packed list of ranges. This is * very slow, but should never be entered unless the source code actually * contains Unicode characters. * - * Ecmascript tokenization is partially context sensitive. First, + * ECMAScript tokenization is partially context sensitive. First, * additional future reserved words are recognized in strict mode (see E5 * Section 7.6.1.2). Second, a forward slash character ('/') can be * recognized either as starting a RegExp literal or as a division operator, @@ -80419,7 +81589,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * * * In particular, surrogate pairs are allowed and not combined, which * allows source files to represent all SourceCharacters with CESU-8. - * Broken surrogate pairs are allowed, as Ecmascript does not mandate + * Broken surrogate pairs are allowed, as ECMAScript does not mandate * their validation. * * * Allow non-shortest UTF-8 encodings. @@ -80427,20 +81597,20 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * Leniency here causes few security concerns because all character data is * decoded into Unicode codepoints before lexer processing, and is then * re-encoded into CESU-8. The source can be parsed as strict UTF-8 with - * a compiler option. However, Ecmascript source characters include -all- + * a compiler option. However, ECMAScript source characters include -all- * 16-bit unsigned integer codepoints, so leniency seems to be appropriate. * * Note that codepoints above the BMP are not strictly SourceCharacters, * but the lexer still accepts them as such. Before ending up in a string * or an identifier name, codepoints above BMP are converted into surrogate * pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as - * expected by Ecmascript. + * expected by ECMAScript. * * An alternative approach to dealing with invalid or partial sequences * would be to skip them and replace them with e.g. the Unicode replacement * character U+FFFD. This has limited utility because a replacement character * will most likely cause a parse error, unless it occurs inside a string. - * Further, Ecmascript source is typically pure ASCII. + * Further, ECMAScript source is typically pure ASCII. * * See: * @@ -80603,6 +81773,7 @@ DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t s lex_ctx->input_line = input_line; DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED); + DUK_WO_NORETURN(return;); } DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) { @@ -80625,7 +81796,7 @@ DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count /* 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, + duk_memmove((void *) lex_ctx->buffer, (const void *) lex_ctx->window, (size_t) avail_bytes); lex_ctx->window = lex_ctx->buffer; @@ -80763,7 +81934,7 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) { error_clipped: /* clipped codepoint */ error_encoding: /* invalid codepoint encoding or codepoint */ DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED); - return 0; + DUK_WO_NORETURN(return 0;); } DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) { @@ -80776,7 +81947,7 @@ DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count /* Zero 'count' is also allowed to make call sites easier. */ keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes; - DUK_MEMMOVE((void *) lex_ctx->window, + duk_memmove((void *) lex_ctx->window, (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes), (size_t) keep_bytes); @@ -80865,7 +82036,7 @@ DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valst DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) { DUK_ASSERT(lex_ctx != NULL); - DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx)); + duk_memzero(lex_ctx, sizeof(*lex_ctx)); #if defined(DUK_USE_EXPLICIT_NULL_INIT) #if defined(DUK_USE_LEXER_SLIDING_WINDOW) lex_ctx->window = NULL; @@ -81030,6 +82201,7 @@ DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bo fail_escape: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE); + DUK_WO_NORETURN(return 0;); } /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377. Maximum @@ -81226,11 +82398,11 @@ DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token fail_escape: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE); - return; + DUK_WO_NORETURN(return;); fail_unterminated: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING); - return; + DUK_WO_NORETURN(return;); } /* Skip to end-of-line (or end-of-file), used for single line comments. */ @@ -81247,7 +82419,7 @@ DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) { } /* - * Parse Ecmascript source InputElementDiv or InputElementRegExp + * Parse ECMAScript source InputElementDiv or InputElementRegExp * (E5 Section 7), skipping whitespace, comments, and line terminators. * * Possible results are: @@ -81274,13 +82446,13 @@ DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) { * lookup window to quickly determine which production is the -longest- * matching one, and then parse that. The top-level if-else clauses * match the first character, and the code blocks for each clause - * handle -all- alternatives for that first character. Ecmascript + * handle -all- alternatives for that first character. ECMAScript * specification uses the "longest match wins" semantics, so the order * of the if-clauses matters. * * Misc notes: * - * * Ecmascript numeric literals do not accept a sign character. + * * ECMAScript numeric literals do not accept a sign character. * Consequently e.g. "-1.0" is parsed as two tokens: a negative * sign and a positive numeric literal. The compiler performs * the negation during compilation, so this has no adverse impact. @@ -81790,7 +82962,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, * (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not * used now). The compiler needs to work around this. * - * Strictly speaking, following Ecmascript longest match + * Strictly speaking, following ECMAScript longest match * specification, an invalid escape for the first character * should cause a syntax error. However, an invalid escape * for IdentifierParts should just terminate the identifier @@ -82074,32 +83246,32 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, fail_token_limit: DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT); - return; + DUK_WO_NORETURN(return;); fail_token: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN); - return; + DUK_WO_NORETURN(return;); fail_number_literal: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL); - return; + DUK_WO_NORETURN(return;); fail_escape: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE); - return; + DUK_WO_NORETURN(return;); fail_unterm_regexp: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP); - return; + DUK_WO_NORETURN(return;); fail_unterm_comment: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT); - return; + DUK_WO_NORETURN(return;); #if !defined(DUK_USE_REGEXP_SUPPORT) fail_regexp_support: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED); - return; + DUK_WO_NORETURN(return;); #endif } @@ -82122,7 +83294,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token goto fail_token_limit; } - DUK_MEMZERO(out_token, sizeof(*out_token)); + duk_memzero(out_token, sizeof(*out_token)); x = DUK__L0(); y = DUK__L1(); @@ -82447,24 +83619,24 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token fail_token_limit: DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT); - return; + DUK_WO_NORETURN(return;); fail_escape: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE); - return; + DUK_WO_NORETURN(return;); fail_group: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP); - return; + DUK_WO_NORETURN(return;); #if !defined(DUK_USE_ES6_REGEXP_SYNTAX) fail_invalid_char: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER); - return; + DUK_WO_NORETURN(return;); fail_quantifier: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER); - return; + DUK_WO_NORETURN(return;); #endif } @@ -82713,15 +83885,15 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range fail_escape: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE); - return; + DUK_WO_NORETURN(return;); fail_range: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE); - return; + DUK_WO_NORETURN(return;); fail_unterm_charclass: DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS); - return; + DUK_WO_NORETURN(return;); } #endif /* DUK_USE_REGEXP_SUPPORT */ @@ -82882,10 +84054,8 @@ DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) { n = y->n; x->n = n; - if (n == 0) { - return; - } - DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n)); + /* No need to special case n == 0. */ + duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n)); } DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) { @@ -83161,7 +84331,7 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) { return; } - DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx)); + duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx)); x->n = nx; nz = z->n; @@ -83311,7 +84481,7 @@ DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) { n = (y / 32) + 1; DUK_ASSERT(n > 0); r = y % 32; - DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * (size_t) n); + duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n); x->n = n; x->v[n - 1] = (((duk_uint32_t) 1) << r); } @@ -83425,6 +84595,7 @@ DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x duk_small_int_t dig; duk_uint32_t t; + DUK_ASSERT(buf != NULL); DUK_ASSERT(radix >= 2 && radix <= 36); /* A 32-bit unsigned integer formats to at most 32 digits (the @@ -83447,7 +84618,7 @@ DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x } len = (duk_size_t) ((buf + 32) - p); - DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len); + duk_memmove((void *) buf, (const void *) p, (size_t) len); return len; } @@ -83850,7 +85021,7 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) { { duk_uint8_t buf[2048]; duk_small_int_t i, t; - DUK_MEMZERO(buf, sizeof(buf)); + duk_memzero(buf, sizeof(buf)); for (i = 0; i < nc_ctx->count; i++) { t = nc_ctx->digits[i]; if (t < 0 || t > 36) { @@ -83915,7 +85086,7 @@ DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify *p = 0; if (p == &nc_ctx->digits[0]) { DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling")); - DUK_MEMMOVE((void *) (&nc_ctx->digits[1]), + duk_memmove((void *) (&nc_ctx->digits[1]), (const void *) (&nc_ctx->digits[0]), (size_t) (sizeof(char) * (size_t) nc_ctx->count)); nc_ctx->digits[0] = 1; /* don't increase 'count' */ @@ -83959,7 +85130,7 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx, duk_uint8_t *buf; /* - * The string conversion here incorporates all the necessary Ecmascript + * The string conversion here incorporates all the necessary ECMAScript * semantics without attempting to be generic. nc_ctx->digits contains * nc_ctx->count digits (>= 1), with the topmost digit's 'position' * indicated by nc_ctx->k as follows: @@ -83970,11 +85141,11 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx, * digits="123" count=3 k=-1 --> 0.0123 * * Note that the identifier names used for format selection are different - * in Burger-Dybvig paper and Ecmascript specification (quite confusingly + * in Burger-Dybvig paper and ECMAScript specification (quite confusingly * so, because e.g. 'k' has a totally different meaning in each). See * documentation for discussion. * - * Ecmascript doesn't specify any specific behavior for format selection + * ECMAScript doesn't specify any specific behavior for format selection * (e.g. when to use exponent notation) for non-base-10 numbers. * * The bigint space in the context is reused for string output, as there @@ -84058,7 +85229,7 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx, /* Exponent */ if (expt != DUK__NO_EXP) { /* - * Exponent notation for non-base-10 numbers isn't specified in Ecmascript + * Exponent notation for non-base-10 numbers isn't specified in ECMAScript * specification, as it never explicitly turns up: non-decimal numbers can * only be formatted with Number.prototype.toString([radix]) and for that, * behavior is not explicitly specified. @@ -84160,7 +85331,7 @@ DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, du * (perhaps because the low part is set (seemingly) conditionally in a * loop), so this is here to avoid the bogus warning. */ - DUK_MEMZERO((void *) &u, sizeof(u)); + duk_memzero((void *) &u, sizeof(u)); /* * Figure out how generated digits match up with the mantissa, @@ -84343,7 +85514,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, * sprintf "%lu" for the fast path and for exponent formatting. */ - uval = (unsigned int) x; + uval = duk_double_to_uint32_t(x); if (((double) uval) == x && /* integer number in range */ flags == 0) { /* no special formatting */ /* use bigint area as a temp */ @@ -84375,7 +85546,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, * is 1-2 kilobytes and nothing should rely on it being zeroed. */ #if 0 - DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */ + duk_memzero((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */ #endif nc_ctx->is_s2n = 0; @@ -84415,7 +85586,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, } DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count)); DUK_ASSERT(count >= 1); - DUK_MEMZERO((void *) nc_ctx->digits, (size_t) count); + duk_memzero((void *) nc_ctx->digits, (size_t) count); nc_ctx->count = count; nc_ctx->k = 1; /* 0.000... */ neg = 0; @@ -84495,8 +85666,8 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc; duk_double_t res; duk_hstring *h_str; - duk_small_int_t expt; - duk_small_int_t expt_neg; + duk_int_t expt; + duk_bool_t expt_neg; duk_small_int_t expt_adj; duk_small_int_t neg; duk_small_int_t dig; @@ -84632,7 +85803,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk * accuracy, so that Dragon4 will generate enough binary output digits. * For decimal numbers, this means generating a 20-digit significand, * which should yield enough practical accuracy to parse IEEE doubles. - * In fact, the Ecmascript specification explicitly allows an + * In fact, the ECMAScript specification explicitly allows an * implementation to treat digits beyond 20 as zeroes (and even * to round the 20th digit upwards). For non-decimal numbers, the * appropriate number of digits has been precomputed for comparable @@ -84803,9 +85974,10 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk } else { /* exponent digit */ + DUK_ASSERT(radix == 10); expt = expt * radix + dig; if (expt > DUK_S2N_MAX_EXPONENT) { - /* impose a reasonable exponent limit, so that exp + /* Impose a reasonable exponent limit, so that exp * doesn't need to get tracked using a bigint. */ DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large")); @@ -85008,7 +86180,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk parse_explimit_error: DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value")); DUK_ERROR_RANGE(thr, "exponent too large"); - return; + DUK_WO_NORETURN(return;); } /* automatic undefs */ @@ -85549,6 +86721,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex if (re_ctx->recursion_depth >= re_ctx->recursion_limit) { DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT); + DUK_WO_NORETURN(return;); } re_ctx->recursion_depth++; @@ -85622,9 +86795,11 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex case DUK_RETOK_QUANTIFIER: { if (atom_start_offset < 0) { DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM); + DUK_WO_NORETURN(return;); } if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) { DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES); + DUK_WO_NORETURN(return;); } if (atom_char_length >= 0) { /* @@ -85693,6 +86868,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex re_ctx->curr_token.qmin : re_ctx->curr_token.qmax; if (atom_copies > DUK_RE_MAX_ATOM_COPIES) { DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES); + DUK_WO_NORETURN(return;); } /* wipe the capture range made by the atom (if any) */ @@ -85956,17 +87132,20 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex case DUK_RETOK_ATOM_END_GROUP: { if (expect_eof) { DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN); + DUK_WO_NORETURN(return;); } goto done; } case DUK_RETOK_EOF: { if (!expect_eof) { DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN); + DUK_WO_NORETURN(return;); } goto done; } default: { DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN); + DUK_WO_NORETURN(return;); } } @@ -86061,7 +87240,7 @@ DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) flags_error: DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS); - return 0; /* never here */ + DUK_WO_NORETURN(return 0U;); } /* @@ -86098,7 +87277,7 @@ DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) { n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); if (n == 0) { - duk_push_string(thr, "(?:)"); + duk_push_literal(thr, "(?:)"); return; } @@ -86178,7 +87357,7 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { /* [ ... pattern flags escaped_source buffer ] */ - DUK_MEMZERO(&re_ctx, sizeof(re_ctx)); + duk_memzero(&re_ctx, sizeof(re_ctx)); DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */ re_ctx.thr = thr; re_ctx.lex.thr = thr; @@ -86225,6 +87404,7 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { if (re_ctx.highest_backref > re_ctx.captures) { DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS); + DUK_WO_NORETURN(return;); } /* @@ -86308,7 +87488,7 @@ DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) { /* * Regexp executor. * - * Safety: the Ecmascript executor should prevent user from reading and + * Safety: the ECMAScript executor should prevent user from reading and * replacing regexp bytecode. Even so, the executor must validate all * memory accesses etc. When an invalid access is detected (e.g. a 'save' * opcode to invalid, unallocated index) it should fail with an internal @@ -86375,7 +87555,7 @@ DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uin fail: DUK_ERROR_INTERNAL(thr); - return NULL; /* never here */ + DUK_WO_NORETURN(return NULL;); } DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) { @@ -86406,7 +87586,7 @@ DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8 fail: DUK_ERROR_INTERNAL(thr); - return NULL; /* never here */ + DUK_WO_NORETURN(return NULL;); } /* @@ -86455,6 +87635,7 @@ DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) { if (re_ctx->recursion_depth >= re_ctx->recursion_limit) { DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT); + DUK_WO_NORETURN(return NULL;); } re_ctx->recursion_depth++; @@ -86463,6 +87644,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const if (re_ctx->steps_count >= re_ctx->steps_limit) { DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT); + DUK_WO_NORETURN(return NULL;); } re_ctx->steps_count++; @@ -86808,14 +87990,14 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * idx_count); DUK_ASSERT(range_save != NULL); - DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count); + duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count); #if defined(DUK_USE_EXPLICIT_NULL_INIT) idx_end = idx_start + idx_count; for (idx = idx_start; idx < idx_end; idx++) { re_ctx->saved[idx] = NULL; } #else - DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count); + duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count); #endif sub_sp = duk__match_regexp(re_ctx, pc, sp); @@ -86833,7 +88015,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])", (long) idx_start, (long) (idx_start + idx_count - 1), (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2))); - DUK_MEMCPY((void *) (re_ctx->saved + idx_start), + duk_memcpy((void *) (re_ctx->saved + idx_start), (const void *) range_save, sizeof(duk_uint8_t *) * idx_count); duk_pop_unsafe(re_ctx->thr); @@ -86865,7 +88047,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * re_ctx->nsaved); DUK_ASSERT(full_save != NULL); - DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved); + duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved); skip = duk__bc_get_i32(re_ctx, &pc); sub_sp = duk__match_regexp(re_ctx, pc, sp); @@ -86890,7 +88072,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const lookahead_fail: /* fail: restore saves */ - DUK_MEMCPY((void *) re_ctx->saved, + duk_memcpy((void *) re_ctx->saved, (const void *) full_save, sizeof(duk_uint8_t *) * re_ctx->nsaved); duk_pop_unsafe(re_ctx->thr); @@ -86972,7 +88154,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const internal_error: DUK_ERROR_INTERNAL(re_ctx->thr); - return NULL; /* never here */ + DUK_WO_NORETURN(return NULL;); } /* @@ -87038,7 +88220,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_ /* [ ... re_obj input bc ] */ - DUK_MEMZERO(&re_ctx, sizeof(re_ctx)); + duk_memzero(&re_ctx, sizeof(re_ctx)); re_ctx.thr = thr; re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); @@ -87075,7 +88257,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_ #elif defined(DUK_USE_ZERO_BUFFER_DATA) /* buffer is automatically zeroed */ #else - DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved); + duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved); #endif DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld", @@ -87160,7 +88342,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_ * internal/limit error occurs (which causes a longjmp()) * * - If we supported anchored matches, we would break out here - * unconditionally; however, Ecmascript regexps don't have anchored + * unconditionally; however, ECMAScript regexps don't have anchored * matches. It might make sense to implement a fast bail-out if * the regexp begins with '^' and sp is not 0: currently we'll just * run through the entire input string, trivially failing the match @@ -87354,13 +88536,13 @@ typedef union { } while (0) #define DUK__DBLUNION_CMP_TRUE(a,b) do { \ - if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \ + if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \ DUK__FAILED("double union compares false (expected true)"); \ } \ } while (0) #define DUK__DBLUNION_CMP_FALSE(a,b) do { \ - if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \ + if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \ DUK__FAILED("double union compares true (expected false)"); \ } \ } while (0) @@ -87669,7 +88851,7 @@ DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) { */ DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - DUK_MEMSET((void *) &c, 0, sizeof(c)); + duk_memset((void *) &c, 0, sizeof(c)); c.d = a.d + b.d; if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) { DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x", @@ -87689,7 +88871,7 @@ DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) { */ DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01); DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - DUK_MEMSET((void *) &c, 0, sizeof(c)); + duk_memset((void *) &c, 0, sizeof(c)); c.d = a.d + b.d; if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) { DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x", @@ -88126,7 +89308,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint * packed format. These tables are used to match non-ASCII * characters of complex productions by resorting to a linear * range-by-range comparison. This is very slow, but is expected - * to be very rare in practical Ecmascript source code, and thus + * to be very rare in practical ECMAScript source code, and thus * compactness is most important. * * The tables are matched using uni_range_match() and the format @@ -88140,54 +89322,55 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint * Automatically generated by extract_chars.py, do not edit! */ -const duk_uint8_t duk_unicode_ids_noa[1036] = { +const duk_uint8_t duk_unicode_ids_noa[1063] = { 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34, 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191, 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240, -101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19, -240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47, -2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18, -47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12, -38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6, -41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98, -34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2, -85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35, -63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227, -240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5, -15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40, -240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27, -43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47, -15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68, -112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52, -29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12, -146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255, -224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63, -253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34, -35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31, -240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32, -240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7, -95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245, -207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10, -207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255, -223,13,79,33,242,31,16,240,47,11,111,22,191,14,63,20,87,36,241,207,142,240, -79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20, -3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15, -1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,107,240, -62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,47,9,240, -207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,102,32,35, -46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,240,67,242, -127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,27,244,127, -10,255,224,122,243,15,17,15,254,11,79,41,255,152,47,21,240,48,242,63,14, -255,226,100,255,226,140,245,143,95,240,63,180,255,233,176,255,227,33,255, -238,197,255,225,57,255,240,1,10,223,254,18,184,240,255,99,240,239,4,242,15, -2,63,17,240,86,240,63,254,38,79,53,192,243,76,243,32,241,31,255,0,6,223, -240,95,254,30,95,255,0,20,1,31,254,175,47,91,108,72,137,255,240,0,101,175, -69,47,55,33,48,49,51,43,32,38,47,49,35,55,38,47,12,35,36,32,70,47,254,4,99, -240,146,240,146,240,242,240,146,240,242,240,146,240,242,240,146,240,242, -240,146,127,254,242,143,181,242,223,52,255,227,176,50,240,178,18,3,2,146, -50,2,7,5,2,2,2,34,18,3,2,2,2,2,2,18,3,50,98,50,50,2,146,240,22,34,66,240, -31,255,0,0,56,255,240,9,92,159,27,255,239,39,207,206,63,255,0,5,116,255, -240,1,133,47,254,17,0, +101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115, +19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5, +47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16, +18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15, +12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2, +6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50, +98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15, +2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25, +35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21, +227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79, +21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240, +175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241, +79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32, +32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57, +32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247, +87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15, +254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242, +127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243, +95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39, +243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13, +143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52, +48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150, +223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18, +18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10, +127,10,207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37, +255,223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142, +240,79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241, +194,20,3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135, +31,50,15,1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240, +107,240,62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241, +47,9,240,207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244, +102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37, +240,67,242,127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223, +27,244,127,10,255,224,122,243,15,17,15,242,11,241,136,15,7,12,241,131,63, +40,242,159,249,130,241,95,3,15,35,240,239,98,98,18,241,111,7,15,254,26,223, +254,40,207,88,245,255,3,251,79,254,155,15,254,50,31,254,236,95,254,19,159, +255,0,16,173,255,225,43,143,15,246,63,14,240,79,32,240,35,241,31,5,111,3, +255,226,100,243,92,15,52,207,50,31,16,255,240,0,109,255,5,255,225,229,255, +240,1,64,31,254,1,31,67,255,224,126,255,231,248,245,182,196,136,159,255,0, +6,90,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4, +98,255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255, +239,40,251,95,45,243,79,254,59,3,47,11,33,32,48,41,35,32,32,112,80,32,32, +34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,98,36,47,1,255,240,0, +3,143,255,0,149,201,241,191,254,242,124,252,227,255,240,0,87,79,0,255,240, +0,194,63,254,177,63,254,17,0, }; #else /* IdentifierStart production with ASCII and non-BMP excluded */ @@ -88196,35 +89379,35 @@ const duk_uint8_t duk_unicode_ids_noa[1036] = { * Automatically generated by extract_chars.py, do not edit! */ -const duk_uint8_t duk_unicode_ids_noabmp[625] = { +const duk_uint8_t duk_unicode_ids_noabmp[626] = { 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34, 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191, 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240, -101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19, -240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47, -2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18, -47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12, -38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6, -41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98, -34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2, -85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35, -63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227, -240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5, -15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40, -240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27, -43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47, -15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68, -112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52, -29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12, -146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255, -224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63, -253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34, -35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31, -240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32, -240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7, -95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245, -207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10, -207,73,69,53,53,50,0, +101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115, +19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5, +47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16, +18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15, +12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2, +6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50, +98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15, +2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25, +35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21, +227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79, +21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240, +175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241, +79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32, +32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57, +32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247, +87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15, +254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242, +127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243, +95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39, +243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13, +143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52, +48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150, +223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18, +18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10, +127,10,207,73,69,53,53,50,0, }; #endif @@ -88259,32 +89442,33 @@ const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = { * Automatically generated by extract_chars.py, do not edit! */ -const duk_uint8_t duk_unicode_idp_m_ids_noa[530] = { +const duk_uint8_t duk_unicode_idp_m_ids_noa[549] = { 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112, 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34, 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50, 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240, -97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9, -240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50, -242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41, -244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245, -111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241, -241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242, -244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57, -241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31, -35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31, -255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242, -79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29, -208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3, +97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9, +240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35, +242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215, +41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160, +245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240, +241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41, +242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12, +57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0, +31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91, +31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161, +242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242, +29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3, 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64, 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47, 39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68, 183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77, 159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255, -226,57,114,127,2,159,42,240,98,223,255,0,60,157,159,120,79,45,111,11,159, -254,46,191,30,240,35,255,240,3,191,225,255,240,0,59,164,69,151,54,241,3, -248,98,255,228,125,242,47,254,15,79,39,95,34,144,240,0,240,132,46,255,228, -68,98,240,19,98,18,79,254,121,150,245,246,105,255,240,192,105,175,224,0, +224,11,159,26,98,57,10,175,32,240,15,254,8,151,39,240,41,242,175,6,45,246, +197,64,33,38,32,153,255,240,3,191,169,247,132,242,214,240,185,255,226,235, +241,239,2,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,134,47,254,71, +223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,47,1,54,33,36, +255,231,153,111,95,102,159,255,12,6,154,254,0, }; #else /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */ @@ -88293,23 +89477,23 @@ const duk_uint8_t duk_unicode_idp_m_ids_noa[530] = { * Automatically generated by extract_chars.py, do not edit! */ -const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357] = { +const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = { 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112, 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34, 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50, 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240, -97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9, -240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50, -242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41, -244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245, -111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241, -241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242, -244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57, -241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31, -35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31, -255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242, -79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29, -208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3, +97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9, +240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35, +242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215, +41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160, +245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240, +241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41, +242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12, +57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0, +31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91, +31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161, +242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242, +29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3, 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0, }; #endif @@ -94494,6 +95678,10 @@ DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) { /* #include duk_internal.h -> already included */ +/* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of + * >0 for the underlying dynamic buffer. + */ + /* * Macro support functions (use only macros in calling code) */ @@ -94505,6 +95693,9 @@ DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, DUK_ASSERT(bw_ctx != NULL); DUK_UNREF(thr); + /* 'p' might be NULL when the underlying buffer is zero size. If so, + * the resulting pointers are not used unsafely. + */ 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; @@ -94513,7 +95704,6 @@ DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, } 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); @@ -94528,6 +95718,7 @@ DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ct (void) duk_push_dynamic_buffer(thr, buf_size); bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1); + DUK_ASSERT(bw_ctx->buf != NULL); duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size); } @@ -94552,7 +95743,7 @@ DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ if (DUK_UNLIKELY(new_sz < curr_off)) { /* overflow */ DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG); - return NULL; /* not reachable */ + DUK_WO_NORETURN(return NULL;); } #if 0 /* for manual torture testing: tight allocation, useful with valgrind */ new_sz = curr_off + sz; @@ -94595,9 +95786,9 @@ DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw DUK_UNREF(thr); p_base = bw->p_base; - DUK_MEMCPY((void *) bw->p, - (const void *) (p_base + src_off), - (size_t) len); + duk_memcpy_unsafe((void *) bw->p, + (const void *) (p_base + src_off), + (size_t) len); bw->p += len; } @@ -94627,12 +95818,12 @@ DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *b 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), - (size_t) move_sz); - DUK_MEMCPY((void *) (p_base + dst_off), - (const void *) buf, - (size_t) len); + duk_memmove_unsafe((void *) (p_base + dst_off + len), + (const void *) (p_base + dst_off), + (size_t) move_sz); + duk_memcpy_unsafe((void *) (p_base + dst_off), + (const void *) buf, + (size_t) len); bw->p += len; } @@ -94674,12 +95865,12 @@ DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b 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), - (size_t) move_sz); - DUK_MEMCPY((void *) (p_base + dst_off), - (const void *) (p_base + src_off), - (size_t) len); + duk_memmove_unsafe((void *) (p_base + dst_off + len), + (const void *) (p_base + dst_off), + (size_t) move_sz); + duk_memcpy_unsafe((void *) (p_base + dst_off), + (const void *) (p_base + src_off), + (size_t) len); bw->p += len; } @@ -94712,7 +95903,7 @@ DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter move_sz = buf_sz - off; p_dst = p_base + off + len; p_src = p_base + off; - DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz); + duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz); return p_src; /* point to start of 'reserved area' */ } @@ -94743,9 +95934,9 @@ DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b 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, - (size_t) move_sz); + duk_memmove_unsafe((void *) p_dst, + (const void *) p_src, + (size_t) move_sz); bw->p -= len; } @@ -94766,7 +95957,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) duk_uint16_t x; } u; - DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2); + duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 2); u.x = DUK_NTOH16(u.x); *p += 2; return u.x; @@ -94778,7 +95969,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) duk_uint32_t x; } u; - DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4); + duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4); u.x = DUK_NTOH32(u.x); *p += 4; return u.x; @@ -94791,10 +95982,10 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t * duk_uint32_t x; } u; - DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4); + duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4); u.x = DUK_NTOH32(u.x); du.ui[DUK_DBL_IDX_UI0] = u.x; - DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4); + duk_memcpy((void *) u.b, (const void *) (*p + 4), (size_t) 4); u.x = DUK_NTOH32(u.x); du.ui[DUK_DBL_IDX_UI1] = u.x; *p += 8; @@ -94809,7 +96000,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_ui } u; u.x = DUK_HTON16(val); - DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2); + duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 2); *p += 2; } @@ -94820,7 +96011,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_ui } u; u.x = DUK_HTON32(val); - DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4); + duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4); *p += 4; } @@ -94834,12 +96025,414 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk du.d = val; u.x = du.ui[DUK_DBL_IDX_UI0]; u.x = DUK_HTON32(u.x); - DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4); + duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4); u.x = du.ui[DUK_DBL_IDX_UI1]; u.x = DUK_HTON32(u.x); - DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4); + duk_memcpy((void *) (*p + 4), (const void *) u.b, (size_t) 4); *p += 8; } +/* + * Cast helpers. + * + * C99+ coercion is challenging portability-wise because out-of-range casts + * may invoke implementation defined or even undefined behavior. See e.g. + * http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer. + * + * Provide explicit cast helpers which try to avoid implementation defined + * or undefined behavior. These helpers can then be simplified in the vast + * majority of cases where the implementation defined or undefined behavior + * is not problematic. + */ + +/* #include duk_internal.h -> already included */ + +/* Portable double-to-integer cast which avoids undefined behavior and avoids + * relying on fmin(), fmax(), or other intrinsics. Out-of-range results are + * not assumed by caller, but here value is clamped, NaN converts to minval. + */ +#define DUK__DOUBLE_INT_CAST1(tname,minval,maxval) do { \ + if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \ + DUK_ASSERT(!DUK_ISNAN(x)); \ + if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \ + return (tname) x; \ + } else { \ + return (tname) (maxval); \ + } \ + } else { \ + /* NaN or below minval. Since we don't care about the result \ + * for out-of-range values, just return the minimum value for \ + * both. \ + */ \ + return (tname) (minval); \ + } \ + } while (0) + +/* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either + * argument is a NaN, return the second argument. This avoids a + * NaN-to-integer cast which is undefined behavior. + */ +#define DUK__DOUBLE_INT_CAST2(tname,minval,maxval) do { \ + return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \ + } while (0) + +/* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */ +#define DUK__DOUBLE_INT_CAST3(tname,minval,maxval) do { \ + if (DUK_ISNAN(x)) { \ + /* 0 or any other value is fine. */ \ + return (tname) 0; \ + } else \ + return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \ + } \ + } while (0) + +/* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if + * one argument is NaN but the other isn't, the non-NaN argument is returned. + * Because the limits are non-NaN values, explicit NaN check is not needed. + * This may not work on all legacy platforms, and also doesn't seem to inline + * the fmin() and fmax() calls (unless one uses -ffast-math which we don't + * support). + */ +#define DUK__DOUBLE_INT_CAST4(tname,minval,maxval) do { \ + return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \ + } while (0) + +DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) { +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + /* Real world solution: almost any practical platform will provide + * an integer value without any guarantees what it is (which is fine). + */ + return (duk_int_t) x; +#else + DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX); +#endif +} + +DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) { +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + return (duk_uint_t) x; +#else + DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX); +#endif +} + +DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) { +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + return (duk_int32_t) x; +#else + DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX); +#endif +} + +DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) { +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + return (duk_uint32_t) x; +#else + DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX); +#endif +} + +/* Largest IEEE double that doesn't round to infinity in the default rounding + * mode. The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to + * infinity, at least on x64. This number is one double unit below that + * midpoint. See misc/float_cast.c. + */ +#define DUK__FLOAT_ROUND_LIMIT 340282356779733623858607532500980858880.0 + +/* Maximum IEEE float. Double-to-float conversion above this would be out of + * range and thus technically undefined behavior. + */ +#define DUK__FLOAT_MAX 340282346638528859811704183484516925440.0 + +DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) { + /* Even a double-to-float cast is technically undefined behavior if + * the double is out-of-range. C99 Section 6.3.1.5: + * + * If the value being converted is in the range of values that can + * be represented but cannot be represented exactly, the result is + * either the nearest higher or nearest lower representable value, + * chosen in an implementation-defined manner. If the value being + * converted is outside the range of values that can be represented, + * the behavior is undefined. + */ +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + return (duk_float_t) x; +#else + duk_double_t t; + + t = DUK_FABS(x); + DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) || + (!DUK_ISNAN(x) && !DUK_ISNAN(t))); + + if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) { + /* Standard in-range case, try to get here with a minimum + * number of checks and branches. + */ + DUK_ASSERT(!DUK_ISNAN(x)); + return (duk_float_t) x; + } else if (t <= DUK__FLOAT_ROUND_LIMIT) { + /* Out-of-range, but rounds to min/max float. */ + DUK_ASSERT(!DUK_ISNAN(x)); + if (x < 0.0) { + return (duk_float_t) -DUK__FLOAT_MAX; + } else { + return (duk_float_t) DUK__FLOAT_MAX; + } + } else if (DUK_ISNAN(x)) { + /* Assumes double NaN -> float NaN considered "in range". */ + DUK_ASSERT(DUK_ISNAN(x)); + return (duk_float_t) x; + } else { + /* Out-of-range, rounds to +/- Infinity. */ + if (x < 0.0) { + return (duk_float_t) -DUK_DOUBLE_INFINITY; + } else { + return (duk_float_t) DUK_DOUBLE_INFINITY; + } + } +#endif +} + +/* automatic undefs */ +#undef DUK__DOUBLE_INT_CAST1 +#undef DUK__DOUBLE_INT_CAST2 +#undef DUK__DOUBLE_INT_CAST3 +#undef DUK__DOUBLE_INT_CAST4 +#undef DUK__FLOAT_MAX +#undef DUK__FLOAT_ROUND_LIMIT +/* + * IEEE double helpers. + */ + +/* #include duk_internal.h -> already included */ + +DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) { + duk_double_union du; + du.d = x; + return DUK_DBLUNION_IS_ANYINF(&du); +} + +DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) { + duk_double_union du; + du.d = x; + return DUK_DBLUNION_IS_POSINF(&du); +} + +DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) { + duk_double_union du; + du.d = x; + return DUK_DBLUNION_IS_NEGINF(&du); +} + +DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) { + duk_double_union du; + du.d = x; + /* Assumes we're dealing with a Duktape internal NaN which is + * NaN normalized if duk_tval requires it. + */ + DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); + return DUK_DBLUNION_IS_NAN(&du); +} + +DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) { + duk_double_union du; + du.d = x; + /* Assumes we're dealing with a Duktape internal NaN which is + * NaN normalized if duk_tval requires it. + */ + DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); + return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du); +} + +DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) { + duk_double_union du; + du.d = x; + /* If exponent is 0x7FF the argument is either a NaN or an + * infinity. We don't need to check any other fields. + */ +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) + return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000); +#else + return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000); +#endif +#else + return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL; +#endif +} + +DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) { + duk_double_union du; +#if defined(DUK_USE_64BIT_OPS) + duk_uint64_t t; +#else + duk_uint32_t t; +#endif + du.d = x; +#if defined(DUK_USE_64BIT_OPS) +#if defined(DUK_USE_DOUBLE_ME) + t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000); + if (t == DUK_U64_CONSTANT(0x0000000000000000)) { + t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000); + return t == 0; + } + if (t == DUK_U64_CONSTANT(0x000000007ff00000)) { + return 1; + } +#else + t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000); + if (t == DUK_U64_CONSTANT(0x0000000000000000)) { + t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000); + return t == 0; + } + if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) { + return 1; + } +#endif +#else + t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL; + if (t == 0x00000000UL) { + return DUK_DBLUNION_IS_ANYZERO(&du); + } + if (t == 0x7ff00000UL) { + return 1; + } +#endif + return 0; +} + +DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) { + duk_double_union du; + du.d = x; + return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du); +} + +DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) { + /* XXX: optimize */ + duk_small_uint_t s = duk_double_signbit(x); + x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */ + if (s) { + x = -x; + } + return x; +} + +DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) { + duk_double_union du1; + duk_double_union du2; + du1.d = x; + du2.d = y; + + return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0); +} + +DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) { + /* Doesn't replicate fmin() behavior exactly: for fmin() if one + * argument is a NaN, the other argument should be returned. + * Duktape doesn't rely on this behavior so the replacement can + * be simplified. + */ + return (x < y ? x : y); +} + +DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) { + /* Doesn't replicate fmax() behavior exactly: for fmax() if one + * argument is a NaN, the other argument should be returned. + * Duktape doesn't rely on this behavior so the replacement can + * be simplified. + */ + return (x > y ? x : y); +} + +DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) { + return !duk_double_is_nan_or_inf(x); +} + +DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) { + if (duk_double_is_nan_or_inf(x)) { + return 0; + } else { + return duk_js_tointeger_number(x) == x; + } +} + +DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) { + /* >>> 2**53-1 + * 9007199254740991 + */ + return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0; +} + +/* Check whether a duk_double_t is a whole number in the 32-bit range (reject + * negative zero), and if so, return a duk_int32_t. + * For compiler use: don't allow negative zero as it will cause trouble with + * LDINT+LDINTX, positive zero is OK. + */ +DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) { + duk_int32_t t; + + t = duk_double_to_int32_t(x); + if (!((duk_double_t) t == x)) { + return 0; + } + if (t == 0) { + duk_double_union du; + du.d = x; + if (DUK_DBLUNION_HAS_SIGNBIT(&du)) { + return 0; + } + } + *ival = t; + return 1; +} + +/* Check whether a duk_double_t is a whole number in the 32-bit range, and if + * so, return a duk_int32_t. + */ +DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) { + duk_int32_t t; + + t = duk_double_to_int32_t(x); + if (!((duk_double_t) t == x)) { + return 0; + } + *ival = t; + return 1; +} + +/* Division: division by zero is undefined behavior (and may in fact trap) + * so it needs special handling for portability. + */ + +DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) { +#if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) + if (DUK_UNLIKELY(y == 0.0)) { + /* In C99+ division by zero is undefined behavior so + * avoid it entirely. Hopefully the compiler is + * smart enough to avoid emitting any actual code + * because almost all practical platforms behave as + * expected. + */ + if (x > 0.0) { + if (DUK_SIGNBIT(y)) { + return -DUK_DOUBLE_INFINITY; + } else { + return DUK_DOUBLE_INFINITY; + } + } else if (x < 0.0) { + if (DUK_SIGNBIT(y)) { + return DUK_DOUBLE_INFINITY; + } else { + return -DUK_DOUBLE_INFINITY; + } + } else { + /* +/- 0, NaN */ + return DUK_DOUBLE_NAN; + } + } +#endif + + return x / y; +} /* * Hash function duk_util_hashbytes(). * @@ -94901,6 +96494,42 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t /* automatic undefs */ #undef DUK__MAGIC_M #undef DUK__MAGIC_R +/* + * Memory utils. + */ + +/* #include duk_internal.h -> already included */ + +#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR) +DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) { + DUK_ASSERT(s1 != NULL || len == 0U); + DUK_ASSERT(s2 != NULL || len == 0U); + return DUK_MEMCMP(s1, s2, (size_t) len); +} + +DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) { + DUK_ASSERT(s1 != NULL); + DUK_ASSERT(s2 != NULL); + return DUK_MEMCMP(s1, s2, (size_t) len); +} +#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */ +DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) { + DUK_ASSERT(s1 != NULL || len == 0U); + DUK_ASSERT(s2 != NULL || len == 0U); + if (DUK_UNLIKELY(len == 0U)) { + return 0; + } + DUK_ASSERT(s1 != NULL); + DUK_ASSERT(s2 != NULL); + return duk_memcmp(s1, s2, len); +} + +DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) { + DUK_ASSERT(s1 != NULL); + DUK_ASSERT(s2 != NULL); + return DUK_MEMCMP(s1, s2, (size_t) len); +} +#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */ /* * A tiny random number generator used for Math.random() and other internals. * @@ -95032,4 +96661,3 @@ DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) { #undef DUK__RANDOM_XOROSHIRO128PLUS #undef DUK__RND_BIT #undef DUK__UPDATE_RND -#endif diff --git a/content/handlers/javascript/duktape/duktape.h b/content/handlers/javascript/duktape/duktape.h index e97e46269..43e2966c1 100644 --- a/content/handlers/javascript/duktape/duktape.h +++ b/content/handlers/javascript/duktape/duktape.h @@ -1,5 +1,5 @@ /* - * Duktape public API for Duktape 2.2.1. + * Duktape public API for Duktape 2.3.0. * * See the API reference for documentation on call semantics. The exposed, * supported API is between the "BEGIN PUBLIC API" and "END PUBLIC API" @@ -21,7 +21,7 @@ * * (http://opensource.org/licenses/MIT) * - * Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst) + * Copyright (c) 2013-2018 by Duktape authors (see AUTHORS.rst) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -92,6 +92,14 @@ * * Steven Don (https://github.com/shdon) * * Simon Stone (https://github.com/sstone1) * * \J. McC. (https://github.com/jmhmccr) + * * Jakub Nowakowski (https://github.com/jimvonmoon) + * * Tommy Nguyen (https://github.com/tn0502) + * * Fabrice Fontaine (https://github.com/ffontaine) + * * Christopher Hiller (https://github.com/boneskull) + * * Gonzalo Diethelm (https://github.com/gonzus) + * * Michal Kasperek (https://github.com/michalkas) + * * Andrew Janke (https://github.com/apjanke) + * * Steve Fan (https://github.com/stevefan1999) * * Other contributions * =================== @@ -130,6 +138,8 @@ * * https://github.com/chris-y * * Laurent Zubiaur (https://github.com/lzubiaur) * * Neil Kolban (https://github.com/nkolban) + * * Wilhelm Wanecek (https://github.com/wanecek) + * * Andrew Janke (https://github.com/apjanke) * * If you are accidentally missing from this list, send me an e-mail * (``sami.vaarala@iki.fi``) and I'll fix the omission. @@ -150,15 +160,15 @@ /* Duktape version, (major * 10000) + (minor * 100) + patch. Allows C code * to #if (DUK_VERSION >= NNN) against Duktape API version. The same value - * is also available to Ecmascript code in Duktape.version. Unofficial + * is also available to ECMAScript code in Duktape.version. Unofficial * development snapshots 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 20201L +#define DUK_VERSION 20300L /* Git commit, describe, and branch 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 + * which Duktape snapshot was used. Not available in the ECMAScript * environment. */ #define DUK_GIT_COMMIT "external" @@ -258,7 +268,7 @@ struct duk_number_list_entry { }; struct duk_time_components { - duk_double_t year; /* year, e.g. 2016, Ecmascript year range */ + duk_double_t year; /* year, e.g. 2016, ECMAScript year range */ duk_double_t month; /* month: 1-12 */ duk_double_t day; /* day: 1-31 */ duk_double_t hours; /* hour: 0-59 */ @@ -294,12 +304,12 @@ struct duk_time_components { /* Value types, used by e.g. duk_get_type() */ #define DUK_TYPE_MIN 0U #define DUK_TYPE_NONE 0U /* no value, e.g. invalid index */ -#define DUK_TYPE_UNDEFINED 1U /* Ecmascript undefined */ -#define DUK_TYPE_NULL 2U /* Ecmascript null */ -#define DUK_TYPE_BOOLEAN 3U /* Ecmascript boolean: 0 or 1 */ -#define DUK_TYPE_NUMBER 4U /* Ecmascript number: double */ -#define DUK_TYPE_STRING 5U /* Ecmascript string: CESU-8 / extended UTF-8 encoded */ -#define DUK_TYPE_OBJECT 6U /* Ecmascript object: includes objects, arrays, functions, threads */ +#define DUK_TYPE_UNDEFINED 1U /* ECMAScript undefined */ +#define DUK_TYPE_NULL 2U /* ECMAScript null */ +#define DUK_TYPE_BOOLEAN 3U /* ECMAScript boolean: 0 or 1 */ +#define DUK_TYPE_NUMBER 4U /* ECMAScript number: double */ +#define DUK_TYPE_STRING 5U /* ECMAScript string: CESU-8 / extended UTF-8 encoded */ +#define DUK_TYPE_OBJECT 6U /* ECMAScript object: includes objects, arrays, functions, threads */ #define DUK_TYPE_BUFFER 7U /* fixed or dynamic, garbage collected byte buffer */ #define DUK_TYPE_POINTER 8U /* raw void pointer */ #define DUK_TYPE_LIGHTFUNC 9U /* lightweight function pointer */ @@ -668,7 +678,21 @@ DUK_EXTERNAL_DECL void duk_push_pointer(duk_context *ctx, void *p); DUK_EXTERNAL_DECL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...); DUK_EXTERNAL_DECL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap); +/* duk_push_literal() may evaluate its argument (a C string literal) more than + * once on purpose. When speed is preferred, sizeof() avoids an unnecessary + * strlen() at runtime. Sizeof("foo") == 4, so subtract 1. The argument + * must be non-NULL and should not contain internal NUL characters as the + * behavior will then depend on config options. + */ +#if defined(DUK_USE_PREFER_SIZE) +#define duk_push_literal(ctx,cstring) duk_push_string((ctx), (cstring)) +#else +DUK_EXTERNAL_DECL const char *duk_push_literal_raw(duk_context *ctx, const char *str, duk_size_t len); +#define duk_push_literal(ctx,cstring) duk_push_literal_raw((ctx), (cstring), sizeof((cstring)) - 1U) +#endif + DUK_EXTERNAL_DECL void duk_push_this(duk_context *ctx); +DUK_EXTERNAL_DECL void duk_push_new_target(duk_context *ctx); DUK_EXTERNAL_DECL void duk_push_current_function(duk_context *ctx); DUK_EXTERNAL_DECL void duk_push_current_thread(duk_context *ctx); DUK_EXTERNAL_DECL void duk_push_global_object(duk_context *ctx); @@ -1000,29 +1024,55 @@ DUK_EXTERNAL_DECL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void * /* * Property access * - * The basic function assumes key is on stack. The _string variant takes - * a C string as a property name, while the _index variant takes an array - * index as a property name (e.g. 123 is equivalent to the key "123"). + * The basic function assumes key is on stack. The _(l)string variant takes + * a C string as a property name; the _literal variant takes a C literal. + * The _index variant takes an array index as a property name (e.g. 123 is + * equivalent to the key "123"). The _heapptr variant takes a raw, borrowed + * heap pointer. */ DUK_EXTERNAL_DECL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx); DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_string((ctx), (obj_idx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) +#endif DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); DUK_EXTERNAL_DECL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx); DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_string((ctx), (obj_idx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) +#endif DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); DUK_EXTERNAL_DECL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx); DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_string((ctx), (obj_idx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) +#endif DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); DUK_EXTERNAL_DECL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx); DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_string((ctx), (obj_idx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len); +#define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U) +#endif DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx); DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr); @@ -1031,8 +1081,22 @@ DUK_EXTERNAL_DECL void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uin DUK_EXTERNAL_DECL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_get_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_get_global_literal(ctx,key) duk_get_global_string((ctx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_get_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len); +#define duk_get_global_literal(ctx,key) duk_get_global_literal_raw((ctx), (key), sizeof((key)) - 1U) +#endif +DUK_EXTERNAL_DECL duk_bool_t duk_get_global_heapptr(duk_context *ctx, void *ptr); DUK_EXTERNAL_DECL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key); DUK_EXTERNAL_DECL duk_bool_t duk_put_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len); +#if defined(DUK_USE_PREFER_SIZE) +#define duk_put_global_literal(ctx,key) duk_put_global_string((ctx), (key)) +#else +DUK_EXTERNAL_DECL duk_bool_t duk_put_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len); +#define duk_put_global_literal(ctx,key) duk_put_global_literal_raw((ctx), (key), sizeof((key)) - 1U) +#endif +DUK_EXTERNAL_DECL duk_bool_t duk_put_global_heapptr(duk_context *ctx, void *ptr); /* * Inspection @@ -1099,7 +1163,7 @@ DUK_EXTERNAL_DECL void duk_trim(duk_context *ctx, duk_idx_t idx); DUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t idx, duk_size_t char_offset); /* - * Ecmascript operators + * ECMAScript operators */ DUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); @@ -1107,6 +1171,12 @@ DUK_EXTERNAL_DECL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t idx1, DUK_EXTERNAL_DECL duk_bool_t duk_samevalue(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); DUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2); +/* + * Random + */ + +DUK_EXTERNAL_DECL duk_double_t duk_random(duk_context *ctx); + /* * Function (method) calls */ @@ -1257,7 +1327,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time #define DUK_DATE_MSEC_HOUR (60L * 60L * 1000L) #define DUK_DATE_MSEC_DAY (24L * 60L * 60L * 1000L) -/* Ecmascript date range is 100 million days from Epoch: +/* ECMAScript date range is 100 million days from Epoch: * > 100e6 * 24 * 60 * 60 * 1000 // 100M days in millisecs * 8640000000000000 * (= 8.64e15) @@ -1265,7 +1335,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time #define DUK_DATE_MSEC_100M_DAYS (8.64e15) #define DUK_DATE_MSEC_100M_DAYS_LEEWAY (8.64e15 + 24 * 3600e3) -/* Ecmascript year range: +/* ECMAScript year range: * > new Date(100e6 * 24 * 3600e3).toISOString() * '+275760-09-13T00:00:00.000Z' * > new Date(-100e6 * 24 * 3600e3).toISOString() @@ -1275,7 +1345,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time #define DUK_DATE_MAX_ECMA_YEAR 275760L /* Part indices for internal breakdowns. Part order from DUK_DATE_IDX_YEAR - * to DUK_DATE_IDX_MILLISECOND matches argument ordering of Ecmascript API + * 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). -- cgit v1.2.3