diff --git a/CMakeLists.txt b/CMakeLists.txt index cfbe77d..73ac28f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,31 +16,28 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") message(STATUS "QuickJS Library: Begin") -# For now, avoid including the quickjs-ng CMake configuration directly, and explicitly specify our own -# add_subdirectory(quickjs-ng) - set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) set(CMAKE_C_STANDARD 11) set(QUICKJS_HEADERS - quickjs-ng/cutils.h - quickjs-ng/dtoa.h - quickjs-ng/libregexp.h - quickjs-ng/libunicode.h - quickjs-ng/list.h - quickjs-ng/quickjs.h + quickjs/cutils.h + quickjs/dtoa.h + quickjs/libregexp.h + quickjs/libunicode.h + quickjs/list.h + quickjs/quickjs.h # extensions quickjs-wz-extensions/quickjs-debugger.h quickjs-wz-extensions/quickjs-limitedcontext.h ) set(QUICKJS_SOURCES - quickjs-ng/cutils.c - quickjs-ng/dtoa.c - quickjs-ng/libregexp.c - quickjs-ng/libunicode.c - quickjs-ng/quickjs.c + quickjs/cutils.c + quickjs/dtoa.c + quickjs/libregexp.c + quickjs/libunicode.c + quickjs/quickjs.c # extensions # INCLUDED DIRECTLY IN QUICKJS.C: quickjs-wz-extensions/quickjs-debugger.c # INCLUDED DIRECTLY IN QUICKJS.C: quickjs-wz-extensions/quickjs-limitedcontext.c @@ -52,10 +49,20 @@ if(WIN32) list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0601) endif() +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/quickjs/VERSION.txt" QUICKJS_VERSION_STR) +list(APPEND qjs_defines CONFIG_VERSION="${QUICKJS_VERSION_STR}") + +include(CheckIncludeFiles) +CHECK_INCLUDE_FILES("sys/time.h" HAVE_SYS_TIME_H LANGUAGE C) +include(CheckSymbolExists) +check_symbol_exists(bswap16 "stdlib.h" HAVE_BSWAP16) +check_symbol_exists(bswap32 "stdlib.h" HAVE_BSWAP32) +check_symbol_exists(bswap64 "stdlib.h" HAVE_BSWAP64) + add_library(qjs STATIC ${QUICKJS_HEADERS} ${QUICKJS_SOURCES}) target_compile_definitions(qjs PRIVATE ${qjs_defines}) target_include_directories(qjs PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/quickjs-ng + ${CMAKE_CURRENT_SOURCE_DIR}/quickjs ${CMAKE_CURRENT_SOURCE_DIR}/quickjs-wz-extensions ) @@ -64,6 +71,10 @@ set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) target_link_libraries(qjs PRIVATE Threads::Threads) +if(HAVE_SYS_TIME_H) + target_compile_definitions(qjs PRIVATE QUICKJS_HAVE_SYS_TIME_H) +endif() + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # GCC 9.3.0+ has been tested to be fine at -O2 if((CMAKE_C_COMPILER_VERSION VERSION_LESS 9.3) AND (CMAKE_C_COMPILER_VERSION VERSION_GREATER 7.0)) @@ -73,7 +84,7 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU") endif() endif() -# Alias the quickjs-ng "qjs" library name to the previous library name that WZ used +# Alias the "qjs" library name to the previous library name that WZ used add_library(quickjs ALIAS qjs) include(CheckCCompilerFlag) @@ -111,7 +122,11 @@ if(MSVC) xcheck_add_c_compiler_flag(/wd4996) # -Wdeprecated-declarations xcheck_add_c_compiler_flag(/wd5045) # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified + xcheck_add_c_compiler_flag(/wd4115) # warning C4115: named type definition in parentheses + xcheck_add_c_compiler_flag(/wd4127) # warning C4127: conditional expression is constant + xcheck_add_c_compiler_flag(/wd4132) # warning C4132: const object should be initialized xcheck_add_c_compiler_flag(/wd4146) # warning C4146: unary minus operator applied to unsigned type, result still unsigned + xcheck_add_c_compiler_flag(/wd4295) # warning C4295: 'digits': array is too small to include a terminating null character xcheck_add_c_compiler_flag(/wd4456) # warning C4456: declaration of 'var' hides previous local declaration xcheck_add_c_compiler_flag(/wd4457) # warning C4457: declaration of 'var' hides function parameter diff --git a/README.md b/README.md index bf685ad..69cd6fc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # QuickJS (modified) -This repo contains [quickjs-ng](https://github.com/quickjs-ng/quickjs), with modifications and patches required by Warzone 2100. +This repo contains [quickjs](https://github.com/bellard/quickjs), with modifications and patches required by Warzone 2100. For a breakdown of the patches applied for Warzone 2100, see the commit history and/or the [`patches/`](patches/) subdirectory. For more information on upstream QuickJS, see: -https://github.com/quickjs-ng/quickjs +https://github.com/bellard/quickjs diff --git a/patches/001-add-extensions.patch b/patches/001-add-extensions.patch index 799b6ad..36f8c75 100644 --- a/patches/001-add-extensions.patch +++ b/patches/001-add-extensions.patch @@ -1,10 +1,10 @@ -diff --git a/quickjs-ng/quickjs.c b/quickjs-ng/quickjs.c ---- a/quickjs-ng/quickjs.c -+++ b/quickjs-ng/quickjs.c -@@ -58122,3 +58122,6 @@ uintptr_t js_std_cmd(int cmd, ...) { - #undef malloc - #undef free - #undef realloc +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -58552,3 +58552,6 @@ int JS_AddIntrinsicWeakRef(JSContext *ctx) + JS_FreeValue(ctx, obj); + return 0; + } + +#include +#include diff --git a/patches/002-add-disable-atomics-define.patch b/patches/002-add-disable-atomics-define.patch index bd871ac..2fd8000 100644 --- a/patches/002-add-disable-atomics-define.patch +++ b/patches/002-add-disable-atomics-define.patch @@ -1,12 +1,12 @@ -diff --git a/quickjs-ng/quickjs.c b/quickjs-ng/quickjs.c ---- a/quickjs-ng/quickjs.c -+++ b/quickjs-ng/quickjs.c +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c @@ -68,7 +68,7 @@ - // atomic_store etc. are completely busted in recent versions of tcc; - // somehow the compiler forgets to load |ptr| into %rdi when calling - // the __atomic_*() helpers in its lib/stdatomic.c and lib/atomic.S --#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !__STDC_NO_ATOMICS__ -+#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(QJS_DISABLE_ATOMICS) && !__STDC_NO_ATOMICS__ - #include "quickjs-c-atomics.h" + + /* define to include Atomics.* operations which depend on the OS + threads */ +-#if !defined(EMSCRIPTEN) ++#if !defined(EMSCRIPTEN) && !defined(QJS_DISABLE_ATOMICS) #define CONFIG_ATOMICS #endif + diff --git a/patches/003-fix-pedantic-cxx-warnings.patch b/patches/003-fix-pedantic-cxx-warnings.patch new file mode 100644 index 0000000..cefa0bc --- /dev/null +++ b/patches/003-fix-pedantic-cxx-warnings.patch @@ -0,0 +1,42 @@ +diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h +--- a/quickjs/quickjs.h ++++ b/quickjs/quickjs.h +@@ -248,6 +248,38 @@ typedef struct JSValue { + + #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } + ++/* msvc doesn't understand designated initializers without /std:c++20 */ ++#ifdef __cplusplus ++#undef JS_MKVAL ++#undef JS_MKPTR ++#undef JS_NAN ++static inline JSValue JS_MKPTR(int64_t tag, void *ptr) ++{ ++ JSValue v; ++ v.u.ptr = ptr; ++ v.tag = tag; ++ return v; ++} ++static inline JSValue JS_MKVAL(int64_t tag, int32_t int32) ++{ ++ JSValue v; ++ v.u.int32 = int32; ++ v.tag = tag; ++ return v; ++} ++static inline JSValue JS_MKNAN(void) ++{ ++ JSValue v; ++ v.u.float64 = NAN; ++ v.tag = JS_TAG_FLOAT64; ++ return v; ++} ++/* provide as macros for consistency and backward compat reasons */ ++#define JS_MKPTR(tag, ptr) JS_MKPTR(tag, ptr) ++#define JS_MKVAL(tag, val) JS_MKVAL(tag, val) ++#define JS_NAN JS_MKNAN() /* alas, not a constant expression */ ++#endif ++ + static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) + { + JSValue v; diff --git a/patches/003-freeruntime2.patch b/patches/003-freeruntime2.patch deleted file mode 100644 index d723fa0..0000000 --- a/patches/003-freeruntime2.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff --git a/quickjs-ng/quickjs.c b/quickjs-ng/quickjs.c ---- a/quickjs-ng/quickjs.c -+++ b/quickjs-ng/quickjs.c -@@ -2136,6 +2136,11 @@ void JS_SetRuntimeInfo(JSRuntime *rt, const char *s) - } - - void JS_FreeRuntime(JSRuntime *rt) -+{ -+ JS_FreeRuntime2(rt, NULL); -+} -+ -+void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) - { - struct list_head *el, *el1; - int i; -@@ -2193,7 +2198,11 @@ void JS_FreeRuntime(JSRuntime *rt) - } - #endif - -- assert(list_empty(&rt->gc_obj_list)); -+ if (!list_empty(&rt->gc_obj_list)) { -+ if (gc_leak_handler != NULL) { -+ gc_leak_handler("gc_obj_list is not empty"); -+ } -+ } - - /* free the classes */ - for(i = 0; i < rt->class_count; i++) { -diff --git a/quickjs-ng/quickjs.h b/quickjs-ng/quickjs.h ---- a/quickjs-ng/quickjs.h -+++ b/quickjs-ng/quickjs.h -@@ -449,6 +449,7 @@ JS_EXTERN void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); - JS_EXTERN void JS_UpdateStackTop(JSRuntime *rt); - JS_EXTERN JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); - JS_EXTERN void JS_FreeRuntime(JSRuntime *rt); -+JS_EXTERN void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)); - JS_EXTERN void *JS_GetRuntimeOpaque(JSRuntime *rt); - JS_EXTERN void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); - JS_EXTERN int JS_AddRuntimeFinalizer(JSRuntime *rt, diff --git a/patches/004-local-math-wrappers.patch b/patches/004-local-math-wrappers.patch new file mode 100644 index 0000000..2252f8a --- /dev/null +++ b/patches/004-local-math-wrappers.patch @@ -0,0 +1,99 @@ +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -45907,39 +45907,69 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val, + return __JS_NewFloat64(ctx, u.d - 1.0); + } + ++/* use local wrappers for math functions to ++ - avoid initializing data with dynamic library entry points. ++ - avoid some overhead if the call can be inlined at compile or link time. ++ */ ++static double js_math_fabs(double d) { return fabs(d); } ++static double js_math_floor(double d) { return floor(d); } ++static double js_math_ceil(double d) { return ceil(d); } ++static double js_math_sqrt(double d) { return sqrt(d); } ++static double js_math_acos(double d) { return acos(d); } ++static double js_math_asin(double d) { return asin(d); } ++static double js_math_atan(double d) { return atan(d); } ++static double js_math_atan2(double a, double b) { return atan2(a, b); } ++static double js_math_cos(double d) { return cos(d); } ++static double js_math_exp(double d) { return exp(d); } ++static double js_math_log(double d) { return log(d); } ++static double js_math_sin(double d) { return sin(d); } ++static double js_math_tan(double d) { return tan(d); } ++static double js_math_trunc(double d) { return trunc(d); } ++static double js_math_cosh(double d) { return cosh(d); } ++static double js_math_sinh(double d) { return sinh(d); } ++static double js_math_tanh(double d) { return tanh(d); } ++static double js_math_acosh(double d) { return acosh(d); } ++static double js_math_asinh(double d) { return asinh(d); } ++static double js_math_atanh(double d) { return atanh(d); } ++static double js_math_expm1(double d) { return expm1(d); } ++static double js_math_log1p(double d) { return log1p(d); } ++static double js_math_log2(double d) { return log2(d); } ++static double js_math_log10(double d) { return log10(d); } ++static double js_math_cbrt(double d) { return cbrt(d); } ++ + static const JSCFunctionListEntry js_math_funcs[] = { + JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ), + JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ), +- JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ), +- JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ), +- JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ), ++ JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, js_math_fabs ), ++ JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, js_math_floor ), ++ JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, js_math_ceil ), + JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ), +- JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ), +- +- JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, acos ), +- JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, asin ), +- JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, atan ), +- JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, atan2 ), +- JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, cos ), +- JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, exp ), +- JS_CFUNC_SPECIAL_DEF("log", 1, f_f, log ), ++ JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, js_math_sqrt ), ++ ++ JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, js_math_acos ), ++ JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, js_math_asin ), ++ JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, js_math_atan ), ++ JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, js_math_atan2 ), ++ JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, js_math_cos ), ++ JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, js_math_exp ), ++ JS_CFUNC_SPECIAL_DEF("log", 1, f_f, js_math_log ), + JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_pow ), +- JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, sin ), +- JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, tan ), ++ JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, js_math_sin ), ++ JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, js_math_tan ), + /* ES6 */ +- JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, trunc ), ++ JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, js_math_trunc ), + JS_CFUNC_SPECIAL_DEF("sign", 1, f_f, js_math_sign ), +- JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, cosh ), +- JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, sinh ), +- JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, tanh ), +- JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, acosh ), +- JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, asinh ), +- JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ), +- JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ), +- JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ), +- JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2 ), +- JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ), +- JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ), ++ JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, js_math_cosh ), ++ JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, js_math_sinh ), ++ JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, js_math_tanh ), ++ JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, js_math_acosh ), ++ JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, js_math_asinh ), ++ JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, js_math_atanh ), ++ JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, js_math_expm1 ), ++ JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, js_math_log1p ), ++ JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, js_math_log2 ), ++ JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, js_math_log10 ), ++ JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, js_math_cbrt ), + JS_CFUNC_DEF("hypot", 2, js_math_hypot ), + JS_CFUNC_DEF("random", 0, js_math_random ), + JS_CFUNC_SPECIAL_DEF("f16round", 1, f_f, js_math_f16round ), diff --git a/patches/005-msvc-compatibility.patch b/patches/005-msvc-compatibility.patch new file mode 100644 index 0000000..23272c9 --- /dev/null +++ b/patches/005-msvc-compatibility.patch @@ -0,0 +1,452 @@ +diff --git a/quickjs/cutils.c b/quickjs/cutils.c +--- a/quickjs/cutils.c ++++ b/quickjs/cutils.c +@@ -29,6 +29,10 @@ + + #include "cutils.h" + ++#if defined(_MSC_VER) ++#include "win32-gettimeofday.c" ++#endif ++ + void pstrcpy(char *buf, int buf_size, const char *str) + { + int c; +diff --git a/quickjs/cutils.h b/quickjs/cutils.h +--- a/quickjs/cutils.h ++++ b/quickjs/cutils.h +@@ -29,17 +29,45 @@ + #include + #include + ++#if defined(_MSC_VER) ++ #if !defined(NOMINMAX) ++ #define NOMINMAX // For windows.h ++ #endif ++ #include ++ #include ++ #include // For timeval struct, etc ++#endif ++ ++#if defined(_MSC_VER) && !defined(__clang__) ++# define likely(x) (x) ++# define unlikely(x) (x) ++# define force_inline __forceinline ++# define no_inline __declspec(noinline) ++# define __maybe_unused ++# define __attribute__(x) ++# define __attribute(x) ++#else + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) + #define force_inline inline __attribute__((always_inline)) + #define no_inline __attribute__((noinline)) + #define __maybe_unused __attribute__((unused)) ++#endif + + #define xglue(x, y) x ## y + #define glue(x, y) xglue(x, y) + #define stringify(s) tostring(s) + #define tostring(s) #s + ++#if defined(_MSC_VER) && !defined(__clang__) ++#include ++#define INF INFINITY ++#define NEG_INF -INFINITY ++#else ++#define INF (1.0/0.0) ++#define NEG_INF (-1.0/0.0) ++#endif ++ + #ifndef offsetof + #define offsetof(type, field) ((size_t) &((type *)0)->field) + #endif +@@ -66,6 +94,10 @@ enum { + }; + #endif + ++#if defined(_MSC_VER) ++int gettimeofday(struct timeval * tp, struct timezone * tzp); ++#endif ++ + void pstrcpy(char *buf, int buf_size, const char *str); + char *pstrcat(char *buf, int buf_size, const char *s); + int strstart(const char *str, const char *val, const char **ptr); +@@ -128,82 +160,113 @@ static inline int64_t min_int64(int64_t a, int64_t b) + /* WARNING: undefined if a = 0 */ + static inline int clz32(unsigned int a) + { ++#if defined(_MSC_VER) && !defined(__clang__) ++ unsigned long index; ++ _BitScanReverse(&index, a); ++ return 31 - index; ++#else + return __builtin_clz(a); ++#endif + } + + /* WARNING: undefined if a = 0 */ + static inline int clz64(uint64_t a) + { ++#if defined(_MSC_VER) && !defined(__clang__) ++#if INTPTR_MAX == INT64_MAX ++ unsigned long index; ++ _BitScanReverse64(&index, a); ++ return 63 - index; ++#else ++ if (a >> 32) ++ return clz32((unsigned)(a >> 32)); ++ else ++ return clz32((unsigned)a) + 32; ++#endif ++#else + return __builtin_clzll(a); ++#endif + } + + /* WARNING: undefined if a = 0 */ + static inline int ctz32(unsigned int a) + { ++#if defined(_MSC_VER) && !defined(__clang__) ++ unsigned long index; ++ _BitScanForward(&index, a); ++ return index; ++#else + return __builtin_ctz(a); ++#endif + } + + /* WARNING: undefined if a = 0 */ + static inline int ctz64(uint64_t a) + { ++#if defined(_MSC_VER) && !defined(__clang__) ++ unsigned long index; ++ _BitScanForward64(&index, a); ++ return index; ++#else + return __builtin_ctzll(a); ++#endif + } + +-struct __attribute__((packed)) packed_u64 { +- uint64_t v; +-}; +- +-struct __attribute__((packed)) packed_u32 { +- uint32_t v; +-}; +- +-struct __attribute__((packed)) packed_u16 { +- uint16_t v; +-}; +- + static inline uint64_t get_u64(const uint8_t *tab) + { +- return ((const struct packed_u64 *)tab)->v; ++ uint64_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline int64_t get_i64(const uint8_t *tab) + { +- return (int64_t)((const struct packed_u64 *)tab)->v; ++ int64_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline void put_u64(uint8_t *tab, uint64_t val) + { +- ((struct packed_u64 *)tab)->v = val; ++ memcpy(tab, &val, sizeof(val)); + } + + static inline uint32_t get_u32(const uint8_t *tab) + { +- return ((const struct packed_u32 *)tab)->v; ++ uint32_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline int32_t get_i32(const uint8_t *tab) + { +- return (int32_t)((const struct packed_u32 *)tab)->v; ++ int32_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline void put_u32(uint8_t *tab, uint32_t val) + { +- ((struct packed_u32 *)tab)->v = val; ++ memcpy(tab, &val, sizeof(val)); + } + + static inline uint32_t get_u16(const uint8_t *tab) + { +- return ((const struct packed_u16 *)tab)->v; ++ uint16_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline int32_t get_i16(const uint8_t *tab) + { +- return (int16_t)((const struct packed_u16 *)tab)->v; ++ int16_t v; ++ memcpy(&v, tab, sizeof(v)); ++ return v; + } + + static inline void put_u16(uint8_t *tab, uint16_t val) + { +- ((struct packed_u16 *)tab)->v = val; ++ memcpy(tab, &val, sizeof(val)); + } + + static inline uint32_t get_u8(const uint8_t *tab) +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -28,7 +28,14 @@ + #include + #include + #include ++#if !defined(QUICKJS_HAVE_SYS_TIME_H) ++ #if defined(__linux__) || defined(__APPLE__) ++ #define QUICKJS_HAVE_SYS_TIME_H ++ #endif ++#endif ++#if defined(QUICKJS_HAVE_SYS_TIME_H) + #include ++#endif + #include + #include + #include +@@ -38,6 +45,8 @@ + #include + #elif defined(__FreeBSD__) + #include ++#elif defined(_WIN32) ++#include + #endif + + #include "cutils.h" +@@ -49,7 +58,7 @@ + + #define OPTIMIZE 1 + #define SHORT_OPCODES 1 +-#if defined(EMSCRIPTEN) ++#if defined(EMSCRIPTEN) || defined(_MSC_VER) + #define DIRECT_DISPATCH 0 + #else + #define DIRECT_DISPATCH 1 +@@ -1601,17 +1610,39 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) + return FALSE; + } + #else ++ ++#if !defined(__has_builtin) ++ #define __has_builtin(x) 0 ++#endif ++ ++#if defined(__GNUC__) || defined(__clang__) || __has_builtin(__builtin_frame_address) + /* Note: OS and CPU dependent */ + static inline uintptr_t js_get_stack_pointer(void) + { + return (uintptr_t)__builtin_frame_address(0); + } ++#elif defined(_MSC_VER) && !defined(__clang__) ++static inline uintptr_t js_get_stack_pointer(void) ++{ ++ return (uintptr_t)_AddressOfReturnAddress(); ++} ++#else ++static inline uintptr_t js_get_stack_pointer(void) ++{ ++ return 0; ++} ++#define NO_VALID_STACK_POINTER ++#endif + + static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) + { ++#if defined(NO_VALID_STACK_POINTER) ++ return FALSE; ++#else + uintptr_t sp; + sp = js_get_stack_pointer() - alloca_size; + return unlikely(sp < rt->stack_limit); ++#endif + } + #endif + +@@ -12300,7 +12331,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, + if (!(flags & ATOD_INT_ONLY) && + (atod_type == ATOD_TYPE_FLOAT64) && + strstart(p, "Infinity", &p)) { +- double d = 1.0 / 0.0; ++ double d = INF; + if (is_neg) + d = -d; + val = JS_NewFloat64(ctx, d); +@@ -22365,7 +22396,7 @@ static int json_parse_number(JSParseState *s, const uint8_t **pp) + if (!is_digit(*p)) { + if (s->ext_json) { + if (strstart((const char *)p, "Infinity", (const char **)&p)) { +- d = 1.0 / 0.0; ++ d = INF; + if (*p_start == '-') + d = -d; + goto done; +@@ -45473,7 +45504,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, + uint32_t tag; + + if (unlikely(argc == 0)) { +- return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0); ++ return __JS_NewFloat64(ctx, is_max ? NEG_INF : INF); + } + + tag = JS_VALUE_GET_TAG(argv[0]); +@@ -53063,7 +53094,7 @@ static const JSCFunctionListEntry js_global_funcs[] = { + JS_CFUNC_MAGIC_DEF("encodeURIComponent", 1, js_global_encodeURI, 1 ), + JS_CFUNC_DEF("escape", 1, js_global_escape ), + JS_CFUNC_DEF("unescape", 1, js_global_unescape ), +- JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ), ++ JS_PROP_DOUBLE_DEF("Infinity", INF, 0 ), + JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ), + JS_PROP_UNDEFINED_DEF("undefined", 0 ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), +diff --git a/quickjs/win32-gettimeofday.c b/quickjs/win32-gettimeofday.c +new file mode 100644 +--- /dev/null ++++ b/quickjs/win32-gettimeofday.c +@@ -0,0 +1,126 @@ ++/* ++ * gettimeofday.c ++ * Win32 gettimeofday() replacement ++ * ++ * src/port/gettimeofday.c ++ * ++ * Copyright (c) 2003 SRA, Inc. ++ * Copyright (c) 2003 SKC, Inc. ++ * ++ * Permission to use, copy, modify, and distribute this software and ++ * its documentation for any purpose, without fee, and without a ++ * written agreement is hereby granted, provided that the above ++ * copyright notice and this paragraph and the following two ++ * paragraphs appear in all copies. ++ * ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, ++ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING ++ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS ++ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS ++ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, ++ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ++ */ ++ ++#if defined(_MSC_VER) ++ ++#if !defined(NOMINMAX) ++ #define NOMINMAX // For windows.h ++#endif ++#include ++ ++/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */ ++static const unsigned __int64 epoch = 116444736000000000ULL; ++ ++/* ++ * FILETIME represents the number of 100-nanosecond intervals since ++ * January 1, 1601 (UTC). ++ */ ++#define FILETIME_UNITS_PER_SEC 10000000L ++#define FILETIME_UNITS_PER_USEC 10 ++ ++/* ++ * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a ++ * signature, so we can just store a pointer to whichever we find. This ++ * is the pointer's type. ++ */ ++typedef VOID(WINAPI * PgGetSystemTimeFn) (LPFILETIME); ++ ++/* One-time initializer function, must match that signature. */ ++static void WINAPI init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime); ++ ++/* Storage for the function we pick at runtime */ ++static PgGetSystemTimeFn pg_get_system_time = &init_gettimeofday; ++ ++/* ++ * One time initializer. Determine whether GetSystemTimePreciseAsFileTime ++ * is available and if so, plan to use it; if not, fall back to ++ * GetSystemTimeAsFileTime. ++ */ ++static void WINAPI ++init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime) ++{ ++ /* ++ * Because it's guaranteed that kernel32.dll will be linked into our ++ * address space already, we don't need to LoadLibrary it and worry about ++ * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper. ++ * ++ * We'll just look up the address of GetSystemTimePreciseAsFileTime if ++ * present. ++ * ++ * While we could look up the Windows version and skip this on Windows ++ * versions below Windows 8 / Windows Server 2012 there isn't much point, ++ * and determining the windows version is its self somewhat Windows ++ * version and development SDK specific... ++ */ ++ pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress( ++ GetModuleHandle(TEXT("kernel32.dll")), ++ "GetSystemTimePreciseAsFileTime"); ++ if (pg_get_system_time == NULL) ++ { ++ /* ++ * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if ++ * the function isn't present. No other error should occur. ++ * ++ * We can't report an error here because this might be running in ++ * frontend code; and even if we're in the backend, it's too early to ++ * elog(...) if we get some unexpected error. Also, it's not a ++ * serious problem, so just silently fall back to ++ * GetSystemTimeAsFileTime irrespective of why the failure occurred. ++ */ ++ pg_get_system_time = &GetSystemTimeAsFileTime; ++ } ++ ++ (*pg_get_system_time) (lpSystemTimeAsFileTime); ++} ++ ++/* ++ * timezone information is stored outside the kernel so tzp isn't used anymore. ++ * ++ * Note: this function is not for Win32 high precision timing purposes. See ++ * elapsed_time(). ++ */ ++int ++gettimeofday(struct timeval * tp, struct timezone * tzp) ++{ ++ FILETIME file_time; ++ ULARGE_INTEGER ularge; ++ ++ if (tp) { ++ (*pg_get_system_time) (&file_time); ++ ularge.LowPart = file_time.dwLowDateTime; ++ ularge.HighPart = file_time.dwHighDateTime; ++ ++ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC); ++ tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC) ++ / FILETIME_UNITS_PER_USEC); ++ } ++ ++ return 0; ++} ++ ++#endif // defined(_MSC_VER) diff --git a/patches/006-msvc-compatibility-2.patch b/patches/006-msvc-compatibility-2.patch new file mode 100644 index 0000000..d955877 --- /dev/null +++ b/patches/006-msvc-compatibility-2.patch @@ -0,0 +1,190 @@ +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -7886,7 +7886,7 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, + JS_ThrowTypeErrorNotASymbol(ctx); + goto fail; + } +- prop = js_symbol_to_atom(ctx, (JSValue)name); ++ prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (prs) { +@@ -7917,7 +7917,7 @@ static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj, + /* safety check */ + if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) + return JS_ThrowTypeErrorNotASymbol(ctx); +- prop = js_symbol_to_atom(ctx, (JSValue)name); ++ prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { +@@ -7944,7 +7944,7 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, + JS_ThrowTypeErrorNotASymbol(ctx); + goto fail; + } +- prop = js_symbol_to_atom(ctx, (JSValue)name); ++ prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { +@@ -8043,7 +8043,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) + return -1; + } + p = JS_VALUE_GET_OBJ(obj); +- prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand)); ++ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(brand))); + return (prs != NULL); + } + +@@ -9762,7 +9762,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, + return -1; + } + /* this code relies on the fact that Uint32 are never allocated */ +- val = (JSValueConst)JS_NewUint32(ctx, array_length); ++ val = JS_VALUE_MAKE_CONST(JS_NewUint32(ctx, array_length)); + /* prs may have been modified */ + prs = find_own_property(&pr, p, prop); + assert(prs != NULL); +@@ -16829,7 +16829,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, + rt->current_stack_frame = sf; + ctx = p->u.cfunc.realm; /* change the current realm */ + sf->js_mode = 0; +- sf->cur_func = (JSValue)func_obj; ++ sf->cur_func = JS_VALUE_CONST_CAST(func_obj); + sf->arg_count = argc; + arg_buf = argv; + +@@ -17074,7 +17074,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, + sf->js_mode = b->js_mode; + arg_buf = argv; + sf->arg_count = argc; +- sf->cur_func = (JSValue)func_obj; ++ sf->cur_func = JS_VALUE_CONST_CAST(func_obj); + init_list_head(&sf->var_ref_list); + var_refs = p->u.func.var_refs; + +@@ -41960,8 +41960,8 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target, + if (!JS_IsUndefined(mapperFunction)) { + JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source }; + element = JS_Call(ctx, mapperFunction, thisArg, 3, args); +- JS_FreeValue(ctx, (JSValue)args[0]); +- JS_FreeValue(ctx, (JSValue)args[1]); ++ JS_FreeValue(ctx, JS_VALUE_CONST_CAST(args[0])); ++ JS_FreeValue(ctx, JS_VALUE_CONST_CAST(args[1])); + if (JS_IsException(element)) + return -1; + } +@@ -44382,7 +44382,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, + str = js_new_string8(ctx, "g"); + if (JS_IsException(str)) + goto fail; +- args[args_len++] = (JSValueConst)str; ++ args[args_len++] = JS_VALUE_MAKE_CONST(str); + } + rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args); + JS_FreeValue(ctx, str); +@@ -49850,7 +49850,7 @@ static JSValue js_weakref_new(JSContext *ctx, JSValueConst val) + } else { + assert(JS_IsUndefined(val)); + } +- return (JSValue)val; ++ return JS_VALUE_CONST_CAST(val); + } + + #define MAGIC_SET (1 << 0) +@@ -49980,7 +49980,7 @@ static JSValue map_normalize_key(JSContext *ctx, JSValue key) + + static JSValueConst map_normalize_key_const(JSContext *ctx, JSValueConst key) + { +- return (JSValueConst)map_normalize_key(ctx, (JSValue)key); ++ return JS_VALUE_MAKE_CONST(map_normalize_key(ctx, JS_VALUE_CONST_CAST(key))); + } + + /* hash multipliers, same as the Linux kernel (see Knuth vol 3, +@@ -50413,7 +50413,7 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, + args[0] = args[1]; + else + args[0] = JS_DupValue(ctx, mr->value); +- args[2] = (JSValue)this_val; ++ args[2] = JS_VALUE_CONST_CAST(this_val); + ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args); + JS_FreeValue(ctx, args[0]); + if (!magic) +@@ -52130,7 +52130,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, + goto fail_reject; + } + resolve_element_data[0] = JS_NewBool(ctx, FALSE); +- resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index); ++ resolve_element_data[1] = JS_VALUE_MAKE_CONST(JS_NewInt32(ctx, index)); + resolve_element_data[2] = values; + resolve_element_data[3] = resolving_funcs[is_promise_any]; + resolve_element_data[4] = resolve_element_env; +@@ -52551,7 +52551,7 @@ static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx, + { + JSValueConst func_data[1]; + +- func_data[0] = (JSValueConst)JS_NewBool(ctx, done); ++ func_data[0] = JS_VALUE_MAKE_CONST(JS_NewBool(ctx, done)); + return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap, + 1, 0, 1, func_data); + } +@@ -56825,8 +56825,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { + cmp = (a_idx > b_idx) - (a_idx < b_idx); + } + done: +- JS_FreeValue(ctx, (JSValue)argv[0]); +- JS_FreeValue(ctx, (JSValue)argv[1]); ++ JS_FreeValue(ctx, JS_VALUE_CONST_CAST(argv[0])); ++ JS_FreeValue(ctx, JS_VALUE_CONST_CAST(argv[1])); + } + return cmp; + } +diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h +--- a/quickjs/quickjs.h ++++ b/quickjs/quickjs.h +@@ -109,6 +109,8 @@ typedef struct JSRefCountHeader { + for objective C) */ + typedef struct __JSValue *JSValue; + typedef const struct __JSValue *JSValueConst; ++#define JS_VALUE_CONST_CAST(cVal) (JSValue)cVal ++#define JS_VALUE_MAKE_CONST(val) (JSValueConst)val + + #define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf) + /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +@@ -146,6 +148,8 @@ static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) + typedef uint64_t JSValue; + + #define JSValueConst JSValue ++#define JS_VALUE_CONST_CAST(cVal) cVal ++#define JS_VALUE_MAKE_CONST(val) val + + #define JS_VALUE_GET_TAG(v) (int)((v) >> 32) + #define JS_VALUE_GET_INT(v) (int)(v) +@@ -231,6 +235,8 @@ typedef struct JSValue { + } JSValue; + + #define JSValueConst JSValue ++#define JS_VALUE_CONST_CAST(cVal) cVal ++#define JS_VALUE_MAKE_CONST(val) val + + #define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) + /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +@@ -733,7 +739,7 @@ static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } +- return (JSValue)v; ++ return JS_VALUE_CONST_CAST(v); + } + + static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) +@@ -742,7 +748,7 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } +- return (JSValue)v; ++ return JS_VALUE_CONST_CAST(v); + } + + JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2); diff --git a/patches/007-fix-dtoa-includes.patch b/patches/007-fix-dtoa-includes.patch new file mode 100644 index 0000000..f4f21b8 --- /dev/null +++ b/patches/007-fix-dtoa-includes.patch @@ -0,0 +1,13 @@ +diff --git a/quickjs/dtoa.c b/quickjs/dtoa.c +--- a/quickjs/dtoa.c ++++ b/quickjs/dtoa.c +@@ -28,9 +28,7 @@ + #include + #include + #include +-#include + #include +-#include + + #include "cutils.h" + #include "dtoa.h" diff --git a/patches/008-freeruntime2.patch b/patches/008-freeruntime2.patch new file mode 100644 index 0000000..3dc887c --- /dev/null +++ b/patches/008-freeruntime2.patch @@ -0,0 +1,45 @@ +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -1978,6 +1978,11 @@ void JS_SetRuntimeInfo(JSRuntime *rt, const char *s) + } + + void JS_FreeRuntime(JSRuntime *rt) ++{ ++ JS_FreeRuntime2(rt, NULL); ++} ++ ++void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) + { + struct list_head *el, *el1; + int i; +@@ -2036,8 +2041,16 @@ void JS_FreeRuntime(JSRuntime *rt) + printf("Secondary object leaks: %d\n", count); + } + #endif +- assert(list_empty(&rt->gc_obj_list)); +- assert(list_empty(&rt->weakref_list)); ++ if (!list_empty(&rt->gc_obj_list)) { ++ if (gc_leak_handler != NULL) { ++ gc_leak_handler("gc_obj_list is not empty"); ++ } ++ } ++ if (!list_empty(&rt->weakref_list)) { ++ if (gc_leak_handler != NULL) { ++ gc_leak_handler("weakref_list is not empty"); ++ } ++ } + + /* free the classes */ + for(i = 0; i < rt->class_count; i++) { +diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h +--- a/quickjs/quickjs.h ++++ b/quickjs/quickjs.h +@@ -413,6 +413,7 @@ void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); + void JS_UpdateStackTop(JSRuntime *rt); + JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); + void JS_FreeRuntime(JSRuntime *rt); ++void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)); + void *JS_GetRuntimeOpaque(JSRuntime *rt); + void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); + typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp); diff --git a/patches/009-bsd-compile-fixes.patch b/patches/009-bsd-compile-fixes.patch new file mode 100644 index 0000000..5ccb540 --- /dev/null +++ b/patches/009-bsd-compile-fixes.patch @@ -0,0 +1,24 @@ +diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c +--- a/quickjs/quickjs.c ++++ b/quickjs/quickjs.c +@@ -41,7 +41,7 @@ + #include + #if defined(__APPLE__) + #include +-#elif defined(__linux__) || defined(__GLIBC__) ++#elif defined(__linux__) || defined(__GLIBC__) || defined(__ANDROID__) + #include + #elif defined(__FreeBSD__) + #include +@@ -1724,9 +1724,9 @@ static size_t js_def_malloc_usable_size(const void *ptr) + return malloc_size(ptr); + #elif defined(_WIN32) + return _msize((void *)ptr); +-#elif defined(EMSCRIPTEN) ++#elif defined(EMSCRIPTEN) || defined(__OpenBSD__) || defined(__NetBSD__) + return 0; +-#elif defined(__linux__) || defined(__GLIBC__) ++#elif defined(__linux__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__GLIBC__) + return malloc_usable_size((void *)ptr); + #else + /* change this to `return 0;` if compilation fails */ diff --git a/patches/apply_quickjs_patches.cmake b/patches/apply_quickjs_patches.cmake index a2cd7f4..118dde9 100644 --- a/patches/apply_quickjs_patches.cmake +++ b/patches/apply_quickjs_patches.cmake @@ -54,7 +54,18 @@ quickjs_apply_patches( PATCHES "001-add-extensions.patch" "002-add-disable-atomics-define.patch" - "003-freeruntime2.patch" + "003-fix-pedantic-cxx-warnings.patch" + "004-local-math-wrappers.patch" + "005-msvc-compatibility.patch" + "006-msvc-compatibility-2.patch" + "007-fix-dtoa-includes.patch" + "008-freeruntime2.patch" + "009-bsd-compile-fixes.patch" ) +# Finally, rename VERSION to VERSION.txt +if(EXISTS "${_directoryOfThisScript}/../VERSION") + file(RENAME "${_directoryOfThisScript}/../VERSION" "${_directoryOfThisScript}/../VERSION.txt") +endif() + message(STATUS "Finished applying patches.") diff --git a/quickjs-ng/CMakeLists.txt b/quickjs-ng/CMakeLists.txt deleted file mode 100644 index f49a052..0000000 --- a/quickjs-ng/CMakeLists.txt +++ /dev/null @@ -1,444 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(quickjs LANGUAGES C) - -include(CheckCCompilerFlag) -include(GNUInstallDirs) - -set(CMAKE_C_VISIBILITY_PRESET hidden) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS ON) -set(CMAKE_C_STANDARD 11) - -# MINGW doesn't exist in older cmake versions, newer versions don't know -# about CMAKE_COMPILER_IS_MINGW, and there is no unique CMAKE_C_COMPILER_ID -# for mingw-based compilers... -if(MINGW) - # do nothing -elseif(CMAKE_C_COMPILER MATCHES "mingw") - set(MINGW TRUE) -else() - set(MINGW FALSE) -endif() - -if(NOT CMAKE_BUILD_TYPE) - message(STATUS "No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif() - -message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode") -message(STATUS "Building with ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION} on ${CMAKE_SYSTEM}") - -macro(xcheck_add_c_compiler_flag FLAG) - string(REPLACE "-" "" FLAG_NO_HYPHEN ${FLAG}) - check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG_NO_HYPHEN}) - if(COMPILER_SUPPORTS_${FLAG_NO_HYPHEN}) - add_compile_options(${FLAG}) - endif() -endmacro() - -xcheck_add_c_compiler_flag(-Wall) -if(NOT MSVC AND NOT IOS) - xcheck_add_c_compiler_flag(-Werror) - xcheck_add_c_compiler_flag(-Wextra) -endif() -xcheck_add_c_compiler_flag(-Wformat=2) -xcheck_add_c_compiler_flag(-Wno-implicit-fallthrough) -xcheck_add_c_compiler_flag(-Wno-sign-compare) -xcheck_add_c_compiler_flag(-Wno-missing-field-initializers) -xcheck_add_c_compiler_flag(-Wno-unused-parameter) -xcheck_add_c_compiler_flag(-Wno-unused-but-set-variable) -xcheck_add_c_compiler_flag(-Wno-unused-result) -xcheck_add_c_compiler_flag(-Wno-stringop-truncation) -xcheck_add_c_compiler_flag(-Wno-array-bounds) -xcheck_add_c_compiler_flag(-funsigned-char) - -# ClangCL is command line compatible with MSVC, so 'MSVC' is set. -if(MSVC) - xcheck_add_c_compiler_flag(-Wno-unsafe-buffer-usage) - xcheck_add_c_compiler_flag(-Wno-sign-conversion) - xcheck_add_c_compiler_flag(-Wno-nonportable-system-include-path) - xcheck_add_c_compiler_flag(-Wno-implicit-int-conversion) - xcheck_add_c_compiler_flag(-Wno-shorten-64-to-32) - xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier) - xcheck_add_c_compiler_flag(-Wno-reserved-identifier) - xcheck_add_c_compiler_flag(-Wdeprecated-declarations) - xcheck_add_c_compiler_flag(/experimental:c11atomics) - xcheck_add_c_compiler_flag(/wd4018) # -Wno-sign-conversion - xcheck_add_c_compiler_flag(/wd4061) # -Wno-implicit-fallthrough - xcheck_add_c_compiler_flag(/wd4100) # -Wno-unused-parameter - xcheck_add_c_compiler_flag(/wd4200) # -Wno-zero-length-array - xcheck_add_c_compiler_flag(/wd4242) # -Wno-shorten-64-to-32 - xcheck_add_c_compiler_flag(/wd4244) # -Wno-shorten-64-to-32 - xcheck_add_c_compiler_flag(/wd4245) # -Wno-sign-compare - xcheck_add_c_compiler_flag(/wd4267) # -Wno-shorten-64-to-32 - xcheck_add_c_compiler_flag(/wd4388) # -Wno-sign-compare - xcheck_add_c_compiler_flag(/wd4389) # -Wno-sign-compare - xcheck_add_c_compiler_flag(/wd4456) # Hides previous local declaration - xcheck_add_c_compiler_flag(/wd4457) # Hides function parameter - xcheck_add_c_compiler_flag(/wd4710) # Function not inlined - xcheck_add_c_compiler_flag(/wd4711) # Function was inlined - xcheck_add_c_compiler_flag(/wd4820) # Padding added after construct - xcheck_add_c_compiler_flag(/wd4996) # -Wdeprecated-declarations - xcheck_add_c_compiler_flag(/wd5045) # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified -endif() - -# Set a 8MB default stack size on Windows. -# It defaults to 1MB on MSVC, which is the same as our current JS stack size, -# so it will overflow and crash otherwise. -# On MinGW it defaults to 2MB. -if(WIN32) - if(MSVC) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") - else() - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,8388608") - endif() -endif() - -# MacOS and GCC 11 or later need -Wno-maybe-uninitialized -# https://github.com/quickjs-ng/quickjs/issues/453 -if(APPLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11) - xcheck_add_c_compiler_flag(-Wno-maybe-uninitialized) -endif() - -if(CMAKE_SYSTEM_NAME STREQUAL "WASI") - add_compile_definitions( - _WASI_EMULATED_PROCESS_CLOCKS - _WASI_EMULATED_SIGNAL - ) - add_link_options( - -lwasi-emulated-process-clocks - -lwasi-emulated-signal - ) -endif() - -if(CMAKE_BUILD_TYPE MATCHES "Debug") - xcheck_add_c_compiler_flag(/Od) - xcheck_add_c_compiler_flag(-O0) - xcheck_add_c_compiler_flag(-ggdb) - xcheck_add_c_compiler_flag(-fno-omit-frame-pointer) -endif() - -macro(xoption OPTION_NAME OPTION_TEXT OPTION_DEFAULT) - option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT}) - if(DEFINED ENV{${OPTION_NAME}}) - # Allow setting the option through an environment variable. - set(${OPTION_NAME} $ENV{${OPTION_NAME}}) - endif() - if(${OPTION_NAME}) - add_definitions(-D${OPTION_NAME}) - endif() - message(STATUS " ${OPTION_NAME}: ${${OPTION_NAME}}") -endmacro() - -xoption(BUILD_SHARED_LIBS "Build a shared library" OFF) -if(BUILD_SHARED_LIBS) - message(STATUS "Building a shared library") -endif() - -# note: QJS_ENABLE_TSAN is currently incompatible with the other sanitizers but we -# don't explicitly check for that because who knows what the future will bring? -# QJS_ENABLE_MSAN only works with clang at the time of writing; also not checked -# for the same reason -xoption(QJS_BUILD_EXAMPLES "Build examples" OFF) -xoption(QJS_BUILD_CLI_STATIC "Build a static qjs executable" OFF) -xoption(QJS_BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF) -xoption(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF) -xoption(QJS_DISABLE_PARSER "Disable JS source code parser" OFF) -xoption(QJS_ENABLE_ASAN "Enable AddressSanitizer (ASan)" OFF) -xoption(QJS_ENABLE_MSAN "Enable MemorySanitizer (MSan)" OFF) -xoption(QJS_ENABLE_TSAN "Enable ThreadSanitizer (TSan)" OFF) -xoption(QJS_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF) - -if(QJS_ENABLE_ASAN) -message(STATUS "Building with ASan") -add_compile_options( - -fsanitize=address - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -add_link_options( - -fsanitize=address - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -endif() - -if(QJS_ENABLE_MSAN) -message(STATUS "Building with MSan") -add_compile_options( - -fsanitize=memory - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -add_link_options( - -fsanitize=memory - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -endif() - -if(QJS_ENABLE_TSAN) -message(STATUS "Building with TSan") -add_compile_options( - -fsanitize=thread - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -add_link_options( - -fsanitize=thread - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -endif() - -if(QJS_ENABLE_UBSAN) -message(STATUS "Building with UBSan") -add_compile_options( - -fsanitize=undefined - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -add_link_options( - -fsanitize=undefined - -fno-sanitize-recover=all - -fno-omit-frame-pointer -) -endif() - - -# QuickJS library -# - -xoption(QJS_BUILD_LIBC "Build standard library modules as part of the library" OFF) -macro(add_qjs_libc_if_needed target) - if(NOT QJS_BUILD_LIBC) - target_sources(${target} PRIVATE quickjs-libc.c) - endif() -endmacro() -macro(add_static_if_needed target) - if(QJS_BUILD_CLI_STATIC OR MINGW) - target_link_options(${target} PRIVATE -static) - if(MINGW) - target_link_options(${target} PRIVATE -static-libgcc) - endif() - endif() -endmacro() - -set(qjs_sources - cutils.c - dtoa.c - libregexp.c - libunicode.c - quickjs.c -) - -if(QJS_BUILD_LIBC) - list(APPEND qjs_sources quickjs-libc.c) -endif() -list(APPEND qjs_defines _GNU_SOURCE) -if(WIN32) - # NB: Windows 7 is EOL and we are only supporting in so far as it doesn't interfere with progress. - list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0601) -endif() -list(APPEND qjs_libs ${CMAKE_DL_LIBS}) -find_package(Threads) -if(NOT CMAKE_SYSTEM_NAME STREQUAL "WASI") - list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT}) -endif() - -# try to find libm -find_library(M_LIBRARIES m) -if(M_LIBRARIES OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC") - list(APPEND qjs_libs m) -endif() - -add_library(qjs ${qjs_sources}) -target_compile_definitions(qjs PRIVATE ${qjs_defines}) -target_include_directories(qjs PUBLIC - $ - $ -) -target_link_libraries(qjs PUBLIC ${qjs_libs}) - -if(EMSCRIPTEN) - add_executable(qjs_wasm ${qjs_sources}) - target_link_options(qjs_wasm PRIVATE - # in emscripten 3.x, this will be set to 16k which is too small for quickjs. #write sth. to force github rebuild - -sSTACK_SIZE=2097152 # let it be 2m = 2 * 1024 * 1024 = 2097152, otherwise, stack overflow may be occured at bootstrap - -sNO_INVOKE_RUN - -sNO_EXIT_RUNTIME - -sMODULARIZE # do not mess the global - -sEXPORT_ES6 # export js file to morden es module - -sEXPORT_NAME=getQuickJs # give a name - -sTEXTDECODER=1 # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail - -sNO_DEFAULT_TO_CXX # this project is pure c project, no need for c plus plus handle - -sEXPORTED_RUNTIME_METHODS=ccall,cwrap - ) - target_compile_definitions(qjs_wasm PRIVATE ${qjs_defines}) - target_link_libraries(qjs_wasm m) -endif() - - -# QuickJS bytecode compiler -# - -add_executable(qjsc - qjsc.c -) -add_qjs_libc_if_needed(qjsc) -add_static_if_needed(qjsc) -target_compile_definitions(qjsc PRIVATE ${qjs_defines}) -target_link_libraries(qjsc qjs) - - -# QuickJS CLI -# - -add_executable(qjs_exe - gen/repl.c - gen/standalone.c - qjs.c -) -add_qjs_libc_if_needed(qjs_exe) -add_static_if_needed(qjs_exe) -set_target_properties(qjs_exe PROPERTIES - OUTPUT_NAME "qjs" -) -target_compile_definitions(qjs_exe PRIVATE ${qjs_defines}) -target_link_libraries(qjs_exe qjs) -if(NOT WIN32) - set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE) -endif() -if(QJS_BUILD_CLI_WITH_MIMALLOC OR QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) - find_package(mimalloc REQUIRED) - # Upstream mimalloc doesn't provide a way to know if both libraries are supported. - if(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) - target_link_libraries(qjs_exe mimalloc-static) - else() - target_link_libraries(qjs_exe mimalloc) - endif() -endif() - -# Test262 runner -# - -if(NOT EMSCRIPTEN) - add_executable(run-test262 - run-test262.c - ) - add_qjs_libc_if_needed(run-test262) - target_compile_definitions(run-test262 PRIVATE ${qjs_defines}) - target_link_libraries(run-test262 qjs) -endif() - -# Interrupt test -# - -add_executable(api-test - api-test.c -) -target_compile_definitions(api-test PRIVATE ${qjs_defines}) -target_link_libraries(api-test qjs) - -# Unicode generator -# - -add_executable(unicode_gen EXCLUDE_FROM_ALL - cutils.c - libunicode.c - unicode_gen.c -) -target_compile_definitions(unicode_gen PRIVATE ${qjs_defines}) - -add_executable(function_source - gen/function_source.c -) -add_qjs_libc_if_needed(function_source) -target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_definitions(function_source PRIVATE ${qjs_defines}) -target_link_libraries(function_source qjs) - -# Examples -# - -if(QJS_BUILD_EXAMPLES) - add_executable(hello - gen/hello.c - ) - add_qjs_libc_if_needed(hello) - target_include_directories(hello PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_definitions(hello PRIVATE ${qjs_defines}) - target_link_libraries(hello qjs) - - add_executable(hello_module - gen/hello_module.c - ) - add_qjs_libc_if_needed(hello_module) - target_include_directories(hello_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_definitions(hello_module PRIVATE ${qjs_defines}) - target_link_libraries(hello_module qjs) - - add_library(fib MODULE examples/fib.c) - set_target_properties(fib PROPERTIES - PREFIX "" - C_VISIBILITY_PRESET default - ) - target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(fib qjs) - elseif(APPLE) - target_link_options(fib PRIVATE -undefined dynamic_lookup) - endif() - - add_library(point MODULE examples/point.c) - set_target_properties(point PROPERTIES - PREFIX "" - C_VISIBILITY_PRESET default - ) - target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(point qjs) - elseif(APPLE) - target_link_options(point PRIVATE -undefined dynamic_lookup) - endif() - - add_executable(test_fib - examples/fib.c - gen/test_fib.c - ) - add_qjs_libc_if_needed(test_fib) - target_include_directories(test_fib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_definitions(test_fib PRIVATE ${qjs_defines}) - target_link_libraries(test_fib qjs) -endif() - -# Install target -# - -if(NOT IOS) - file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION) - string(REGEX MATCH "QJS_VERSION_MAJOR ([0-9]*)" _ "${quickjs_h}") - set(QJS_VERSION_MAJOR ${CMAKE_MATCH_1}) - string(REGEX MATCH "QJS_VERSION_MINOR ([0-9]*)" _ "${quickjs_h}") - set(QJS_VERSION_MINOR ${CMAKE_MATCH_1}) - string(REGEX MATCH "QJS_VERSION_PATCH ([0-9]*)" _ "${quickjs_h}") - set(QJS_VERSION_PATCH ${CMAKE_MATCH_1}) - set_target_properties(qjs PROPERTIES - VERSION ${QJS_VERSION_MAJOR}.${QJS_VERSION_MINOR}.${QJS_VERSION_PATCH} - SOVERSION ${QJS_VERSION_MAJOR} - ) - install(FILES quickjs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - if(QJS_BUILD_LIBC) - install(FILES quickjs-libc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - endif() - install(TARGETS qjs_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - install(TARGETS qjsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - install(TARGETS qjs EXPORT qjsConfig - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(EXPORT qjsConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/quickjs) - install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) - install(DIRECTORY examples DESTINATION ${CMAKE_INSTALL_DOCDIR}) -endif() diff --git a/quickjs-ng/Makefile b/quickjs-ng/Makefile deleted file mode 100644 index 596ef05..0000000 --- a/quickjs-ng/Makefile +++ /dev/null @@ -1,147 +0,0 @@ -# -# QuickJS Javascript Engine -# -# Copyright (c) 2017-2024 Fabrice Bellard -# Copyright (c) 2017-2024 Charlie Gordon -# Copyright (c) 2023-2025 Ben Noordhuis -# Copyright (c) 2023-2025 Saúl Ibarra Corretgé -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -BUILD_DIR=build -BUILD_TYPE?=Release -INSTALL_PREFIX?=/usr/local - -QJS=$(BUILD_DIR)/qjs -QJSC=$(BUILD_DIR)/qjsc -RUN262=$(BUILD_DIR)/run-test262 - -JOBS?=$(shell getconf _NPROCESSORS_ONLN) -ifeq ($(JOBS),) -JOBS := $(shell sysctl -n hw.ncpu) -endif -ifeq ($(JOBS),) -JOBS := $(shell nproc) -endif -ifeq ($(JOBS),) -JOBS := 4 -endif - -all: $(QJS) - -amalgam: TEMP := $(shell mktemp -d) -amalgam: $(QJS) - $(QJS) amalgam.js $(TEMP)/quickjs-amalgam.c - cp quickjs.h quickjs-libc.h $(TEMP) - cd $(TEMP) && zip -9 quickjs-amalgam.zip quickjs-amalgam.c quickjs.h quickjs-libc.h - cp $(TEMP)/quickjs-amalgam.zip $(BUILD_DIR) - cd $(TEMP) && $(RM) quickjs-amalgam.zip quickjs-amalgam.c quickjs.h quickjs-libc.h - $(RM) -d $(TEMP) - -fuzz: - clang -g -O1 -fsanitize=address,undefined,fuzzer -o fuzz fuzz.c - ./fuzz - -$(BUILD_DIR): - cmake -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX) - -$(QJS): $(BUILD_DIR) - cmake --build $(BUILD_DIR) -j $(JOBS) - -$(QJSC): $(BUILD_DIR) - cmake --build $(BUILD_DIR) --target qjsc -j $(JOBS) - -install: $(QJS) $(QJSC) - cmake --build $(BUILD_DIR) --target install - -clean: - cmake --build $(BUILD_DIR) --target clean - -codegen: $(QJSC) - $(QJSC) -ss -o gen/repl.c -m repl.js - $(QJSC) -ss -o gen/standalone.c -m standalone.js - $(QJSC) -e -o gen/function_source.c tests/function_source.js - $(QJSC) -e -o gen/hello.c examples/hello.js - $(QJSC) -e -o gen/hello_module.c -m examples/hello_module.js - $(QJSC) -e -o gen/test_fib.c -M examples/fib.so,fib -m examples/test_fib.js - $(QJSC) -C -ss -o builtin-array-fromasync.h builtin-array-fromasync.js - -debug: - BUILD_TYPE=Debug $(MAKE) - -distclean: - @rm -rf $(BUILD_DIR) - -stats: $(QJS) - $(QJS) -qd - -jscheck: CFLAGS=-I. -D_GNU_SOURCE -DJS_CHECK_JSVALUE -Wall -Werror -fsyntax-only -c -o /dev/null -jscheck: - $(CC) $(CFLAGS) api-test.c - $(CC) $(CFLAGS) ctest.c - $(CC) $(CFLAGS) fuzz.c - $(CC) $(CFLAGS) gen/function_source.c - $(CC) $(CFLAGS) gen/hello.c - $(CC) $(CFLAGS) gen/hello_module.c - $(CC) $(CFLAGS) gen/repl.c - $(CC) $(CFLAGS) gen/standalone.c - $(CC) $(CFLAGS) gen/test_fib.c - $(CC) $(CFLAGS) qjs.c - $(CC) $(CFLAGS) qjsc.c - $(CC) $(CFLAGS) quickjs-libc.c - $(CC) $(CFLAGS) quickjs.c - $(CC) $(CFLAGS) run-test262.c - -# effectively .PHONY because it doesn't generate output -ctest: CFLAGS=-std=c11 -fsyntax-only -Wall -Wextra -Werror -pedantic -ctest: ctest.c quickjs.h - $(CC) $(CFLAGS) -DJS_NAN_BOXING=0 $< - $(CC) $(CFLAGS) -DJS_NAN_BOXING=1 $< - -# effectively .PHONY because it doesn't generate output -cxxtest: CXXFLAGS=-std=c++11 -fsyntax-only -Wall -Wextra -Werror -pedantic -cxxtest: cxxtest.cc quickjs.h - $(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=0 $< - $(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=1 $< - -test: $(QJS) - $(RUN262) -c tests.conf - -test262: $(QJS) - $(RUN262) -m -c test262.conf -a - -test262-fast: $(QJS) - $(RUN262) -m -c test262.conf -c test262-fast.conf -a - -test262-update: $(QJS) - $(RUN262) -u -c test262.conf -a -t 1 - -test262-check: $(QJS) - $(RUN262) -m -c test262.conf -E -a - -microbench: $(QJS) - $(QJS) tests/microbench.js - -unicode_gen: $(BUILD_DIR) - cmake --build $(BUILD_DIR) --target unicode_gen - -libunicode-table.h: unicode_gen - $(BUILD_DIR)/unicode_gen unicode $@ - -.PHONY: all amalgam ctest cxxtest debug fuzz jscheck install clean codegen distclean stats test test262 test262-update test262-check microbench unicode_gen $(QJS) $(QJSC) diff --git a/quickjs-ng/README.md b/quickjs-ng/README.md deleted file mode 100644 index e4b0e34..0000000 --- a/quickjs-ng/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# ⚡️ QuickJS - A mighty JavaScript engine - -## Overview - -QuickJS is a small and embeddable JavaScript engine. It aims to support the latest -[ECMAScript] specification. - -This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development. - -## Getting started - -Head over to the [project website] for instructions on how to get started and more -documentation. - -## Authors - -[@bnoordhuis], [@saghul], and many more [contributors]. - -[ECMAScript]: https://tc39.es/ecma262/ -[original QuickJS project]: https://bellard.org/quickjs -[@bnoordhuis]: https://github.com/bnoordhuis -[@saghul]: https://github.com/saghul -[contributors]: https://github.com/quickjs-ng/quickjs/graphs/contributors -[project website]: https://quickjs-ng.github.io/quickjs/ diff --git a/quickjs-ng/amalgam.js b/quickjs-ng/amalgam.js deleted file mode 100644 index 028d779..0000000 --- a/quickjs-ng/amalgam.js +++ /dev/null @@ -1,49 +0,0 @@ -import {loadFile, writeFile} from "qjs:std" - -const cutils_c = loadFile("cutils.c") -const cutils_h = loadFile("cutils.h") -const dtoa_c = loadFile("dtoa.c") -const dtoa_h = loadFile("dtoa.h") -const libregexp_c = loadFile("libregexp.c") -const libregexp_h = loadFile("libregexp.h") -const libregexp_opcode_h = loadFile("libregexp-opcode.h") -const libunicode_c = loadFile("libunicode.c") -const libunicode_h = loadFile("libunicode.h") -const libunicode_table_h = loadFile("libunicode-table.h") -const list_h = loadFile("list.h") -const quickjs_atom_h = loadFile("quickjs-atom.h") -const quickjs_c = loadFile("quickjs.c") -const quickjs_c_atomics_h = loadFile("quickjs-c-atomics.h") -const quickjs_h = loadFile("quickjs.h") -const quickjs_libc_c = loadFile("quickjs-libc.c") -const quickjs_libc_h = loadFile("quickjs-libc.h") -const quickjs_opcode_h = loadFile("quickjs-opcode.h") -const gen_builtin_array_fromasync_h = loadFile("builtin-array-fromasync.h") - -let source = "#if defined(QJS_BUILD_LIBC) && defined(__linux__) && !defined(_GNU_SOURCE)\n" - + "#define _GNU_SOURCE\n" - + "#endif\n" - + quickjs_c_atomics_h - + cutils_h - + dtoa_h - + list_h - + libunicode_h // exports lre_is_id_start, used by libregexp.h - + libregexp_h - + libunicode_table_h - + quickjs_h - + quickjs_c - + cutils_c - + dtoa_c - + libregexp_c - + libunicode_c - + "#ifdef QJS_BUILD_LIBC\n" - + quickjs_libc_h - + quickjs_libc_c - + "#endif // QJS_BUILD_LIBC\n" -source = source.replace(/#include "quickjs-atom.h"/g, quickjs_atom_h) -source = source.replace(/#include "quickjs-opcode.h"/g, quickjs_opcode_h) -source = source.replace(/#include "libregexp-opcode.h"/g, libregexp_opcode_h) -source = source.replace(/#include "builtin-array-fromasync.h"/g, - gen_builtin_array_fromasync_h) -source = source.replace(/#include "[^"]+"/g, "") -writeFile(execArgv[2] ?? "quickjs-amalgam.c", source) diff --git a/quickjs-ng/api-test.c b/quickjs-ng/api-test.c deleted file mode 100644 index 950b415..0000000 --- a/quickjs-ng/api-test.c +++ /dev/null @@ -1,562 +0,0 @@ -#ifdef NDEBUG -#undef NDEBUG -#endif -#include -#include -#include -#include "quickjs.h" -#include "cutils.h" - -#define MAX_TIME 10 - -static int timeout_interrupt_handler(JSRuntime *rt, void *opaque) -{ - int *time = (int *)opaque; - if (*time <= MAX_TIME) - *time += 1; - return *time > MAX_TIME; -} - -static void sync_call(void) -{ - static const char code[] = -"(function() { \ - try { \ - while (true) {} \ - } catch (e) {} \ -})();"; - - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - int time = 0; - JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time); - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL); - assert(time > MAX_TIME); - assert(JS_IsException(ret)); - JS_FreeValue(ctx, ret); - assert(JS_HasException(ctx)); - JSValue e = JS_GetException(ctx); - assert(JS_IsUncatchableError(ctx, e)); - JS_FreeValue(ctx, e); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void async_call(void) -{ - static const char code[] = -"(async function() { \ - const loop = async () => { \ - await Promise.resolve(); \ - while (true) {} \ - }; \ - await loop().catch(() => {}); \ -})();"; - - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - int time = 0; - JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time); - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret)); - JS_FreeValue(ctx, ret); - assert(JS_IsJobPending(rt)); - int r = 0; - while (JS_IsJobPending(rt)) { - r = JS_ExecutePendingJob(rt, &ctx); - } - assert(time > MAX_TIME); - assert(r == -1); - assert(JS_HasException(ctx)); - JSValue e = JS_GetException(ctx); - assert(JS_IsUncatchableError(ctx, e)); - JS_FreeValue(ctx, e); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static JSValue save_value(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - assert(argc == 1); - JSValue *p = (JSValue *)JS_GetContextOpaque(ctx); - *p = JS_DupValue(ctx, argv[0]); - return JS_UNDEFINED; -} - -static void async_call_stack_overflow(void) -{ - static const char code[] = -"(async function() { \ - const f = () => f(); \ - try { \ - await Promise.resolve(); \ - f(); \ - } catch (e) { \ - save_value(e); \ - } \ -})();"; - - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - JSValue value = JS_UNDEFINED; - JS_SetContextOpaque(ctx, &value); - JSValue global = JS_GetGlobalObject(ctx); - JS_SetPropertyStr(ctx, global, "save_value", JS_NewCFunction(ctx, save_value, "save_value", 1)); - JS_FreeValue(ctx, global); - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret)); - JS_FreeValue(ctx, ret); - assert(JS_IsJobPending(rt)); - int r = 0; - while (JS_IsJobPending(rt)) { - r = JS_ExecutePendingJob(rt, &ctx); - } - assert(r == 1); - assert(!JS_HasException(ctx)); - assert(JS_IsError(ctx, value)); // stack overflow should be caught - JS_FreeValue(ctx, value); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -// https://github.com/quickjs-ng/quickjs/issues/914 -static void raw_context_global_var(void) -{ - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContextRaw(rt); - JS_AddIntrinsicEval(ctx); - { - static const char code[] = "globalThis"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL); - assert(JS_IsException(ret)); - JS_FreeValue(ctx, ret); - } - { - static const char code[] = "var x = 42"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL); - assert(JS_IsUndefined(ret)); - JS_FreeValue(ctx, ret); - } - { - static const char code[] = "function f() {}"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL); - assert(JS_IsUndefined(ret)); - JS_FreeValue(ctx, ret); - } - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void is_array(void) -{ - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - { - static const char code[] = "[]"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret)); - assert(JS_IsArray(ret)); - JS_FreeValue(ctx, ret); - } - { - static const char code[] = "new Proxy([], {})"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret)); - assert(!JS_IsArray(ret)); - assert(JS_IsProxy(ret)); - JSValue handler = JS_GetProxyHandler(ctx, ret); - JSValue target = JS_GetProxyTarget(ctx, ret); - assert(!JS_IsException(handler)); - assert(!JS_IsException(target)); - assert(!JS_IsProxy(handler)); - assert(!JS_IsProxy(target)); - assert(JS_IsObject(handler)); - assert(JS_IsArray(target)); - JS_FreeValue(ctx, handler); - JS_FreeValue(ctx, target); - JS_FreeValue(ctx, ret); - } - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static int loader_calls; - -static JSModuleDef *loader(JSContext *ctx, const char *name, void *opaque) -{ - loader_calls++; - assert(!strcmp(name, "b")); - static const char code[] = "export function f(x){}"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "b", - JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY); - assert(!JS_IsException(ret)); - JSModuleDef *m = JS_VALUE_GET_PTR(ret); - assert(m); - JS_FreeValue(ctx, ret); - return m; -} - -static void module_serde(void) -{ - JSRuntime *rt = JS_NewRuntime(); - //JS_SetDumpFlags(rt, JS_DUMP_MODULE_RESOLVE); - JS_SetModuleLoaderFunc(rt, NULL, loader, NULL); - JSContext *ctx = JS_NewContext(rt); - static const char code[] = "import {f} from 'b'; f()"; - assert(loader_calls == 0); - JSValue mod = JS_Eval(ctx, code, strlen(code), "a", - JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY); - assert(loader_calls == 1); - assert(!JS_IsException(mod)); - assert(JS_IsModule(mod)); - size_t len = 0; - uint8_t *buf = JS_WriteObject(ctx, &len, mod, - JS_WRITE_OBJ_BYTECODE|JS_WRITE_OBJ_REFERENCE); - assert(buf); - assert(len > 0); - JS_FreeValue(ctx, mod); - assert(loader_calls == 1); - mod = JS_ReadObject(ctx, buf, len, JS_READ_OBJ_BYTECODE); - js_free(ctx, buf); - assert(loader_calls == 1); // 'b' is returned from cache - assert(!JS_IsException(mod)); - JSValue ret = JS_EvalFunction(ctx, mod); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - JSValue result = JS_PromiseResult(ctx, ret); - assert(!JS_IsException(result)); - assert(JS_IsUndefined(result)); - JS_FreeValue(ctx, result); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, mod); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void two_byte_string(void) -{ - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - { - JSValue v = JS_NewTwoByteString(ctx, NULL, 0); - assert(!JS_IsException(v)); - const char *s = JS_ToCString(ctx, v); - assert(s); - assert(!strcmp(s, "")); - JS_FreeCString(ctx, s); - JS_FreeValue(ctx, v); - } - { - JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){'o','k'}, 2); - assert(!JS_IsException(v)); - const char *s = JS_ToCString(ctx, v); - assert(s); - assert(!strcmp(s, "ok")); - JS_FreeCString(ctx, s); - JS_FreeValue(ctx, v); - } - { - JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){0xD800}, 1); - assert(!JS_IsException(v)); - const char *s = JS_ToCString(ctx, v); - assert(s); - // questionable but surrogates don't map to UTF-8 without WTF-8 - assert(!strcmp(s, "\xED\xA0\x80")); - JS_FreeCString(ctx, s); - JS_FreeValue(ctx, v); - } - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void weak_map_gc_check(void) -{ - static const char init_code[] = -"const map = new WeakMap(); \ -function addItem() { \ - const k = { \ - text: 'a', \ - }; \ - map.set(k, {k}); \ -}"; - static const char test_code[] = "addItem()"; - - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - - JSValue ret = JS_Eval(ctx, init_code, strlen(init_code), "", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret)); - - JSValue ret_test = JS_Eval(ctx, test_code, strlen(test_code), "", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret_test)); - JS_RunGC(rt); - JSMemoryUsage memory_usage; - JS_ComputeMemoryUsage(rt, &memory_usage); - - for (int i = 0; i < 3; i++) { - JSValue ret_test2 = JS_Eval(ctx, test_code, strlen(test_code), "", JS_EVAL_TYPE_GLOBAL); - assert(!JS_IsException(ret_test2)); - JS_RunGC(rt); - JSMemoryUsage memory_usage2; - JS_ComputeMemoryUsage(rt, &memory_usage2); - - assert(memory_usage.memory_used_count == memory_usage2.memory_used_count); - assert(memory_usage.memory_used_size == memory_usage2.memory_used_size); - JS_FreeValue(ctx, ret_test2); - } - - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, ret_test); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -struct { - int hook_type_call_count[4]; -} promise_hook_state; - -static void promise_hook_cb(JSContext *ctx, JSPromiseHookType type, - JSValueConst promise, JSValueConst parent_promise, - void *opaque) -{ - assert(type == JS_PROMISE_HOOK_INIT || - type == JS_PROMISE_HOOK_BEFORE || - type == JS_PROMISE_HOOK_AFTER || - type == JS_PROMISE_HOOK_RESOLVE); - promise_hook_state.hook_type_call_count[type]++; - assert(opaque == (void *)&promise_hook_state); - if (!JS_IsUndefined(parent_promise)) { - JSValue global_object = JS_GetGlobalObject(ctx); - JS_SetPropertyStr(ctx, global_object, "actual", - JS_DupValue(ctx, parent_promise)); - JS_FreeValue(ctx, global_object); - } -} - -static void promise_hook(void) -{ - int *cc = promise_hook_state.hook_type_call_count; - JSContext *unused; - JSRuntime *rt = JS_NewRuntime(); - //JS_SetDumpFlags(rt, JS_DUMP_PROMISE); - JS_SetPromiseHook(rt, promise_hook_cb, &promise_hook_state); - JSContext *ctx = JS_NewContext(rt); - JSValue global_object = JS_GetGlobalObject(ctx); - { - // empty module; creates an outer and inner module promise; - // JS_Eval returns the outer promise - JSValue ret = JS_Eval(ctx, "", 0, "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); - JS_FreeValue(ctx, ret); - assert(2 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(!JS_IsJobPending(rt)); - } - memset(&promise_hook_state, 0, sizeof(promise_hook_state)); - { - // module with unresolved promise; the outer and inner module promises - // are resolved but not the user's promise - static const char code[] = "new Promise(() => {})"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise - JS_FreeValue(ctx, ret); - assert(3 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); // outer and inner module promise - assert(!JS_IsJobPending(rt)); - } - memset(&promise_hook_state, 0, sizeof(promise_hook_state)); - { - // module with resolved promise - static const char code[] = "new Promise((resolve,reject) => resolve())"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise - JS_FreeValue(ctx, ret); - assert(3 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(!JS_IsJobPending(rt)); - } - memset(&promise_hook_state, 0, sizeof(promise_hook_state)); - { - // module with rejected promise - static const char code[] = "new Promise((resolve,reject) => reject())"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise - JS_FreeValue(ctx, ret); - assert(3 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(!JS_IsJobPending(rt)); - } - memset(&promise_hook_state, 0, sizeof(promise_hook_state)); - { - // module with promise chain - static const char code[] = - "globalThis.count = 0;" - "globalThis.actual = undefined;" // set by promise_hook_cb - "globalThis.expected = new Promise(resolve => resolve());" - "expected.then(_ => count++)"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise - JS_FreeValue(ctx, ret); - assert(4 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]); - JSValue v = JS_GetPropertyStr(ctx, global_object, "count"); - assert(!JS_IsException(v)); - int32_t count; - assert(0 == JS_ToInt32(ctx, &count, v)); - assert(0 == count); - JS_FreeValue(ctx, v); - assert(JS_IsJobPending(rt)); - assert(1 == JS_ExecutePendingJob(rt, &unused)); - assert(!JS_HasException(ctx)); - assert(4 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(4 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(!JS_IsJobPending(rt)); - v = JS_GetPropertyStr(ctx, global_object, "count"); - assert(!JS_IsException(v)); - assert(0 == JS_ToInt32(ctx, &count, v)); - assert(1 == count); - JS_FreeValue(ctx, v); - JSValue actual = JS_GetPropertyStr(ctx, global_object, "actual"); - JSValue expected = JS_GetPropertyStr(ctx, global_object, "expected"); - assert(!JS_IsException(actual)); - assert(!JS_IsException(expected)); - assert(JS_IsSameValue(ctx, actual, expected)); - JS_FreeValue(ctx, actual); - JS_FreeValue(ctx, expected); - } - memset(&promise_hook_state, 0, sizeof(promise_hook_state)); - { - // module with thenable; fires before and after hooks - static const char code[] = - "new Promise(resolve => resolve({then(resolve){ resolve() }}))"; - JSValue ret = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); - assert(!JS_IsException(ret)); - assert(JS_IsPromise(ret)); - assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise - JS_FreeValue(ctx, ret); - assert(3 == cc[JS_PROMISE_HOOK_INIT]); - assert(0 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(0 == cc[JS_PROMISE_HOOK_AFTER]); - assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(JS_IsJobPending(rt)); - assert(1 == JS_ExecutePendingJob(rt, &unused)); - assert(!JS_HasException(ctx)); - assert(3 == cc[JS_PROMISE_HOOK_INIT]); - assert(1 == cc[JS_PROMISE_HOOK_BEFORE]); - assert(1 == cc[JS_PROMISE_HOOK_AFTER]); - assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]); - assert(!JS_IsJobPending(rt)); - } - JS_FreeValue(ctx, global_object); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void dump_memory_usage(void) -{ - JSMemoryUsage stats; - - JSRuntime *rt = NULL; - JSContext *ctx = NULL; - - rt = JS_NewRuntime(); - ctx = JS_NewContext(rt); - - //JS_SetDumpFlags(rt, JS_DUMP_PROMISE); - - static const char code[] = - "globalThis.count = 0;" - "globalThis.actual = undefined;" // set by promise_hook_cb - "globalThis.expected = new Promise(resolve => resolve());" - "expected.then(_ => count++)"; - - JSValue evalVal = JS_Eval(ctx, code, strlen(code), "", 0); - JS_FreeValue(ctx, evalVal); - - FILE *temp = tmpfile(); - assert(temp != NULL); - JS_ComputeMemoryUsage(rt, &stats); - JS_DumpMemoryUsage(temp, &stats, rt); - // JS_DumpMemoryUsage(stdout, &stats, rt); - fclose(temp); - - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -static void new_errors(void) -{ - typedef struct { - const char name[16]; - JSValue (*func)(JSContext *, const char *, ...); - } Entry; - static const Entry entries[] = { - {"Error", JS_NewPlainError}, - {"InternalError", JS_NewInternalError}, - {"RangeError", JS_NewRangeError}, - {"ReferenceError", JS_NewReferenceError}, - {"SyntaxError", JS_NewSyntaxError}, - {"TypeError", JS_NewTypeError}, - }; - const Entry *e; - - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - for (e = entries; e < endof(entries); e++) { - JSValue obj = (*e->func)(ctx, "the %s", "needle"); - assert(!JS_IsException(obj)); - assert(JS_IsObject(obj)); - assert(JS_IsError(ctx, obj)); - const char *haystack = JS_ToCString(ctx, obj); - char needle[256]; - snprintf(needle, sizeof(needle), "%s: the needle", e->name); - assert(strstr(haystack, needle)); - JS_FreeCString(ctx, haystack); - JSValue stack = JS_GetPropertyStr(ctx, obj, "stack"); - assert(!JS_IsException(stack)); - assert(JS_IsString(stack)); - JS_FreeValue(ctx, stack); - JS_FreeValue(ctx, obj); - } - JS_FreeContext(ctx); - JS_FreeRuntime(rt); -} - -int main(void) -{ - sync_call(); - async_call(); - async_call_stack_overflow(); - raw_context_global_var(); - is_array(); - module_serde(); - two_byte_string(); - weak_map_gc_check(); - promise_hook(); - dump_memory_usage(); - new_errors(); - return 0; -} diff --git a/quickjs-ng/builtin-array-fromasync.h b/quickjs-ng/builtin-array-fromasync.h deleted file mode 100644 index 19f1f07..0000000 --- a/quickjs-ng/builtin-array-fromasync.h +++ /dev/null @@ -1,113 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include - -const uint32_t qjsc_builtin_array_fromasync_size = 826; - -const uint8_t qjsc_builtin_array_fromasync[826] = { - 0x15, 0x0d, 0x01, 0x1a, 0x61, 0x73, 0x79, 0x6e, - 0x63, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x01, 0x10, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x01, 0x12, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x4c, 0x69, 0x6b, 0x65, 0x01, 0x0a, - 0x6d, 0x61, 0x70, 0x46, 0x6e, 0x01, 0x0e, 0x74, - 0x68, 0x69, 0x73, 0x41, 0x72, 0x67, 0x01, 0x0c, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x02, - 0x69, 0x01, 0x1a, 0x69, 0x73, 0x43, 0x6f, 0x6e, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, - 0x01, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x01, 0x0c, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x01, 0x08, - 0x69, 0x74, 0x65, 0x72, 0x01, 0x1c, 0x6e, 0x6f, - 0x74, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x08, 0x63, 0x61, - 0x6c, 0x6c, 0x0c, 0x00, 0x02, 0x00, 0xa2, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x04, 0x01, - 0xa4, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x43, 0x02, - 0x01, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x01, - 0x03, 0x05, 0xaa, 0x02, 0x00, 0x01, 0x40, 0xa0, - 0x03, 0x00, 0x01, 0x40, 0xc6, 0x03, 0x00, 0x01, - 0x40, 0xcc, 0x01, 0x00, 0x01, 0x40, 0xc8, 0x03, - 0x00, 0x01, 0x40, 0x0c, 0x60, 0x02, 0x01, 0xf8, - 0x01, 0x03, 0x0e, 0x01, 0x06, 0x05, 0x00, 0x86, - 0x04, 0x11, 0xca, 0x03, 0x00, 0x01, 0x00, 0xcc, - 0x03, 0x00, 0x01, 0x00, 0xce, 0x03, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x01, 0xff, 0xff, 0xff, 0xff, - 0x0f, 0x20, 0xcc, 0x03, 0x01, 0x01, 0x20, 0xce, - 0x03, 0x01, 0x02, 0x20, 0xd0, 0x03, 0x02, 0x00, - 0x20, 0xd2, 0x03, 0x02, 0x04, 0x20, 0xd4, 0x03, - 0x02, 0x05, 0x20, 0xd6, 0x03, 0x02, 0x06, 0x20, - 0xd8, 0x03, 0x02, 0x07, 0x20, 0x64, 0x06, 0x08, - 0x20, 0x82, 0x01, 0x07, 0x09, 0x20, 0xda, 0x03, - 0x0a, 0x08, 0x30, 0x82, 0x01, 0x0d, 0x0b, 0x20, - 0xd4, 0x01, 0x0d, 0x0c, 0x20, 0x10, 0x00, 0x01, - 0x00, 0xa0, 0x03, 0x01, 0x03, 0xc6, 0x03, 0x02, - 0x03, 0xc8, 0x03, 0x04, 0x03, 0xaa, 0x02, 0x00, - 0x03, 0xcc, 0x01, 0x03, 0x03, 0x08, 0xc4, 0x0d, - 0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62, 0x00, - 0x00, 0xd3, 0xcb, 0xd4, 0x11, 0xf4, 0xec, 0x08, - 0x0e, 0x39, 0x46, 0x00, 0x00, 0x00, 0xdc, 0xcc, - 0xd5, 0x11, 0xf4, 0xec, 0x08, 0x0e, 0x39, 0x46, - 0x00, 0x00, 0x00, 0xdd, 0xcd, 0x62, 0x07, 0x00, - 0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62, 0x04, - 0x00, 0x62, 0x03, 0x00, 0xd4, 0x39, 0x46, 0x00, - 0x00, 0x00, 0xb0, 0xec, 0x16, 0xd4, 0x98, 0x04, - 0x1b, 0x00, 0x00, 0x00, 0xb0, 0xec, 0x0c, 0xdf, - 0x11, 0x04, 0xee, 0x00, 0x00, 0x00, 0x21, 0x01, - 0x00, 0x30, 0x06, 0xce, 0xb6, 0xc4, 0x04, 0xc3, - 0x0d, 0xf7, 0xc4, 0x05, 0x09, 0xc4, 0x06, 0xd3, - 0xe0, 0x48, 0xc4, 0x07, 0x63, 0x07, 0x00, 0x07, - 0xad, 0xec, 0x0f, 0x0a, 0x11, 0x64, 0x06, 0x00, - 0x0e, 0xd3, 0xe1, 0x48, 0x11, 0x64, 0x07, 0x00, - 0x0e, 0x63, 0x07, 0x00, 0x07, 0xad, 0x6a, 0xa6, - 0x00, 0x00, 0x00, 0x62, 0x08, 0x00, 0x06, 0x11, - 0xf4, 0xed, 0x0c, 0x71, 0x43, 0x32, 0x00, 0x00, - 0x00, 0xc4, 0x08, 0x0e, 0xee, 0x05, 0x0e, 0xd3, - 0xee, 0xf2, 0x63, 0x08, 0x00, 0x8e, 0x11, 0xed, - 0x03, 0x0e, 0xb6, 0x11, 0x64, 0x08, 0x00, 0x0e, - 0x63, 0x05, 0x00, 0xec, 0x0c, 0xc3, 0x0d, 0x11, - 0x63, 0x08, 0x00, 0x21, 0x01, 0x00, 0xee, 0x06, - 0xe2, 0x63, 0x08, 0x00, 0xf1, 0x11, 0x64, 0x03, - 0x00, 0x0e, 0x63, 0x04, 0x00, 0x63, 0x08, 0x00, - 0xa7, 0x6a, 0x2a, 0x01, 0x00, 0x00, 0x62, 0x09, - 0x00, 0xd3, 0x63, 0x04, 0x00, 0x48, 0xc4, 0x09, - 0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x09, 0x00, - 0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0xd4, 0xec, - 0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5, - 0x63, 0x09, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03, - 0x00, 0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0x5f, - 0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00, - 0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x09, 0x00, - 0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e, - 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00, - 0x00, 0xf3, 0x0e, 0xee, 0x9e, 0x62, 0x0a, 0x00, - 0x63, 0x07, 0x00, 0x43, 0xef, 0x00, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0xc4, 0x0a, 0x63, 0x05, - 0x00, 0xec, 0x09, 0xc3, 0x0d, 0x11, 0x21, 0x00, - 0x00, 0xee, 0x03, 0xe2, 0xf0, 0x11, 0x64, 0x03, - 0x00, 0x0e, 0x6d, 0x8c, 0x00, 0x00, 0x00, 0x62, - 0x0c, 0x00, 0x62, 0x0b, 0x00, 0x06, 0x11, 0xf4, - 0xed, 0x13, 0x71, 0x43, 0x41, 0x00, 0x00, 0x00, - 0xc4, 0x0b, 0x43, 0x6a, 0x00, 0x00, 0x00, 0xc4, - 0x0c, 0x0e, 0xee, 0x10, 0x0e, 0x63, 0x0a, 0x00, - 0x43, 0x6b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x8c, 0xee, 0xe0, 0x63, 0x0c, 0x00, 0xed, 0x4e, - 0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x0b, 0x00, - 0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0xd4, 0xec, - 0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5, - 0x63, 0x0b, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03, - 0x00, 0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0x5f, - 0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00, - 0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x0b, 0x00, - 0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e, - 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00, - 0x00, 0xf3, 0x0e, 0xee, 0x83, 0x0e, 0x06, 0x6e, - 0x0d, 0x00, 0x00, 0x00, 0x0e, 0xee, 0x1e, 0x6e, - 0x05, 0x00, 0x00, 0x00, 0x30, 0x63, 0x0a, 0x00, - 0x42, 0x06, 0x00, 0x00, 0x00, 0xec, 0x0d, 0x63, - 0x0a, 0x00, 0x43, 0x06, 0x00, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x0e, 0x6f, 0x63, 0x03, 0x00, 0x63, - 0x04, 0x00, 0x44, 0x32, 0x00, 0x00, 0x00, 0x63, - 0x03, 0x00, 0x2f, 0xc1, 0x00, 0x28, 0xc1, 0x00, - 0xcf, 0x28, -}; - diff --git a/quickjs-ng/builtin-array-fromasync.js b/quickjs-ng/builtin-array-fromasync.js deleted file mode 100644 index a07e40e..0000000 --- a/quickjs-ng/builtin-array-fromasync.js +++ /dev/null @@ -1,36 +0,0 @@ -;(function(Array, TypeError, asyncIterator, defineProperty, iterator) { - "use strict" // result.length=i should throw if .length is not writable - return async function fromAsync(arrayLike, mapFn=undefined, thisArg=undefined) { - if (mapFn !== undefined && typeof mapFn !== "function") throw new TypeError("not a function") - let result, i = 0, isConstructor = typeof this === "function" - let sync = false, method = arrayLike[asyncIterator] - if (method == null) sync = true, method = arrayLike[iterator] - if (method == null) { - let {length} = arrayLike - length = +length || 0 - result = isConstructor ? new this(length) : Array(length) - while (i < length) { - let value = arrayLike[i] - if (sync) value = await value - if (mapFn) value = await mapFn.call(thisArg, value, i) - defineProperty(result, i++, {value, configurable: true, writable: true}) - } - } else { - const iter = method.call(arrayLike) - result = isConstructor ? new this() : Array() - try { - for (;;) { - let {value, done} = await iter.next() - if (done) break - if (sync) value = await value - if (mapFn) value = await mapFn.call(thisArg, value, i) - defineProperty(result, i++, {value, configurable: true, writable: true}) - } - } finally { - if (iter.return) iter.return() - } - } - result.length = i - return result - } -}) diff --git a/quickjs-ng/ctest.c b/quickjs-ng/ctest.c deleted file mode 100644 index eeb03e8..0000000 --- a/quickjs-ng/ctest.c +++ /dev/null @@ -1,17 +0,0 @@ -// note: file is not actually compiled, only checked for C syntax errors -#include "quickjs.h" - -int main(void) -{ - JSRuntime *rt = JS_NewRuntime(); - JSContext *ctx = JS_NewContext(rt); - JS_FreeValue(ctx, JS_NAN); - JS_FreeValue(ctx, JS_UNDEFINED); - JS_FreeValue(ctx, JS_NewFloat64(ctx, 42)); - // not a legal way of using JS_MKPTR but this is here - // to have the compiler syntax-check its definition - JS_FreeValue(ctx, JS_MKPTR(JS_TAG_UNINITIALIZED, 0)); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return 0; -} diff --git a/quickjs-ng/cutils.c b/quickjs-ng/cutils.c deleted file mode 100644 index 7d36ddf..0000000 --- a/quickjs-ng/cutils.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* - * C utilities - * - * Copyright (c) 2017 Fabrice Bellard - * Copyright (c) 2018 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#if !defined(_MSC_VER) -#include -#endif -#if defined(_WIN32) -#include -#include // _beginthread -#endif -#if defined(__APPLE__) -#include -#endif - -#include "cutils.h" - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif - -void js__pstrcpy(char *buf, int buf_size, const char *str) -{ - int c; - char *q = buf; - - if (buf_size <= 0) - return; - - for(;;) { - c = *str++; - if (c == 0 || q >= buf + buf_size - 1) - break; - *q++ = c; - } - *q = '\0'; -} - -/* strcat and truncate. */ -char *js__pstrcat(char *buf, int buf_size, const char *s) -{ - int len; - len = strlen(buf); - if (len < buf_size) - js__pstrcpy(buf + len, buf_size - len, s); - return buf; -} - -int js__strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} - -int js__has_suffix(const char *str, const char *suffix) -{ - size_t len = strlen(str); - size_t slen = strlen(suffix); - return (len >= slen && !memcmp(str + len - slen, suffix, slen)); -} - -/* Dynamic buffer package */ - -static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) -{ - if (unlikely(size == 0)) { - free(ptr); - return NULL; - } - return realloc(ptr, size); -} - -void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) -{ - memset(s, 0, sizeof(*s)); - if (!realloc_func) - realloc_func = dbuf_default_realloc; - s->opaque = opaque; - s->realloc_func = realloc_func; -} - -void dbuf_init(DynBuf *s) -{ - dbuf_init2(s, NULL, NULL); -} - -/* return < 0 if error */ -int dbuf_realloc(DynBuf *s, size_t new_size) -{ - size_t size; - uint8_t *new_buf; - if (new_size > s->allocated_size) { - if (s->error) - return -1; - size = s->allocated_size * 3 / 2; - if (size > new_size) - new_size = size; - new_buf = s->realloc_func(s->opaque, s->buf, new_size); - if (!new_buf) { - s->error = true; - return -1; - } - s->buf = new_buf; - s->allocated_size = new_size; - } - return 0; -} - -int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len) -{ - size_t end; - end = offset + len; - if (dbuf_realloc(s, end)) - return -1; - memcpy(s->buf + offset, data, len); - if (end > s->size) - s->size = end; - return 0; -} - -int dbuf_put(DynBuf *s, const void *data, size_t len) -{ - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) - return -1; - } - if (len > 0) { - memcpy(s->buf + s->size, data, len); - s->size += len; - } - return 0; -} - -int dbuf_put_self(DynBuf *s, size_t offset, size_t len) -{ - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) - return -1; - } - memcpy(s->buf + s->size, s->buf + offset, len); - s->size += len; - return 0; -} - -int dbuf_putc(DynBuf *s, uint8_t c) -{ - return dbuf_put(s, &c, 1); -} - -int dbuf_putstr(DynBuf *s, const char *str) -{ - return dbuf_put(s, (const uint8_t *)str, strlen(str)); -} - -int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...) -{ - va_list ap; - char buf[128]; - int len; - - va_start(ap, fmt); - len = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - if (len < (int)sizeof(buf)) { - /* fast case */ - return dbuf_put(s, (uint8_t *)buf, len); - } else { - if (dbuf_realloc(s, s->size + len + 1)) - return -1; - va_start(ap, fmt); - vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, - fmt, ap); - va_end(ap); - s->size += len; - } - return 0; -} - -void dbuf_free(DynBuf *s) -{ - /* we test s->buf as a fail safe to avoid crashing if dbuf_free() - is called twice */ - if (s->buf) { - s->realloc_func(s->opaque, s->buf, 0); - } - memset(s, 0, sizeof(*s)); -} - -/*--- UTF-8 utility functions --*/ - -/* Note: only encode valid codepoints (0x0000..0x10FFFF). - At most UTF8_CHAR_LEN_MAX bytes are output. */ - -/* Compute the number of bytes of the UTF-8 encoding for a codepoint - `c` is a code-point. - Returns the number of bytes. If a codepoint is beyond 0x10FFFF the - return value is 3 as the codepoint would be encoded as 0xFFFD. - */ -size_t utf8_encode_len(uint32_t c) -{ - if (c < 0x80) - return 1; - if (c < 0x800) - return 2; - if (c < 0x10000) - return 3; - if (c < 0x110000) - return 4; - return 3; -} - -/* Encode a codepoint in UTF-8 - `buf` points to an array of at least `UTF8_CHAR_LEN_MAX` bytes - `c` is a code-point. - Returns the number of bytes. If a codepoint is beyond 0x10FFFF the - return value is 3 and the codepoint is encoded as 0xFFFD. - No null byte is stored after the encoded bytes. - Return value is in range 1..4 - */ -size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c) -{ - if (c < 0x80) { - buf[0] = c; - return 1; - } - if (c < 0x800) { - buf[0] = (c >> 6) | 0xC0; - buf[1] = (c & 0x3F) | 0x80; - return 2; - } - if (c < 0x10000) { - buf[0] = (c >> 12) | 0xE0; - buf[1] = ((c >> 6) & 0x3F) | 0x80; - buf[2] = (c & 0x3F) | 0x80; - return 3; - } - if (c < 0x110000) { - buf[0] = (c >> 18) | 0xF0; - buf[1] = ((c >> 12) & 0x3F) | 0x80; - buf[2] = ((c >> 6) & 0x3F) | 0x80; - buf[3] = (c & 0x3F) | 0x80; - return 4; - } - buf[0] = (0xFFFD >> 12) | 0xE0; - buf[1] = ((0xFFFD >> 6) & 0x3F) | 0x80; - buf[2] = (0xFFFD & 0x3F) | 0x80; - return 3; -} - -/* Decode a single code point from a UTF-8 encoded array of bytes - `p` is a valid pointer to an array of bytes - `pp` is a valid pointer to a `const uint8_t *` to store a pointer - to the byte following the current sequence. - Return the code point at `p`, in the range `0..0x10FFFF` - Return 0xFFFD on error. Only a single byte is consumed in this case - The maximum length for a UTF-8 byte sequence is 4 bytes. - This implements the algorithm specified in whatwg.org, except it accepts - UTF-8 encoded surrogates as JavaScript allows them in strings. - The source string is assumed to have at least UTF8_CHAR_LEN_MAX bytes - or be null terminated. - If `p[0]` is '\0', the return value is `0` and the byte is consumed. - cf: https://encoding.spec.whatwg.org/#utf-8-encoder - */ -uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp) -{ - uint32_t c; - uint8_t lower, upper; - - c = *p++; - if (c < 0x80) { - *pp = p; - return c; - } - switch(c) { - case 0xC2: case 0xC3: - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - case 0xD0: case 0xD1: case 0xD2: case 0xD3: - case 0xD4: case 0xD5: case 0xD6: case 0xD7: - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDC: case 0xDD: case 0xDE: case 0xDF: - if (*p >= 0x80 && *p <= 0xBF) { - *pp = p + 1; - return ((c - 0xC0) << 6) + (*p - 0x80); - } - // otherwise encoding error - break; - case 0xE0: - lower = 0xA0; /* reject invalid encoding */ - goto need2; - case 0xE1: case 0xE2: case 0xE3: - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xE8: case 0xE9: case 0xEA: case 0xEB: - case 0xEC: case 0xED: case 0xEE: case 0xEF: - lower = 0x80; - need2: - if (*p >= lower && *p <= 0xBF && p[1] >= 0x80 && p[1] <= 0xBF) { - *pp = p + 2; - return ((c - 0xE0) << 12) + ((*p - 0x80) << 6) + (p[1] - 0x80); - } - // otherwise encoding error - break; - case 0xF0: - lower = 0x90; /* reject invalid encoding */ - upper = 0xBF; - goto need3; - case 0xF4: - lower = 0x80; - upper = 0x8F; /* reject values above 0x10FFFF */ - goto need3; - case 0xF1: case 0xF2: case 0xF3: - lower = 0x80; - upper = 0xBF; - need3: - if (*p >= lower && *p <= upper && p[1] >= 0x80 && p[1] <= 0xBF - && p[2] >= 0x80 && p[2] <= 0xBF) { - *pp = p + 3; - return ((c - 0xF0) << 18) + ((*p - 0x80) << 12) + - ((p[1] - 0x80) << 6) + (p[2] - 0x80); - } - // otherwise encoding error - break; - default: - // invalid lead byte - break; - } - *pp = p; - return 0xFFFD; -} - -uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp) { - switch (max_len) { - case 0: - *pp = p; - return 0xFFFD; - case 1: - if (*p < 0x80) - goto good; - break; - case 2: - if (*p < 0xE0) - goto good; - break; - case 3: - if (*p < 0xF0) - goto good; - break; - default: - good: - return utf8_decode(p, pp); - } - *pp = p + 1; - return 0xFFFD; -} - -/* Scan a UTF-8 encoded buffer for content type - `buf` is a valid pointer to a UTF-8 encoded string - `len` is the number of bytes to scan - `plen` points to a `size_t` variable to receive the number of units - Return value is a mask of bits. - - `UTF8_PLAIN_ASCII`: return value for 7-bit ASCII plain text - - `UTF8_NON_ASCII`: bit for non ASCII code points (8-bit or more) - - `UTF8_HAS_16BIT`: bit for 16-bit code points - - `UTF8_HAS_NON_BMP1`: bit for non-BMP1 code points, needs UTF-16 surrogate pairs - - `UTF8_HAS_ERRORS`: bit for encoding errors - */ -int utf8_scan(const char *buf, size_t buf_len, size_t *plen) -{ - const uint8_t *p, *p_end, *p_next; - size_t i, len; - int kind; - uint8_t cbits; - - kind = UTF8_PLAIN_ASCII; - cbits = 0; - len = buf_len; - // TODO: handle more than 1 byte at a time - for (i = 0; i < buf_len; i++) - cbits |= buf[i]; - if (cbits >= 0x80) { - p = (const uint8_t *)buf; - p_end = p + buf_len; - kind = UTF8_NON_ASCII; - len = 0; - while (p < p_end) { - len++; - if (*p++ >= 0x80) { - /* parse UTF-8 sequence, check for encoding error */ - uint32_t c = utf8_decode_len(p - 1, p_end - (p - 1), &p_next); - if (p_next == p) - kind |= UTF8_HAS_ERRORS; - p = p_next; - if (c > 0xFF) { - kind |= UTF8_HAS_16BIT; - if (c > 0xFFFF) { - len++; - kind |= UTF8_HAS_NON_BMP1; - } - } - } - } - } - *plen = len; - return kind; -} - -/* Decode a string encoded in UTF-8 into an array of bytes - `src` points to the source string. It is assumed to be correctly encoded - and only contains code points below 0x800 - `src_len` is the length of the source string - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len) -{ - const uint8_t *p, *p_end; - size_t i; - - p = (const uint8_t *)src; - p_end = p + src_len; - for (i = 0; p < p_end; i++) { - uint32_t c = *p++; - if (c >= 0xC0) - c = (c << 6) + *p++ - ((0xC0 << 6) + 0x80); - if (i < dest_len) - dest[i] = c; - } - if (i < dest_len) - dest[i] = '\0'; - else if (dest_len > 0) - dest[dest_len - 1] = '\0'; - return i; -} - -/* Decode a string encoded in UTF-8 into an array of 16-bit words - `src` points to the source string. It is assumed to be correctly encoded. - `src_len` is the length of the source string - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length of the destination array. No null terminator is - stored at the end of the array. - */ -size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len) -{ - const uint8_t *p, *p_end; - size_t i; - - p = (const uint8_t *)src; - p_end = p + src_len; - for (i = 0; p < p_end; i++) { - uint32_t c = *p++; - if (c >= 0x80) { - /* parse utf-8 sequence */ - c = utf8_decode_len(p - 1, p_end - (p - 1), &p); - /* encoding errors are converted as 0xFFFD and use a single byte */ - if (c > 0xFFFF) { - if (i < dest_len) - dest[i] = get_hi_surrogate(c); - i++; - c = get_lo_surrogate(c); - } - } - if (i < dest_len) - dest[i] = c; - } - return i; -} - -/* Encode a buffer of 8-bit bytes as a UTF-8 encoded string - `src` points to the source buffer. - `src_len` is the length of the source buffer - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length in bytes of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len) -{ - size_t i, j; - uint32_t c; - - for (i = j = 0; i < src_len; i++) { - c = src[i]; - if (c < 0x80) { - if (j + 1 >= dest_len) - goto overflow; - dest[j++] = c; - } else { - if (j + 2 >= dest_len) - goto overflow; - dest[j++] = (c >> 6) | 0xC0; - dest[j++] = (c & 0x3F) | 0x80; - } - } - if (j < dest_len) - dest[j] = '\0'; - return j; - -overflow: - if (j < dest_len) - dest[j] = '\0'; - while (i < src_len) - j += 1 + (src[i++] >= 0x80); - return j; -} - -/* Encode a buffer of 16-bit code points as a UTF-8 encoded string - `src` points to the source buffer. - `src_len` is the length of the source buffer - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length in bytes of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len) -{ - size_t i, j; - uint32_t c; - - for (i = j = 0; i < src_len;) { - c = src[i++]; - if (c < 0x80) { - if (j + 1 >= dest_len) - goto overflow; - dest[j++] = c; - } else { - if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) - c = from_surrogate(c, src[i++]); - if (j + utf8_encode_len(c) >= dest_len) - goto overflow; - j += utf8_encode((uint8_t *)dest + j, c); - } - } - if (j < dest_len) - dest[j] = '\0'; - return j; - -overflow: - i -= 1 + (c > 0xFFFF); - if (j < dest_len) - dest[j] = '\0'; - while (i < src_len) { - c = src[i++]; - if (c < 0x80) { - j++; - } else { - if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) - c = from_surrogate(c, src[i++]); - j += utf8_encode_len(c); - } - } - return j; -} - -/*---- sorting with opaque argument ----*/ - -typedef void (*exchange_f)(void *a, void *b, size_t size); -typedef int (*cmp_f)(const void *, const void *, void *opaque); - -static void exchange_bytes(void *a, void *b, size_t size) { - uint8_t *ap = (uint8_t *)a; - uint8_t *bp = (uint8_t *)b; - - while (size-- != 0) { - uint8_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_byte(void *a, void *b, size_t size) { - uint8_t *ap = (uint8_t *)a; - uint8_t *bp = (uint8_t *)b; - uint8_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int16s(void *a, void *b, size_t size) { - uint16_t *ap = (uint16_t *)a; - uint16_t *bp = (uint16_t *)b; - - for (size /= sizeof(uint16_t); size-- != 0;) { - uint16_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int16(void *a, void *b, size_t size) { - uint16_t *ap = (uint16_t *)a; - uint16_t *bp = (uint16_t *)b; - uint16_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int32s(void *a, void *b, size_t size) { - uint32_t *ap = (uint32_t *)a; - uint32_t *bp = (uint32_t *)b; - - for (size /= sizeof(uint32_t); size-- != 0;) { - uint32_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int32(void *a, void *b, size_t size) { - uint32_t *ap = (uint32_t *)a; - uint32_t *bp = (uint32_t *)b; - uint32_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int64s(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - - for (size /= sizeof(uint64_t); size-- != 0;) { - uint64_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int64(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - uint64_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int128s(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - - for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { - uint64_t t = ap[0]; - uint64_t u = ap[1]; - ap[0] = bp[0]; - ap[1] = bp[1]; - bp[0] = t; - bp[1] = u; - } -} - -static void exchange_one_int128(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - uint64_t t = ap[0]; - uint64_t u = ap[1]; - ap[0] = bp[0]; - ap[1] = bp[1]; - bp[0] = t; - bp[1] = u; -} - -static inline exchange_f exchange_func(const void *base, size_t size) { - switch (((uintptr_t)base | (uintptr_t)size) & 15) { - case 0: - if (size == sizeof(uint64_t) * 2) - return exchange_one_int128; - else - return exchange_int128s; - case 8: - if (size == sizeof(uint64_t)) - return exchange_one_int64; - else - return exchange_int64s; - case 4: - case 12: - if (size == sizeof(uint32_t)) - return exchange_one_int32; - else - return exchange_int32s; - case 2: - case 6: - case 10: - case 14: - if (size == sizeof(uint16_t)) - return exchange_one_int16; - else - return exchange_int16s; - default: - if (size == 1) - return exchange_one_byte; - else - return exchange_bytes; - } -} - -static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) -{ - uint8_t *basep = (uint8_t *)base; - size_t i, n, c, r; - exchange_f swap = exchange_func(base, size); - - if (nmemb > 1) { - i = (nmemb / 2) * size; - n = nmemb * size; - - while (i > 0) { - i -= size; - for (r = i; (c = r * 2 + size) < n; r = c) { - if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) - c += size; - if (cmp(basep + r, basep + c, opaque) > 0) - break; - swap(basep + r, basep + c, size); - } - } - for (i = n - size; i > 0; i -= size) { - swap(basep, basep + i, size); - - for (r = 0; (c = r * 2 + size) < i; r = c) { - if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) - c += size; - if (cmp(basep + r, basep + c, opaque) > 0) - break; - swap(basep + r, basep + c, size); - } - } - } -} - -static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) -{ - return cmp(a, b, opaque) < 0 ? - (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : - (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); -} - -/* pointer based version with local stack and insertion sort threshhold */ -void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) -{ - struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; - uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; - size_t m4, i, lt, gt, span, span2; - int c, depth; - exchange_f swap = exchange_func(base, size); - exchange_f swap_block = exchange_func(base, size | 128); - - if (nmemb < 2 || size <= 0) - return; - - sp->base = (uint8_t *)base; - sp->count = nmemb; - sp->depth = 0; - sp++; - - while (sp > stack) { - sp--; - ptr = sp->base; - nmemb = sp->count; - depth = sp->depth; - - while (nmemb > 6) { - if (++depth > 50) { - /* depth check to ensure worst case logarithmic time */ - heapsortx(ptr, nmemb, size, cmp, opaque); - nmemb = 0; - break; - } - /* select median of 3 from 1/4, 1/2, 3/4 positions */ - /* should use median of 5 or 9? */ - m4 = (nmemb >> 2) * size; - m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); - swap(ptr, m, size); /* move the pivot to the start or the array */ - i = lt = 1; - pi = plt = ptr + size; - gt = nmemb; - pj = pgt = top = ptr + nmemb * size; - for (;;) { - while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { - if (c == 0) { - swap(plt, pi, size); - lt++; - plt += size; - } - i++; - pi += size; - } - while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { - if (c == 0) { - gt--; - pgt -= size; - swap(pgt, pj, size); - } - } - if (pi >= pj) - break; - swap(pi, pj, size); - i++; - pi += size; - } - /* array has 4 parts: - * from 0 to lt excluded: elements identical to pivot - * from lt to pi excluded: elements smaller than pivot - * from pi to gt excluded: elements greater than pivot - * from gt to n excluded: elements identical to pivot - */ - /* move elements identical to pivot in the middle of the array: */ - /* swap values in ranges [0..lt[ and [i-lt..i[ - swapping the smallest span between lt and i-lt is sufficient - */ - span = plt - ptr; - span2 = pi - plt; - lt = i - lt; - if (span > span2) - span = span2; - swap_block(ptr, pi - span, span); - /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ - swapping the smallest span between top-gt and gt-i is sufficient - */ - span = top - pgt; - span2 = pgt - pi; - pgt = top - span2; - gt = nmemb - (gt - i); - if (span > span2) - span = span2; - swap_block(pi, top - span, span); - - /* now array has 3 parts: - * from 0 to lt excluded: elements smaller than pivot - * from lt to gt excluded: elements identical to pivot - * from gt to n excluded: elements greater than pivot - */ - /* stack the larger segment and keep processing the smaller one - to minimize stack use for pathological distributions */ - if (lt > nmemb - gt) { - sp->base = ptr; - sp->count = lt; - sp->depth = depth; - sp++; - ptr = pgt; - nmemb -= gt; - } else { - sp->base = pgt; - sp->count = nmemb - gt; - sp->depth = depth; - sp++; - nmemb = lt; - } - } - /* Use insertion sort for small fragments */ - for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { - for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) - swap(pj, pj - size, size); - } - } -} - -/*---- Portable time functions ----*/ - -#ifdef _WIN32 - // From: https://stackoverflow.com/a/26085827 -static int gettimeofday_msvc(struct timeval *tp) -{ - static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); - - SYSTEMTIME system_time; - FILETIME file_time; - uint64_t time; - - GetSystemTime(&system_time); - SystemTimeToFileTime(&system_time, &file_time); - time = ((uint64_t)file_time.dwLowDateTime); - time += ((uint64_t)file_time.dwHighDateTime) << 32; - - tp->tv_sec = (long)((time - EPOCH) / 10000000L); - tp->tv_usec = (long)(system_time.wMilliseconds * 1000); - - return 0; -} - -uint64_t js__hrtime_ns(void) { - LARGE_INTEGER counter, frequency; - double scaled_freq; - double result; - - if (!QueryPerformanceFrequency(&frequency)) - abort(); - assert(frequency.QuadPart != 0); - - if (!QueryPerformanceCounter(&counter)) - abort(); - assert(counter.QuadPart != 0); - - /* Because we have no guarantee about the order of magnitude of the - * performance counter interval, integer math could cause this computation - * to overflow. Therefore we resort to floating point math. - */ - scaled_freq = (double) frequency.QuadPart / NANOSEC; - result = (double) counter.QuadPart / scaled_freq; - return (uint64_t) result; -} -#else -uint64_t js__hrtime_ns(void) { - struct timespec t; - - if (clock_gettime(CLOCK_MONOTONIC, &t)) - abort(); - - return t.tv_sec * NANOSEC + t.tv_nsec; -} -#endif - -int64_t js__gettimeofday_us(void) { - struct timeval tv; -#ifdef _WIN32 - gettimeofday_msvc(&tv); -#else - gettimeofday(&tv, NULL); -#endif - return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; -} - -#if defined(_WIN32) -int js_exepath(char *buffer, size_t *size_ptr) { - int utf8_len, utf16_buffer_len, utf16_len; - WCHAR* utf16_buffer; - - if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) - return -1; - - if (*size_ptr > 32768) { - /* Windows paths can never be longer than this. */ - utf16_buffer_len = 32768; - } else { - utf16_buffer_len = (int)*size_ptr; - } - - utf16_buffer = malloc(sizeof(WCHAR) * utf16_buffer_len); - if (!utf16_buffer) - return -1; - - /* Get the path as UTF-16. */ - utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); - if (utf16_len <= 0) - goto error; - - /* Convert to UTF-8 */ - utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - (int)*size_ptr, - NULL, - NULL); - if (utf8_len == 0) - goto error; - - free(utf16_buffer); - - /* utf8_len *does* include the terminating null at this point, but the - * returned size shouldn't. */ - *size_ptr = utf8_len - 1; - return 0; - -error: - free(utf16_buffer); - return -1; -} -#elif defined(__APPLE__) -int js_exepath(char *buffer, size_t *size) { - /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ - char abspath[PATH_MAX * 2 + 1]; - char exepath[PATH_MAX + 1]; - uint32_t exepath_size; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - exepath_size = sizeof(exepath); - if (_NSGetExecutablePath(exepath, &exepath_size)) - return -1; - - if (realpath(exepath, abspath) != abspath) - return -1; - - abspath_size = strlen(abspath); - if (abspath_size == 0) - return -1; - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} -#elif defined(__linux__) || defined(__GNU__) -int js_exepath(char *buffer, size_t *size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return n; - - buffer[n] = '\0'; - *size = n; - - return 0; -} -#else -int js_exepath(char* buffer, size_t* size_ptr) { - return -1; -} -#endif - -/*--- Cross-platform threading APIs. ----*/ - -#if JS_HAVE_THREADS -#if defined(_WIN32) -typedef void (*js__once_cb)(void); - -typedef struct { - js__once_cb callback; -} js__once_data_t; - -static int WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) { - js__once_data_t *data = param; - - data->callback(); - - return 1; -} - -void js_once(js_once_t *guard, js__once_cb callback) { - js__once_data_t data = { .callback = callback }; - InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL); -} - -void js_mutex_init(js_mutex_t *mutex) { - InitializeCriticalSection(mutex); -} - -void js_mutex_destroy(js_mutex_t *mutex) { - DeleteCriticalSection(mutex); -} - -void js_mutex_lock(js_mutex_t *mutex) { - EnterCriticalSection(mutex); -} - -void js_mutex_unlock(js_mutex_t *mutex) { - LeaveCriticalSection(mutex); -} - -void js_cond_init(js_cond_t *cond) { - InitializeConditionVariable(cond); -} - -void js_cond_destroy(js_cond_t *cond) { - /* nothing to do */ - (void) cond; -} - -void js_cond_signal(js_cond_t *cond) { - WakeConditionVariable(cond); -} - -void js_cond_broadcast(js_cond_t *cond) { - WakeAllConditionVariable(cond); -} - -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { - if (!SleepConditionVariableCS(cond, mutex, INFINITE)) - abort(); -} - -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { - if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6))) - return 0; - if (GetLastError() != ERROR_TIMEOUT) - abort(); - return -1; -} - -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, - int flags) -{ - HANDLE h, cp; - - *thrd = INVALID_HANDLE_VALUE; - if (flags & ~JS_THREAD_CREATE_DETACHED) - return -1; - h = (HANDLE)_beginthread(start, /*stacksize*/2<<20, arg); - if (!h) - return -1; - if (flags & JS_THREAD_CREATE_DETACHED) - return 0; - // _endthread() automatically closes the handle but we want to wait on - // it so make a copy. Race-y for very short-lived threads. Can be solved - // by switching to _beginthreadex(CREATE_SUSPENDED) but means changing - // |start| from __cdecl to __stdcall. - cp = GetCurrentProcess(); - if (DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS)) - return 0; - return -1; -} - -int js_thread_join(js_thread_t thrd) -{ - if (WaitForSingleObject(thrd, INFINITE)) - return -1; - CloseHandle(thrd); - return 0; -} - -#else /* !defined(_WIN32) */ - -void js_once(js_once_t *guard, void (*callback)(void)) { - if (pthread_once(guard, callback)) - abort(); -} - -void js_mutex_init(js_mutex_t *mutex) { - if (pthread_mutex_init(mutex, NULL)) - abort(); -} - -void js_mutex_destroy(js_mutex_t *mutex) { - if (pthread_mutex_destroy(mutex)) - abort(); -} - -void js_mutex_lock(js_mutex_t *mutex) { - if (pthread_mutex_lock(mutex)) - abort(); -} - -void js_mutex_unlock(js_mutex_t *mutex) { - if (pthread_mutex_unlock(mutex)) - abort(); -} - -void js_cond_init(js_cond_t *cond) { -#if defined(__APPLE__) && defined(__MACH__) - if (pthread_cond_init(cond, NULL)) - abort(); -#else - pthread_condattr_t attr; - - if (pthread_condattr_init(&attr)) - abort(); - - if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) - abort(); - - if (pthread_cond_init(cond, &attr)) - abort(); - - if (pthread_condattr_destroy(&attr)) - abort(); -#endif -} - -void js_cond_destroy(js_cond_t *cond) { -#if defined(__APPLE__) && defined(__MACH__) - /* It has been reported that destroying condition variables that have been - * signalled but not waited on can sometimes result in application crashes. - * See https://codereview.chromium.org/1323293005. - */ - pthread_mutex_t mutex; - struct timespec ts; - int err; - - if (pthread_mutex_init(&mutex, NULL)) - abort(); - - if (pthread_mutex_lock(&mutex)) - abort(); - - ts.tv_sec = 0; - ts.tv_nsec = 1; - - err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts); - if (err != 0 && err != ETIMEDOUT) - abort(); - - if (pthread_mutex_unlock(&mutex)) - abort(); - - if (pthread_mutex_destroy(&mutex)) - abort(); -#endif /* defined(__APPLE__) && defined(__MACH__) */ - - if (pthread_cond_destroy(cond)) - abort(); -} - -void js_cond_signal(js_cond_t *cond) { - if (pthread_cond_signal(cond)) - abort(); -} - -void js_cond_broadcast(js_cond_t *cond) { - if (pthread_cond_broadcast(cond)) - abort(); -} - -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { -#if defined(__APPLE__) && defined(__MACH__) - int r; - - errno = 0; - r = pthread_cond_wait(cond, mutex); - - /* Workaround for a bug in OS X at least up to 13.6 - * See https://github.com/libuv/libuv/issues/4165 - */ - if (r == EINVAL && errno == EBUSY) - return; - if (r) - abort(); -#else - if (pthread_cond_wait(cond, mutex)) - abort(); -#endif -} - -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { - int r; - struct timespec ts; - -#if !defined(__APPLE__) - timeout += js__hrtime_ns(); -#endif - - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; -#if defined(__APPLE__) && defined(__MACH__) - r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -#else - r = pthread_cond_timedwait(cond, mutex, &ts); -#endif - - if (r == 0) - return 0; - - if (r == ETIMEDOUT) - return -1; - - abort(); - - /* Pacify some compilers. */ - return -1; -} - -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, - int flags) -{ - union { - void (*x)(void *); - void *(*f)(void *); - } u = {start}; - pthread_attr_t attr; - int ret; - - if (flags & ~JS_THREAD_CREATE_DETACHED) - return -1; - if (pthread_attr_init(&attr)) - return -1; - ret = -1; - if (pthread_attr_setstacksize(&attr, 2<<20)) - goto fail; - if (flags & JS_THREAD_CREATE_DETACHED) - if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) - goto fail; - if (pthread_create(thrd, &attr, u.f, arg)) - goto fail; - ret = 0; -fail: - pthread_attr_destroy(&attr); - return ret; -} - -int js_thread_join(js_thread_t thrd) -{ - if (pthread_join(thrd, NULL)) - return -1; - return 0; -} - -#endif /* !defined(_WIN32) */ -#endif /* JS_HAVE_THREADS */ - -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif diff --git a/quickjs-ng/cxxtest.cc b/quickjs-ng/cxxtest.cc deleted file mode 100644 index b615100..0000000 --- a/quickjs-ng/cxxtest.cc +++ /dev/null @@ -1,2 +0,0 @@ -// note: file is not actually compiled, only checked for C++ syntax errors -#include "ctest.c" diff --git a/quickjs-ng/docs/.gitignore b/quickjs-ng/docs/.gitignore deleted file mode 100644 index b2d6de3..0000000 --- a/quickjs-ng/docs/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# Dependencies -/node_modules - -# Production -/build - -# Generated files -.docusaurus -.cache-loader - -# Misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/quickjs-ng/docs/.nvmrc b/quickjs-ng/docs/.nvmrc deleted file mode 100644 index 3c03207..0000000 --- a/quickjs-ng/docs/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -18 diff --git a/quickjs-ng/docs/babel.config.js b/quickjs-ng/docs/babel.config.js deleted file mode 100644 index e00595d..0000000 --- a/quickjs-ng/docs/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; diff --git a/quickjs-ng/docs/docs/building.md b/quickjs-ng/docs/docs/building.md deleted file mode 100644 index 30ac215..0000000 --- a/quickjs-ng/docs/docs/building.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Building - -QuickJS uses [CMake] as its main build system, with an additional helper [Makefile]. - -:::note -Windows users will need to run the CMake commands manually. -::: - -## Getting the source - -```bash -git clone https://github.com/quickjs-ng/quickjs.git -cd quickjs -``` - -## Compiling everything - -```bash -make -``` - -This will build the `qjs` and `qjsc` executables and other test tools. Head over [here](./cli) for -instructions on how to use them. - -## Amalgamated builds - -The amalgamated build rolls individual source files into a single big file. -It's a good choice for projects that want to use QuickJS without CMake. - -Download quickjs-amalgam.zip from https://github.com/quickjs-ng/quickjs/releases - -To enable the std, os and bjson modules, compile quickjs-amalgam.c with -`-DQJS_BUILD_LIBC`. - -## Debug builds - -```bash -make debug -``` - -This will produce a debug build without optimizations, suitable for developers. - -## Running test262 - -```bash -make test262 -``` - -This will run the test262 suite. - -```bash -make test262-update -``` - -This will run the test262 suite and update the error / pass report, useful after -implementing a new feature that would alter the result of the test suite. - -[CMake]: https://cmake.org -[Makefile]: https://www.gnu.org/software/make/ diff --git a/quickjs-ng/docs/docs/cli.md b/quickjs-ng/docs/docs/cli.md deleted file mode 100644 index 2ef6d11..0000000 --- a/quickjs-ng/docs/docs/cli.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -sidebar_position: 4 ---- - -# The qjs and qjsc CLI tools - -## `qjs` - The QuickJS JavaScript interpreter - -The `qjs` executable runs the JavaScript interpreter. It includes a simple standard -library and REPL. - -``` -$ qjs -usage: qjs [options] [file [args]] --h --help list options --e --eval EXPR evaluate EXPR --i --interactive go to interactive mode --m --module load as ES6 module (default=autodetect) - --script load as ES6 script (default=autodetect) --I --include file include an additional file - --std make 'std', 'os' and 'bjson' available to script --T --trace trace memory allocation --d --dump dump the memory usage stats --D --dump-flags flags for dumping debug data (see DUMP_* defines) --c --compile FILE compile the given JS file as a standalone executable --o --out FILE output file for standalone executables - --exe select the executable to use as the base, defaults to the current one - --memory-limit n limit the memory usage to 'n' Kbytes - --stack-size n limit the stack size to 'n' Kbytes - --unhandled-rejection dump unhandled promise rejections --q --quit just instantiate the interpreter and quit -``` - -The following dump flags are supported: - -``` -DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */ -DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */ -DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */ -DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */ -DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */ -DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */ -DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */ -DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */ -DUMP_FREE 0x200 /* dump every object free */ -DUMP_GC 0x400 /* dump the occurrence of the automatic GC */ -DUMP_GC_FREE 0x800 /* dump objects freed by the GC */ -DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */ -DUMP_PROMISE 0x2000 /* dump promise steps */ -DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */ -DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */ -DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */ -DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ -DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ -DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ -``` - -### Creating standalone executables - -With the `qjs` CLI it's possible to create standalone executables that will bundle the given JavaScript file -alongside the binary. - -``` -$ qjs -c app.js -o app --exe qjs -``` - -The resulting `app` binary will have the same runtime dependencies as the `qjs` binary. This is acomplished -by compiling the target JavaScript file to bytecode and adding it a copy of the executable, with a little -trailer to help locate it. `--exe` expects the absolute path to `qjs`, e.g., `~/bin/qjs` or `$HOME/bin/qjs`. - -Rather than using the current executable, it's possible to use the `--exe` switch to create standalone -executables for other platforms. - -No JavaScript bundling is performed, the specified JS file cannot depend on other files. A bundler such -as `esbuild` can be used to generate an app bundle which can then be turned into the executable. - -``` -npx esbuild my-app/index.js \ - --bundle \ - --outfile=app.js \ - --external:qjs:* \ - --minify \ - --target=es2023 \ - --platform=neutral \ - --format=esm \ - --main-fields=main,module -``` - -## `qjsc` - The QuickJS JavaScript compiler - -The `qjsc` executable runs the JavaScript compiler, it can generate bytecode from -source files which can then be embedded in an executable, or it can generate the necessary -scaffolding to build a C application which embeds QuickJS. - -``` -$ qjsc -usage: qjsc [options] [files] - -options are: --b output raw bytecode instead of C code --e output main() and bytecode in a C file --o output set the output filename --n script_name set the script name (as used in stack traces) --N cname set the C name of the generated data --m compile as JavaScript module (default=autodetect) --D module_name compile a dynamically loaded module or worker --M module_name[,cname] add initialization code for an external C module --p prefix set the prefix of the generated C names --s strip the source code, specify twice to also strip debug info --S n set the maximum stack size to 'n' bytes (default=262144) -``` - -Here is an example on how to create a standalone executable that embeds QuickJS -and the `examples/hello.js` JavaScript file: - -```bash -# Make sure you are in the QuickJS source directory. -$ cc hello.c cutils.c libbf.c libregexp.c libunicode.c quickjs.c quickjs-libc.c -I. -o hello -``` - -The resulting binary `hello` will be in the current directory. - -```bash -$ ./hello -Hello World -``` - -:::note -See the ["Creating standalone executables"](#creating-standalone-executables) section for a simpler way. -::: diff --git a/quickjs-ng/docs/docs/developer-guide/_category_.json b/quickjs-ng/docs/docs/developer-guide/_category_.json deleted file mode 100644 index 6050477..0000000 --- a/quickjs-ng/docs/docs/developer-guide/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Developer Guide", - "position": 6, - "link": { - "type": "generated-index" - } -} diff --git a/quickjs-ng/docs/docs/developer-guide/api.md b/quickjs-ng/docs/docs/developer-guide/api.md deleted file mode 100644 index 78bec94..0000000 --- a/quickjs-ng/docs/docs/developer-guide/api.md +++ /dev/null @@ -1,3 +0,0 @@ -# API Reference - -WIP. diff --git a/quickjs-ng/docs/docs/developer-guide/internals.md b/quickjs-ng/docs/docs/developer-guide/internals.md deleted file mode 100644 index 4c9afea..0000000 --- a/quickjs-ng/docs/docs/developer-guide/internals.md +++ /dev/null @@ -1,117 +0,0 @@ -# Internals - -## Bytecode - -The compiler generates bytecode directly with no intermediate -representation such as a parse tree, hence it is very fast. Several -optimizations passes are done over the generated bytecode. - -A stack-based bytecode was chosen because it is simple and generates -compact code. - -For each function, the maximum stack size is computed at compile time so that -no runtime stack overflow tests are needed. - -A separate compressed line number table is maintained for the debug -information. - -Access to closure variables is optimized and is almost as fast as local -variables. - -Direct `eval` in strict mode is optimized. - -## Runtime - -### Strings - -Strings are stored either as an 8 bit or a 16 bit array of -characters. Hence random access to characters is always fast. - -The C API provides functions to convert JavaScript Strings to C UTF-8 encoded -strings. The most common case where the JavaScript string contains -only ASCII characters involves no copying. - -### Objects - -The object shapes (object prototype, property names and flags) are shared -between objects to save memory. - -Arrays with no holes (except at the end of the array) are optimized. - -TypedArray accesses are optimized. - -### Atoms - -Object property names and some strings are stored as Atoms (unique -strings) to save memory and allow fast comparison. Atoms are -represented as a 32 bit integer. Half of the atom range is reserved for -immediate integer literals from 0 to 2^31-1. - -### Numbers - -Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754 -floating point values. Most operations have fast paths for the 32-bit -integer case. - -### Garbage collection - -Reference counting is used to free objects automatically and -deterministically. A separate cycle removal pass is done when the allocated -memory becomes too large. The cycle removal algorithm only uses the -reference counts and the object content, so no explicit garbage -collection roots need to be manipulated in the C code. - -### JSValue - -It is a JavaScript value which can be a primitive type (such as -Number, String, ...) or an Object. NaN boxing is used in the 32-bit version -to store 64-bit floating point numbers. The representation is -optimized so that 32-bit integers and reference counted values can be -efficiently tested. - -In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The -rationale is that in 64-bit code memory usage is less critical. - -In both cases (32 or 64 bits), JSValue exactly fits two CPU registers, -so it can be efficiently returned by C functions. - -### Function call - -The engine is optimized so that function calls are fast. The system -stack holds the JavaScript parameters and local variables. - -### RegExp - -A specific regular expression engine was developed. It is both small -and efficient and supports all the ES2020+ features including the -Unicode properties. As the JavaScript compiler, it directly generates -bytecode without a parse tree. - -Backtracking with an explicit stack is used so that there is no -recursion on the system stack. Simple quantifiers are specifically -optimized to avoid recursions. - -Infinite recursions coming from quantifiers with empty terms are -avoided. - -The full regexp library weighs about 15 KiB (x86 code), excluding the -Unicode library. - -### Unicode - -A specific Unicode library was developed so that there is no -dependency on an external large Unicode library such as ICU. All the -Unicode tables are compressed while keeping a reasonable access -speed. - -The library supports case conversion, Unicode normalization, Unicode -script queries, Unicode general category queries and all Unicode -binary properties. - -The full Unicode library weighs about 45 KiB (x86 code). - -### BigInt - -BigInt is implemented with the [libbf](https://bellard.org/libbf) library. -It weights about 90 KiB (x86 code) and provides arbitrary precision IEEE 754 floating -point operations and transcendental functions with exact rounding. diff --git a/quickjs-ng/docs/docs/developer-guide/intro.md b/quickjs-ng/docs/docs/developer-guide/intro.md deleted file mode 100644 index 4d85efb..0000000 --- a/quickjs-ng/docs/docs/developer-guide/intro.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -sidebar_position: 1 ---- - -# The QuickJS C API - -The C API was designed to be simple and efficient. The C API is -defined in the header `quickjs.h`. - -## Runtime and contexts - -`JSRuntime` represents a JavaScript runtime corresponding to an -object heap. Several runtimes can exist at the same time but they -cannot exchange objects. Inside a given runtime, no multi-threading is -supported. - -`JSContext` represents a JavaScript context (or Realm). Each -JSContext has its own global objects and system objects. There can be -several JSContexts per JSRuntime and they can share objects, similar -to frames of the same origin sharing JavaScript objects in a -web browser. - -## JSValue - -`JSValue` represents a JavaScript value which can be a primitive -type or an object. Reference counting is used, so it is important to -explicitly duplicate (`JS_DupValue()`, increment the reference -count) or free (`JS_FreeValue()`, decrement the reference count) -JSValues. - -## C functions - -C functions can be created with -`JS_NewCFunction()`. `JS_SetPropertyFunctionList()` is a -shortcut to easily add functions, setters and getters properties to a -given object. - -Unlike other embedded JavaScript engines, there is no implicit stack, -so C functions get their parameters as normal C parameters. As a -general rule, C functions take constant `JSValue`s as parameters -(so they don't need to free them) and return a newly allocated (=live) -`JSValue`. - -## Exceptions - -Most C functions can return a JavaScript exception. It -must be explicitly tested and handled by the C code. The specific -`JSValue` `JS_EXCEPTION` indicates that an exception -occurred. The actual exception object is stored in the -`JSContext` and can be retrieved with `JS_GetException()`. - -## Script evaluation - -Use `JS_Eval()` to evaluate a script or module source. - -If the script or module was compiled to bytecode with `qjsc`, it -can be evaluated by calling `js_std_eval_binary()`. The advantage -is that no compilation is needed so it is faster and smaller because -the compiler can be removed from the executable if no `eval` is -required. - -Note: the bytecode format is linked to a given QuickJS -version. Moreover, no security check is done before its -execution. Hence the bytecode should not be loaded from untrusted -sources. - -## JS Classes - -C opaque data can be attached to a JavaScript object. The type of the -C opaque data is determined with the class ID (`JSClassID`) of -the object. Hence the first step is to register a new class ID and JS -class (`JS_NewClassID()`, `JS_NewClass()`). Then you can -create objects of this class with `JS_NewObjectClass()` and get or -set the C opaque point with `JS_GetOpaque()` / `JS_SetOpaque()`. - -When defining a new JS class, it is possible to declare a finalizer -which is called when the object is destroyed. The finalizer should be -used to release C resources. It is invalid to execute JS code from -it. A `gc_mark` method can be provided so that the cycle removal -algorithm can find the other objects referenced by this object. Other -methods are available to define exotic object behaviors. - -The Class ID are allocated per-runtime. The -`JSClass` are allocated per `JSRuntime`. `JS_SetClassProto()` -is used to define a prototype for a given class in a given -`JSContext`. `JS_NewObjectClass()` sets this prototype in the -created object. - -Examples are available in `quickjs-libc.c`. - -## C Modules - -Native ES6 modules are supported and can be dynamically or statically -linked. The standard library `quickjs-libc.c` is a good example -of a native module. - -## Memory handling - -Use `JS_SetMemoryLimit()` to set a global memory allocation limit -to a given `JSRuntime`. - -Custom memory allocation functions can be provided with `JS_NewRuntime2()`. - -The maximum system stack size can be set with `JS_SetMaxStackSize()`. - -## Execution timeout and interrupts - -Use `JS_SetInterruptHandler()` to set a callback which is -regularly called by the engine when it is executing code. This -callback can be used to implement an execution timeout. - -It is used by the command line interpreter to implement a -`Ctrl-C` handler. diff --git a/quickjs-ng/docs/docs/diff.md b/quickjs-ng/docs/docs/diff.md deleted file mode 100644 index 1390e1b..0000000 --- a/quickjs-ng/docs/docs/diff.md +++ /dev/null @@ -1,68 +0,0 @@ -# Differences with bellard/quickjs - -This project aims to be a drop-in replacement for those already using QuickJS. -Minimal API changes might be necessary. - -## Community development - -NG is developed in the open, interacting with the wider community and through -these interactions many improvements have already been made, including the incorporation -of patches previously maintained in other forks. - -Each PR is reviewed, iterated on, and merged in GitHub. - -To date, NG has had over 40 distinct contributors and over 400 PRs. - -## Consistent release cadence - -As the project moves forward, a steady cadence of releases has been maintained, with an -average of a new release every 2 months. - -## Testing - -Since its inception testing has been a focus. Each PR is tested in over 50 configurations, -involving different operating systems, build types and sanitizers. - -The `test262` suite is also ran for every change. - -## Cross-platform support - -In order to better support other platforms such as Windows the build system was -changed to use [CMake]. - -In addition, Windows is treated as a first class citizen, with the addition of support -for the MSVC compiler. - -[CMake]: https://cmake.org/ - -## Performance - -While being an interpreter limits the performance in comparison with other engines which -use a JIT, several significant performance improvements have been made: - -- Opcode fusion -- Polymorphic inline caching -- Memory allocation improvements -- Improved parse speeds - -## New ECMAScript APIs - -The main focus of NG is to deliver state-of-the-art JavaScript features. Typically once they -are stable (stage 4) but sometimes even at earlier stages. Here is a non-exhaustive list -of ES features present in NG: - -- Resizable ArrayBuffer -- Float16Array -- WeakRef -- FinalizationRegistry -- Iterator Helpers -- Promise.try -- Error.isError -- Set operations - -Some non-standard but widely used APIs have also been added: - -- V8's [stack trace API](https://v8.dev/docs/stack-trace-api) - - `Error.captureStackTrace` - - `Error.prepareStackTrace` - - `Error.stackTraceLimit` diff --git a/quickjs-ng/docs/docs/es_features.md b/quickjs-ng/docs/docs/es_features.md deleted file mode 100644 index d57754c..0000000 --- a/quickjs-ng/docs/docs/es_features.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -sidebar_position: 7 ---- - -# ECMAScript Features - -QuickJS aims to support the latest available ECMAScript features once they hit the spec. - -Progress on _test262_ compliance can be checked [here](https://test262.fyi/#|qjs_ng). - -Due to size constraints it is unlikely QuickJS will ever support the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) APIs. diff --git a/quickjs-ng/docs/docs/installation.md b/quickjs-ng/docs/docs/installation.md deleted file mode 100644 index 5df467c..0000000 --- a/quickjs-ng/docs/docs/installation.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Installation - -Installing QuickJS is simple, and we provide several ways to do so. - - -## Build from source - -If you built it from source as outlined in [building](./building) you can just run: - -```bash -make install -``` - -and it will be installed in your system. The default installation path is `/usr/local`. - - -## Using a prebuilt binary - -Each [release on GitHub] includes binaries for several systems and architectures. - - -## Using jsvu - -As of version 2.2.0 of `jsvu`, QuickJS-ng will be installed when the `quickjs` engine is requested. - -```bash -npm install jsvu -g -``` - -[release on GitHub]: https://github.com/quickjs-ng/quickjs/releases diff --git a/quickjs-ng/docs/docs/intro.md b/quickjs-ng/docs/docs/intro.md deleted file mode 100644 index cb63ed5..0000000 --- a/quickjs-ng/docs/docs/intro.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -slug: / -sidebar_position: 1 -sidebar_label: Welcome ---- - -# Welcome to QuickJS-NG - -QuickJS is a small and embeddable JavaScript engine. It aims to support the latest -[ECMAScript] specification. - -This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development. - -This project is focused on (but not limited to): - -- Community development -- Testing -- Cross-platform support -- ES features - -You can check the differences with the original project [here.](./diff) - -:::note -This site is under construction, the entire API is not yet documented. -::: - -## Getting Started - -Head over to [building](./building) if you want to build QuickJS from source or [installation](./installation) -for installing it from prebuilt binaries. - -[ECMAScript]: https://tc39.es/ecma262/ -[original QuickJS project]: https://bellard.org/quickjs diff --git a/quickjs-ng/docs/docs/projects.md b/quickjs-ng/docs/docs/projects.md deleted file mode 100644 index 05e9798..0000000 --- a/quickjs-ng/docs/docs/projects.md +++ /dev/null @@ -1,36 +0,0 @@ -# Projects using NG - -Here is a list of projects currently using, supporting or migrating to QuickJS-NG. -If you want yours to be listed here, please open a PR! - -## [txiki.js](https://github.com/saghul/txiki.js) - -A tiny JavaScript runtime. - -## [radare2](https://github.com/radareorg/radare2) - -Reverse engineering framework. - -## [rquickjs](https://github.com/DelSkayn/rquickjs) - -High level Rust bindings. - -## [llrt](https://github.com/awslabs/llrt) - -Lightweight JS runtime for serverless applications. - -## [nx.js](https://github.com/TooTallNate/nx.js) - -JavaScript runtime for Nintendo Switch homebrew applications. - -## [quickjs-rusty](https://github.com/Icemic/quickjs-rusty) - -Rust wrapper focus on embedding-ready and no-pain type conversion and interoperability. - -## [GodotJS](https://github.com/godotjs/GodotJS) - -This project adds TypeScript/JavaScript support for Godot 4.x. It supports multiple javascript runtimes, including QuickJS-NG. - -## [quickjs_es_runtime](https://github.com/HiRoFa/quickjs_es_runtime) - -Rust wrapper with typescript, modules, promises, async/await and much more. diff --git a/quickjs-ng/docs/docs/stdlib.md b/quickjs-ng/docs/docs/stdlib.md deleted file mode 100644 index 593a1b5..0000000 --- a/quickjs-ng/docs/docs/stdlib.md +++ /dev/null @@ -1,577 +0,0 @@ ---- -sidebar_position: 5 ---- - -# Standard library - -The standard libary is provided as part of the `qjs` executable and the `quickjs-libc.c` source file -and it's not part of the core engine. - -## Globals - -### `argv0` - -Provides the executable path. - -### `scriptArgs` - -Provides the command line arguments. The first argument is the script name. - -### `print(...args)` - -Print the arguments separated by spaces and a trailing newline. - -### `console.log(...args)` - -Same as `print()`. - -### `navigator.userAgent` - -Returns `quickjs-ng/`. - -### `gc()` - -Shorthand for `std.gc()`. - -## `qjs:bjson` module - -### `bjson.write(obj, [flags])` - -Serializes the given object into the QuickJS internal serialization format. -Returns an ArrayBuffer with the serialized data. - -Supported flags: - -- `WRITE_OBJ_BYTECODE`: allow serializing functions and modules -- `WRITE_OBJ_REFERENCE`: allow serializing object references -- `WRITE_OBJ_SAB`: allow serializing SharedArrayBuffer instances -- `WRITE_OBJ_STRIP_DEBUG`: strip debugging information when serializing -- `WRITE_OBJ_STRIP_SOURCE`: strip the source information when serializing - -### `bjson.read(buf, [pos], [len], [flags])` - -De-serialize the given ArrayBuffer (in QuickJS internal serialization format) back into a JavaScript value. - -Supported flags: - -- `READ_OBJ_BYTECODE`: allow de-serializing functions and modules -- `READ_OBJ_REFERENCE`: allow de-serializing object references -- `READ_OBJ_SAB`: allow de-serializing SharedArrayBuffer instances - -## `qjs:os` module - -The `os` module provides Operating System specific functions: - -- low level file access -- signals -- timers -- basic asynchronous I/O -- workers (threads) - -The OS functions usually return 0 if OK or an OS specific negative -error code. - -### `open(filename, flags, mode = 0o666)` - -Open a file. Return a handle or < 0 if error. - -Supported flags: - -- `O_RDONLY` -- `O_WRONLY` -- `O_RDWR` -- `O_APPEND` -- `O_CREAT` -- `O_EXCL` -- `O_TRUNC` - -POSIX open flags. - -- `O_TEXT` - -(Windows specific). Open the file in text mode. The default is binary mode. - -### `close(fd)` - -Close the file handle `fd`. - -### `seek(fd, offset, whence)` - -Seek in the file. Use `std.SEEK_*` for -`whence`. `offset` is either a number or a BigInt. If -`offset` is a BigInt, a BigInt is returned too. - -### `read(fd, buffer, offset, length)` - -Read `length` bytes from the file handle `fd` to the -ArrayBuffer `buffer` at byte position `offset`. -Return the number of read bytes or < 0 if error. - -### `write(fd, buffer, offset, length)` - -Write `length` bytes to the file handle `fd` from the -ArrayBuffer `buffer` at byte position `offset`. -Return the number of written bytes or < 0 if error. - -### `isatty(fd)` - -Return `true` is `fd` is a TTY (terminal) handle. - -### `ttyGetWinSize(fd)` - -Return the TTY size as `[width, height]` or `null` if not available. - -### `ttySetRaw(fd)` - -Set the TTY in raw mode. - -### `remove(filename)` - -Remove a file. Return 0 if OK or `-errno`. - -### `rename(oldname, newname)` - -Rename a file. Return 0 if OK or `-errno`. - -### `realpath(path)` - -Return `[str, err]` where `str` is the canonicalized absolute -pathname of `path` and `err` the error code. - -### `getcwd()` - -Return `[str, err]` where `str` is the current working directory -and `err` the error code. - -### `exePath()` - -Returns the full path of the current executable or `undefined` if not available / supported. - -### `chdir(path)` - -Change the current directory. Return 0 if OK or `-errno`. - -### `mkdir(path, mode = 0o777)` - -Create a directory at `path`. Return 0 if OK or `-errno`. - -### `stat(path)` / `lstat(path)` - -Return `[obj, err]` where `obj` is an object containing the -file status of `path`. `err` is the error code. The -following fields are defined in `obj`: `dev`, `ino`, `mode`, `nlink`, -`uid`, `gid`, `rdev`, `size`, `blocks`, `atime`, `mtime`, `ctime`. The times are -specified in milliseconds since 1970. `lstat()` is the same as -`stat()` excepts that it returns information about the link -itself. - -- `S_IFMT` -- `S_IFIFO` -- `S_IFCHR` -- `S_IFDIR` -- `S_IFBLK` -- `S_IFREG` -- `S_IFSOCK` -- `S_IFLNK` -- `S_ISGID` -- `S_ISUID` - -Constants to interpret the `mode` property returned by -`stat()`. They have the same value as in the C system header -`sys/stat.h`. - -### `utimes(path, atime, mtime)` - -Change the access and modification times of the file `path`. The -times are specified in milliseconds since 1970. Return 0 if OK or `-errno`. - -### `symlink(target, linkpath)` - -Create a link at `linkpath` containing the string `target`. Return 0 if OK or `-errno`. - -### `readlink(path)` - -Return `[str, err]` where `str` is the link target and `err` -the error code. - -### `readdir(path)` - -Return `[array, err]` where `array` is an array of strings -containing the filenames of the directory `path`. `err` is -the error code. `array` contains at least `"."` and `".."` -if successful. - -### `setReadHandler(fd, func)` - -Add a read handler to the file handle `fd`. `func` is called -each time there is data pending for `fd`. A single read handler -per file handle is supported. Use `func = null` to remove the -handler. - -### `setWriteHandler(fd, func)` - -Add a write handler to the file handle `fd`. `func` is -called each time data can be written to `fd`. A single write -handler per file handle is supported. Use `func = null` to remove -the handler. - -### `signal(signal, func)` - -Call the function `func` when the signal `signal` -happens. Only a single handler per signal number is supported. Use -`null` to set the default handler or `undefined` to ignore -the signal. Signal handlers can only be defined in the main thread. - -- `SIGINT` -- `SIGABRT` -- `SIGFPE` -- `SIGILL` -- `SIGSEGV` -- `SIGTERM` - -POSIX signal numbers. - -### `kill(pid, sig)` - -Send the signal `sig` to the process `pid`. - -### `exec(args[, options])` - -Execute a process with the arguments `args`. `options` is an -object containing optional parameters: - -- `block` - Boolean (default = true). If true, wait until the process is - terminated. In this case, `exec` return the exit code if positive - or the negated signal number if the process was interrupted by a - signal. If false, do not block and return the process id of the child. -- `usePath` - Boolean (default = true). If true, the file is searched in the - `PATH` environment variable. -- `file` - String (default = `args[0]`). Set the file to be executed. -- `cwd` - String. If present, set the working directory of the new process. -- `stdin`, `stdout`, `stderr` - If present, set the handle in the child for stdin, stdout or stderr. -- `env` - Object. If present, set the process environment from the object - key-value pairs. Otherwise use the same environment as the current - process. -- `uid` - Integer. If present, the process uid with `setuid`. -- `gid` - Integer. If present, the process gid with `setgid`. -- `groups` - Array of integer. If present, the supplementary - group IDs with `setgroup`. - -### `waitpid(pid, options)` - -`waitpid` Unix system call. Return the array `[ret, status]`. -`ret` contains `-errno` in case of error. - -- `WNOHANG` - -Constant for the `options` argument of `waitpid`. - -### `dup(fd)` - -`dup` Unix system call. - -### `dup2(oldfd, newfd)` - -`dup2` Unix system call. - -### `pipe()` - -`pipe` Unix system call. Return two handles as `[read_fd, write_fd]` or null in case of error. - -### `sleep(delay_ms)` - -Sleep during `delay_ms` milliseconds. - -### `sleepAsync(delay_ms)` - -Asynchronouse sleep during `delay_ms` milliseconds. Returns a promise. Example: - -```js -await os.sleepAsync(500); -``` - -### `setTimeout(func, delay)` - -Call the function `func` after `delay` ms. Return a timer ID. - -### `clearTimeout(id)` - -Cancel a timer. - -### `platform` - -Return a string representing the platform: `"linux"`, `"darwin"`, `"win32"` or `"js"`. - -### `Worker(module_filename)` - -Constructor to create a new thread (worker) with an API close to that of -`WebWorkers`. `module_filename` is a string specifying the -module filename which is executed in the newly created thread. As for -dynamically imported module, it is relative to the current script or -module path. Threads normally don't share any data and communicate -between each other with messages. Nested workers are not supported. An -example is available in `tests/test_worker.js`. - -The worker class has the following static properties: - -- `parent` - In the created worker, `Worker.parent` represents the parent - worker and is used to send or receive messages. - -The worker instances have the following properties: - -- `postMessage(msg)` - Send a message to the corresponding worker. `msg` is cloned in - the destination worker using an algorithm similar to the `HTML` - structured clone algorithm. `SharedArrayBuffer` are shared - between workers. - -- `onmessage` - Getter and setter. Set a function which is called each time a - message is received. The function is called with a single - argument. It is an object with a `data` property containing the - received message. The thread is not terminated if there is at least - one non `null` `onmessage` handler. - -## `qjs:std` module - -The `std` module provides wrappers to libc (`stdlib.h` and `stdio.h`) and a few other utilities. - -### `exit(n)` - -Exit the process. - -### `evalScript(str, options = undefined)` - -Evaluate the string `str` as a script (global -eval). `options` is an optional object containing the following -optional properties: - -- `backtrace_barrier` - Boolean (default = false). If true, error backtraces do not list the - stack frames below the evalScript. -- `async` - Boolean (default = false). If true, `await` is accepted in the - script and a promise is returned. The promise is resolved with an - object whose `value` property holds the value returned by the - script. - -### `loadScript(filename)` - -Evaluate the file `filename` as a script (global eval). - -### `loadFile(filename, [options])` - -Load the file `filename` and return it as a string assuming UTF-8 -encoding. Return `null` in case of I/O error. - -If `options.binary` is set to `true` a `Uint8Array` is returned instead. - -### `writeFile(filename, data)` - -Create the file `filename` and write `data` into it. - -`data` can be a string, a typed array or an `ArrayBuffer`. `undefined` is -treated as the empty string. - -When `data` is a string, the file is opened in text mode; otherwise it is -opened in binary mode. (This distinction is only relevant on Windows.) - -Throws an exception if the file cannot be created or written to. - -### `open(filename, flags, errorObj = undefined)` - -Open a file (wrapper to the libc `fopen()`). Return the FILE -object or `null` in case of I/O error. If `errorObj` is not -undefined, set its `errno` property to the error code or to 0 if -no error occurred. - -### `popen(command, flags, errorObj = undefined)` - -Open a process by creating a pipe (wrapper to the libc -`popen()`). Return the FILE -object or `null` in case of I/O error. If `errorObj` is not -undefined, set its `errno` property to the error code or to 0 if -no error occurred. - -### `fdopen(fd, flags, errorObj = undefined)` - -Open a file from a file handle (wrapper to the libc -`fdopen()`). Return the FILE -object or null` in case of I/O error. If `errorObj` is not -undefined, set its `errno` property to the error code or to 0 if -no error occurred. - -### `tmpfile(errorObj = undefined)` - -Open a temporary file. Return the FILE -object or `null` in case of I/O error. If `errorObj` is not -undefined, set its `errno` property to the error code or to 0 if -no error occurred. - -### `puts(str)` - -Equivalent to `std.out.puts(str)`. - -### `printf(fmt, ...args)` - -Equivalent to `std.out.printf(fmt, ...args)`. - -### `sprintf(fmt, ...args)` - -Equivalent to the libc sprintf(). - -### `in`, `out`, `err` - -Wrappers to the libc file `stdin`, `stdout`, `stderr`. - -### `Error` - -Enumeration object containing the integer value of common errors -(additional error codes may be defined): - -- `EINVAL` -- `EIO` -- `EACCES` -- `EEXIST` -- `ENOSPC` -- `ENOSYS` -- `EBUSY` -- `ENOENT` -- `EPERM` -- `EPIPE` - -### `strerror(errno)` - -Return a string that describes the error `errno`. - -### `gc()` - -Manually invoke the cycle removal algorithm. The cycle removal -algorithm is automatically started when needed, so this function is -useful in case of specific memory constraints or for testing. - -### `getenv(name)` - -Return the value of the environment variable `name` or -`undefined` if it is not defined. - -### `setenv(name, value)` - -Set the value of the environment variable `name` to the string -`value`. - -### `unsetenv(name)` - -Delete the environment variable `name`. - -### `getenviron()` - -Return an object containing the environment variables as key-value pairs. - -### `urlGet(url, options = undefined)` - -Download `url` using the `curl` command line -utility. `options` is an optional object containing the following -optional properties: - -- `binary` - Boolean (default = false). If true, the response is an ArrayBuffer - instead of a string. When a string is returned, the data is assumed - to be UTF-8 encoded. -- `full` - Boolean (default = false). If true, return the an object contains - the properties `response` (response content), - `responseHeaders` (headers separated by CRLF), `status` - (status code). `response` is `null` is case of protocol or - network error. If `full` is false, only the response is - returned if the status is between 200 and 299. Otherwise `null` - is returned. - -### `FILE` - -File object. - -#### `close()` - -Close the file. Return 0 if OK or `-errno` in case of I/O error. - -#### `puts(str)` - -Outputs the string with the UTF-8 encoding. - -#### `printf(fmt, ...args)` - -Formatted printf. - -The same formats as the standard C library `printf` are -supported. Integer format types (e.g. `%d`) truncate the Numbers -or BigInts to 32 bits. Use the `l` modifier (e.g. `%ld`) to -truncate to 64 bits. - -#### `flush()` - -Flush the buffered file. - -#### `seek(offset, whence)` - -Seek to a give file position (whence is -`std.SEEK_*`). `offset` can be a number or a BigInt. Return -0 if OK or `-errno` in case of I/O error. - -- `SEEK_SET` -- `SEEK_CUR` -- `SEEK_END` - -Constants for seek(). - -#### `tell()` - -Return the current file position. - -#### `tello()` - -Return the current file position as a BigInt. - -#### `eof()` - -Return true if end of file. - -#### `fileno()` - -Return the associated OS handle. - -#### `error()` - -Return true if there was an error. - -#### `clearerr()` - -Clear the error indication. - -#### `read(buffer, position, length)` - -Read `length` bytes from the file to the ArrayBuffer `buffer` at byte -position `position` (wrapper to the libc `fread`). - -#### `write(buffer, position, length)` - -Write `length` bytes to the file from the ArrayBuffer `buffer` at byte -position `position` (wrapper to the libc `fwrite`). - -#### `getline()` - -Return the next line from the file, assuming UTF-8 encoding, excluding -the trailing line feed. - -#### `readAsArrayBuffer(max_size = undefined)` - -Read `max_size` bytes from the file and return them as an ArrayBuffer. -If `max_size` is not present, the file is read until its end. - -#### `readAsString(max_size = undefined)` - -Read `max_size` bytes from the file and return them as a string -assuming UTF-8 encoding. If `max_size` is not present, the file -is read until its end. - -#### `getByte()` - -Return the next byte from the file. Return -1 if the end of file is reached. - -#### `putByte(c)` - -Write one byte to the file. diff --git a/quickjs-ng/docs/docs/supported_platforms.md b/quickjs-ng/docs/docs/supported_platforms.md deleted file mode 100644 index bb817b3..0000000 --- a/quickjs-ng/docs/docs/supported_platforms.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -sidebar_position: 8 ---- - -# Supported Platforms - -| System | Supported versions | Notes | -|---|---|---| -| GNU/Linux | * | glibc and musl are supported | -| macOS | macOS >= 11 | Currently supported macOS releases | -| Windows | >= Windows 7* | VS >= 2022 and Clang are supported; requires `` | -| FreeBSD | * | Limited testing | -| OpenBSD | * | Limited testing | -| NetBSD | * | Limited testing | -| Android | NDK >= 26.0.10792818 | Limited testing | -| iOS | * | Limited testing | -| MinGW | MinGW-w64 | | -| Other | N/A | Missing? Open a PR! | - -- `*`: Windows 7 is EOL and only supported in this project as long as it doesn't interfere with its progress. diff --git a/quickjs-ng/docs/docusaurus.config.js b/quickjs-ng/docs/docusaurus.config.js deleted file mode 100644 index 25524ed..0000000 --- a/quickjs-ng/docs/docusaurus.config.js +++ /dev/null @@ -1,114 +0,0 @@ -// @ts-check -// `@type` JSDoc annotations allow editor autocompletion and type checking -// (when paired with `@ts-check`). -// There are various equivalent ways to declare your Docusaurus config. -// See: https://docusaurus.io/docs/api/docusaurus-config - -/** @type {import('@docusaurus/types').Config} */ -const config = { - title: 'QuickJS-NG', - tagline: 'QuickJS, the Next Generation: a mighty JavaScript engine', - favicon: 'img/favicon.ico', - - // Set the production url of your site here - url: 'https://quickjs-ng.github.io', - // Set the // pathname under which your site is served - // For GitHub pages deployment, it is often '//' - baseUrl: '/quickjs/', - - // GitHub pages deployment config. - // If you aren't using GitHub pages, you don't need these. - organizationName: 'quickjs-ng', // Usually your GitHub org/user name. - projectName: 'quickjs', // Usually your repo name. - - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - - // Even if you don't use internationalization, you can use this field to set - // useful metadata like html lang. For example, if your site is Chinese, you - // may want to replace "en" with "zh-Hans". - i18n: { - defaultLocale: 'en', - locales: ['en'], - }, - - presets: [ - [ - 'classic', - /** @type {import('@docusaurus/preset-classic').Options} */ - ({ - docs: { - routeBasePath: '/', - sidebarPath: './sidebars.js', - // Please change this to your repo. - // Remove this to remove the "edit this page" links. - editUrl: 'https://github.com/quickjs-ng/quickjs/tree/master/docs/', - }, - blog: false, - theme: { - customCss: './src/css/custom.css', - }, - }), - ], - ], - - themeConfig: - /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - ({ - // Replace with your project's social card - image: 'img/docusaurus-social-card.jpg', - navbar: { - title: 'QuickJS-NG', - items: [ - { - type: 'docSidebar', - sidebarId: 'docsSidebar', - position: 'left', - label: 'Documentation', - }, - { - href: 'https://github.com/quickjs-ng/quickjs', - label: 'GitHub', - position: 'right', - }, - ], - }, - footer: { - style: 'dark', - links: [ - { - title: 'Docs', - items: [ - ], - }, - { - title: 'Community', - items: [ - { - label: 'GitHub Discussions', - href: 'https://github.com/quickjs-ng/quickjs/discussions', - }, - { - label: 'Matrix', - href: 'https://matrix.to/#/%23quickjs-ng%3Amatrix.org?via=matrix.org', - }, - ], - }, - { - title: 'More', - items: [ - { - label: 'GitHub', - href: 'https://github.com/quickjs-ng/quickjs', - }, - ], - }, - ], - copyright: `Copyright © ${new Date().getFullYear()} QuickJS-NG project contributors.`, - }, - prism: { - }, - }), -}; - -export default config; diff --git a/quickjs-ng/docs/package-lock.json b/quickjs-ng/docs/package-lock.json deleted file mode 100644 index f13c2d8..0000000 --- a/quickjs-ng/docs/package-lock.json +++ /dev/null @@ -1,14656 +0,0 @@ -{ - "name": "docs", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/preset-classic": "3.5.2", - "@mdx-js/react": "3.0.1", - "clsx": "2.1.1", - "prism-react-renderer": "2.4.0", - "react": "18.3.1", - "react-dom": "18.3.1" - }, - "devDependencies": { - "@docusaurus/module-type-aliases": "3.5.2", - "@docusaurus/types": "3.5.2" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@algolia/autocomplete-core": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", - "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", - "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", - "@algolia/autocomplete-shared": "1.9.3" - } - }, - "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", - "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", - "dependencies": { - "@algolia/autocomplete-shared": "1.9.3" - }, - "peerDependencies": { - "search-insights": ">= 1 < 3" - } - }, - "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", - "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", - "dependencies": { - "@algolia/autocomplete-shared": "1.9.3" - }, - "peerDependencies": { - "@algolia/client-search": ">= 4.9.1 < 6", - "algoliasearch": ">= 4.9.1 < 6" - } - }, - "node_modules/@algolia/autocomplete-shared": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", - "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", - "peerDependencies": { - "@algolia/client-search": ">= 4.9.1 < 6", - "algoliasearch": ">= 4.9.1 < 6" - } - }, - "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", - "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, - "node_modules/@algolia/cache-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", - "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==" - }, - "node_modules/@algolia/cache-in-memory": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", - "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", - "dependencies": { - "@algolia/cache-common": "4.24.0" - } - }, - "node_modules/@algolia/client-account": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", - "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-account/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-analytics": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", - "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-analytics/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-common": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.5.3.tgz", - "integrity": "sha512-3rdSdreBL2LGYu4DWmUGlMhaGy1vy36Xp42LdbTFsW/y3bhW5viptMHI5A3PKT0hPEMZUn+te1iM/EWvLUuVGQ==", - "peer": true, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-personalization": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", - "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/client-search": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.5.3.tgz", - "integrity": "sha512-qrokD+uoNxchbiF9aP8niQd/9SZ6BgYg4WaesFaubHhr9DFvwGm4IePEMha8vQcc3fSsY6uL+gOtKB3J6RF0NQ==", - "peer": true, - "dependencies": { - "@algolia/client-common": "5.5.3", - "@algolia/requester-browser-xhr": "5.5.3", - "@algolia/requester-fetch": "5.5.3", - "@algolia/requester-node-http": "5.5.3" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/events": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", - "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" - }, - "node_modules/@algolia/logger-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", - "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==" - }, - "node_modules/@algolia/logger-console": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", - "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", - "dependencies": { - "@algolia/logger-common": "4.24.0" - } - }, - "node_modules/@algolia/recommend": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", - "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/@algolia/requester-browser-xhr": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.5.3.tgz", - "integrity": "sha512-LsfUPokiXEpvlYF7SwNjyyjkUX7IoW7oIhH6WkDUD4PCfEZkFbVplGQA0UrCiWOAbpb25P7mmP6+ldwjwqW6Kg==", - "peer": true, - "dependencies": { - "@algolia/client-common": "5.5.3" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", - "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==" - }, - "node_modules/@algolia/requester-fetch": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.5.3.tgz", - "integrity": "sha512-RKaliEFHtVeD/fMxwrApkcI6ZxR+mU6pZna29r3NwVMpCXTJWWtlMpQmbr1RHzUsaAlpfv9pfGJN4nYPE8XWEg==", - "peer": true, - "dependencies": { - "@algolia/client-common": "5.5.3" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-node-http": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.5.3.tgz", - "integrity": "sha512-2wU+HlTVrVce7BMW2b3Gd62btk8B0jBbuKYYzu3OFeBD/aZa88eHABtjcjQCdw3x+wvkIPEc56UsZx9eHYLebg==", - "peer": true, - "dependencies": { - "@algolia/client-common": "5.5.3" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/transporter": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", - "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", - "dependencies": { - "@algolia/cache-common": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", - "dependencies": { - "@babel/types": "^7.25.6", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", - "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", - "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", - "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-wrap-function": "^7.25.0", - "@babel/traverse": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", - "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", - "dependencies": { - "@babel/types": "^7.25.6" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", - "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", - "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", - "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", - "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", - "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", - "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", - "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", - "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", - "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", - "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/traverse": "^7.25.4", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", - "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", - "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", - "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", - "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", - "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", - "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", - "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", - "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.25.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", - "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", - "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.4.tgz", - "integrity": "sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", - "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", - "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", - "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", - "dependencies": { - "@babel/compat-data": "^7.25.4", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.25.0", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.25.4", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", - "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.24.7", - "@babel/plugin-transform-react-jsx-development": "^7.24.7", - "@babel/plugin-transform-react-pure-annotations": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", - "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.6.tgz", - "integrity": "sha512-Gz0Nrobx8szge6kQQ5Z5MX9L3ObqNwCQY1PSwSNzreFL7aHGxv8Fp2j3ETV6/wWdbiV+mW6OSm8oQhg3Tcsniw==", - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@docsearch/css": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", - "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" - }, - "node_modules/@docsearch/react": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", - "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", - "dependencies": { - "@algolia/autocomplete-core": "1.9.3", - "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.6.1", - "algoliasearch": "^4.19.1" - }, - "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0", - "search-insights": ">= 1 < 3" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "search-insights": { - "optional": true - } - } - }, - "node_modules/@docusaurus/core": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.5.2.tgz", - "integrity": "sha512-4Z1WkhCSkX4KO0Fw5m/Vuc7Q3NxBG53NE5u59Rs96fWkMPZVSrzEPP16/Nk6cWb/shK7xXPndTmalJtw7twL/w==", - "dependencies": { - "@babel/core": "^7.23.3", - "@babel/generator": "^7.23.3", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.22.9", - "@babel/preset-env": "^7.22.9", - "@babel/preset-react": "^7.22.5", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@babel/runtime-corejs3": "^7.22.6", - "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.5.2", - "@docusaurus/logger": "3.5.2", - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "autoprefixer": "^10.4.14", - "babel-loader": "^9.1.3", - "babel-plugin-dynamic-import-node": "^2.3.3", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "clean-css": "^5.3.2", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.31.1", - "css-loader": "^6.8.1", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "del": "^6.1.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "html-minifier-terser": "^7.2.0", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.5.3", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.7.6", - "p-map": "^4.0.0", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", - "react-helmet-async": "^1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "rtl-detect": "^1.0.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.5", - "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "url-loader": "^4.1.1", - "webpack": "^5.88.1", - "webpack-bundle-analyzer": "^4.9.0", - "webpack-dev-server": "^4.15.1", - "webpack-merge": "^5.9.0", - "webpackbar": "^5.0.2" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@mdx-js/react": "^3.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.5.2.tgz", - "integrity": "sha512-D3KiQXOMA8+O0tqORBrTOEQyQxNIfPm9jEaJoALjjSjc2M/ZAWcUfPQEnwr2JB2TadHw2gqWgpZckQmrVWkytA==", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/logger": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.5.2.tgz", - "integrity": "sha512-LHC540SGkeLfyT3RHK3gAMK6aS5TRqOD4R72BEU/DE2M/TY8WwEUAMY576UUc/oNJXv8pGhBmQB6N9p3pt8LQw==", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/mdx-loader": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.5.2.tgz", - "integrity": "sha512-ku3xO9vZdwpiMIVd8BzWV0DCqGEbCP5zs1iHfKX50vw6jX8vQo0ylYo1YJMZyz6e+JFJ17HYHT5FzVidz2IflA==", - "dependencies": { - "@docusaurus/logger": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^1.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/module-type-aliases": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.5.2.tgz", - "integrity": "sha512-Z+Xu3+2rvKef/YKTMxZHsEXp1y92ac0ngjDiExRdqGTmEKtCUpkbNYH8v5eXo5Ls+dnW88n6WTa+Q54kLOkwPg==", - "dependencies": { - "@docusaurus/types": "3.5.2", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.5.2.tgz", - "integrity": "sha512-R7ghWnMvjSf+aeNDH0K4fjyQnt5L0KzUEnUhmf1e3jZrv3wogeytZNN6n7X8yHcMsuZHPOrctQhXWnmxu+IRRg==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/logger": "3.5.2", - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/theme-common": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "cheerio": "1.0.0-rc.12", - "feed": "^4.2.2", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "reading-time": "^1.5.0", - "srcset": "^4.0.0", - "tslib": "^2.6.0", - "unist-util-visit": "^5.0.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.5.2.tgz", - "integrity": "sha512-Bt+OXn/CPtVqM3Di44vHjE7rPCEsRCB/DMo2qoOuozB9f7+lsdrHvD0QCHdBs0uhz6deYJDppAr2VgqybKPlVQ==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/logger": "3.5.2", - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/module-type-aliases": "3.5.2", - "@docusaurus/theme-common": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "@types/react-router-config": "^5.0.7", - "combine-promises": "^1.1.0", - "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.5.2.tgz", - "integrity": "sha512-WzhHjNpoQAUz/ueO10cnundRz+VUtkjFhhaQ9jApyv1a46FPURO4cef89pyNIOMny1fjDz/NUN2z6Yi+5WUrCw==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.5.2.tgz", - "integrity": "sha512-kBK6GlN0itCkrmHuCS6aX1wmoWc5wpd5KJlqQ1FyrF0cLDnvsYSnh7+ftdwzt7G6lGBho8lrVwkkL9/iQvaSOA==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^1.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.5.2.tgz", - "integrity": "sha512-rjEkJH/tJ8OXRE9bwhV2mb/WP93V441rD6XnM6MIluu7rk8qg38iSxS43ga2V2Q/2ib53PcqbDEJDG/yWQRJhQ==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.5.2.tgz", - "integrity": "sha512-lm8XL3xLkTPHFKKjLjEEAHUrW0SZBSHBE1I+i/tmYMBsjCcUB5UJ52geS5PSiOCFVR74tbPGcPHEV/gaaxFeSA==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "@types/gtag.js": "^0.0.12", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.5.2.tgz", - "integrity": "sha512-QkpX68PMOMu10Mvgvr5CfZAzZQFx8WLlOiUQ/Qmmcl6mjGK6H21WLT5x7xDmcpCoKA/3CegsqIqBR+nA137lQg==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.5.2.tgz", - "integrity": "sha512-DnlqYyRAdQ4NHY28TfHuVk414ft2uruP4QWCH//jzpHjqvKyXjj2fmDtI8RPUBh9K8iZKFMHRnLtzJKySPWvFA==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/logger": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.5.2.tgz", - "integrity": "sha512-3ihfXQ95aOHiLB5uCu+9PRy2gZCeSZoDcqpnDvf3B+sTrMvMTr8qRUzBvWkoIqc82yG5prCboRjk1SVILKx6sg==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/plugin-content-blog": "3.5.2", - "@docusaurus/plugin-content-docs": "3.5.2", - "@docusaurus/plugin-content-pages": "3.5.2", - "@docusaurus/plugin-debug": "3.5.2", - "@docusaurus/plugin-google-analytics": "3.5.2", - "@docusaurus/plugin-google-gtag": "3.5.2", - "@docusaurus/plugin-google-tag-manager": "3.5.2", - "@docusaurus/plugin-sitemap": "3.5.2", - "@docusaurus/theme-classic": "3.5.2", - "@docusaurus/theme-common": "3.5.2", - "@docusaurus/theme-search-algolia": "3.5.2", - "@docusaurus/types": "3.5.2" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-classic": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.5.2.tgz", - "integrity": "sha512-XRpinSix3NBv95Rk7xeMF9k4safMkwnpSgThn0UNQNumKvmcIYjfkwfh2BhwYh/BxMXQHJ/PdmNh22TQFpIaYg==", - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/module-type-aliases": "3.5.2", - "@docusaurus/plugin-content-blog": "3.5.2", - "@docusaurus/plugin-content-docs": "3.5.2", - "@docusaurus/plugin-content-pages": "3.5.2", - "@docusaurus/theme-common": "3.5.2", - "@docusaurus/theme-translations": "3.5.2", - "@docusaurus/types": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.44", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.4.26", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-common": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.5.2.tgz", - "integrity": "sha512-QXqlm9S6x9Ibwjs7I2yEDgsCocp708DrCrgHgKwg2n2AY0YQ6IjU0gAK35lHRLOvAoJUfCKpQAwUykB0R7+Eew==", - "dependencies": { - "@docusaurus/mdx-loader": "3.5.2", - "@docusaurus/module-type-aliases": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "clsx": "^2.0.0", - "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^2.3.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/plugin-content-docs": "*", - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.5.2.tgz", - "integrity": "sha512-qW53kp3VzMnEqZGjakaV90sst3iN1o32PH+nawv1uepROO8aEGxptcq2R5rsv7aBShSRbZwIobdvSYKsZ5pqvA==", - "dependencies": { - "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.5.2", - "@docusaurus/logger": "3.5.2", - "@docusaurus/plugin-content-docs": "3.5.2", - "@docusaurus/theme-common": "3.5.2", - "@docusaurus/theme-translations": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-validation": "3.5.2", - "algoliasearch": "^4.18.0", - "algoliasearch-helper": "^3.13.3", - "clsx": "^2.0.0", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-translations": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.5.2.tgz", - "integrity": "sha512-GPZLcu4aT1EmqSTmbdpVrDENGR2yObFEX8ssEFYTCiAIVc0EihNSdOIBTazUvgNqwvnoU1A8vIs1xyzc3LITTw==", - "dependencies": { - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/types": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.5.2.tgz", - "integrity": "sha512-N6GntLXoLVUwkZw7zCxwy9QiuEXIcTVzA9AkmNw16oc0AP3SXLrMmDMMBIfgqwuKWa6Ox6epHol9kMtJqekACw==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/utils": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.5.2.tgz", - "integrity": "sha512-33QvcNFh+Gv+C2dP9Y9xWEzMgf3JzrpL2nW9PopidiohS1nDcyknKRx2DWaFvyVTTYIkkABVSr073VTj/NITNA==", - "dependencies": { - "@docusaurus/logger": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "@svgr/webpack": "^8.1.0", - "escape-string-regexp": "^4.0.0", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-common": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.5.2.tgz", - "integrity": "sha512-i0AZjHiRgJU6d7faQngIhuHKNrszpL/SHQPgF1zH4H+Ij6E9NBYGy6pkcGWToIv7IVPbs+pQLh1P3whn0gWXVg==", - "dependencies": { - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-validation": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.5.2.tgz", - "integrity": "sha512-m+Foq7augzXqB6HufdS139PFxDC5d5q2QKZy8q0qYYvGdI6nnlNsGH4cIGsgBnV7smz+mopl3g4asbSDvMV0jA==", - "dependencies": { - "@docusaurus/logger": "3.5.2", - "@docusaurus/utils": "3.5.2", - "@docusaurus/utils-common": "3.5.2", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" - }, - "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==" - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@slorber/remark-comment": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", - "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.1.0", - "micromark-util-symbol": "^1.0.1" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/gtag.js": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.15", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", - "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" - }, - "node_modules/@types/node": { - "version": "22.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.0.tgz", - "integrity": "sha512-QyR8d5bmq+eR72TwQDfujwShHMcIrWIYsaQFtXRE58MHPTEKUNxjxvl0yS0qPMds5xbSDWtp7ZpvGFtd7dfMdQ==", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prismjs": { - "version": "1.26.4", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", - "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" - }, - "node_modules/@types/qs": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", - "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "node_modules/@types/react": { - "version": "18.3.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.8.tgz", - "integrity": "sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" - } - }, - "node_modules/@types/react-router-config": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", - "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "^5.1.0" - } - }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, - "node_modules/@types/sax": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", - "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" - }, - "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/algoliasearch": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", - "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-account": "4.24.0", - "@algolia/client-analytics": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-personalization": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/recommend": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch-helper": { - "version": "3.22.5", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.5.tgz", - "integrity": "sha512-lWvhdnc+aKOKx8jyA3bsdEgHzm/sglC4cYdMG4xSQyRiPLJVJtH/IVYZG3Hp6PkTEhQqhyVYkeP9z2IlcHJsWw==", - "dependencies": { - "@algolia/events": "^4.0.1" - }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 6" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/client-common": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", - "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", - "dependencies": { - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/client-search": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", - "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", - "dependencies": { - "@algolia/client-common": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/transporter": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", - "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", - "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", - "dependencies": { - "@algolia/requester-common": "4.24.0" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/astring": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", - "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", - "bin": { - "astring": "bin/astring" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/babel-loader": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", - "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", - "dependencies": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/boxen": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", - "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^6.2.0", - "chalk": "^4.1.2", - "cli-boxes": "^3.0.0", - "string-width": "^5.0.1", - "type-fest": "^2.5.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001663", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", - "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/collapse-white-space": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", - "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "node_modules/combine-promises": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", - "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compressible/node_modules/mime-db": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", - "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/configstore": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", - "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", - "dependencies": { - "dot-prop": "^6.0.1", - "graceful-fs": "^4.2.6", - "unique-string": "^3.0.0", - "write-file-atomic": "^3.0.3", - "xdg-basedir": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/yeoman/configstore?sponsor=1" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" - }, - "node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/copy-text-to-clipboard": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", - "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dependencies": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/core-js": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", - "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", - "dependencies": { - "browserslist": "^4.23.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-pure": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", - "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-declaration-sorter": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", - "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", - "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "cssnano": "^6.0.1", - "jest-worker": "^29.4.3", - "postcss": "^8.4.24", - "schema-utils": "^4.0.1", - "serialize-javascript": "^6.0.1" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "lightningcss": { - "optional": true - } - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", - "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", - "dependencies": { - "cssnano-preset-default": "^6.1.2", - "lilconfig": "^3.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-preset-advanced": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", - "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", - "dependencies": { - "autoprefixer": "^10.4.19", - "browserslist": "^4.23.0", - "cssnano-preset-default": "^6.1.2", - "postcss-discard-unused": "^6.0.5", - "postcss-merge-idents": "^6.0.3", - "postcss-reduce-idents": "^6.0.3", - "postcss-zindex": "^6.0.2" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-preset-default": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", - "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", - "dependencies": { - "browserslist": "^4.23.0", - "css-declaration-sorter": "^7.2.0", - "cssnano-utils": "^4.0.2", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.1.0", - "postcss-convert-values": "^6.1.0", - "postcss-discard-comments": "^6.0.2", - "postcss-discard-duplicates": "^6.0.3", - "postcss-discard-empty": "^6.0.3", - "postcss-discard-overridden": "^6.0.2", - "postcss-merge-longhand": "^6.0.5", - "postcss-merge-rules": "^6.1.1", - "postcss-minify-font-values": "^6.1.0", - "postcss-minify-gradients": "^6.0.3", - "postcss-minify-params": "^6.1.0", - "postcss-minify-selectors": "^6.0.4", - "postcss-normalize-charset": "^6.0.2", - "postcss-normalize-display-values": "^6.0.2", - "postcss-normalize-positions": "^6.0.2", - "postcss-normalize-repeat-style": "^6.0.2", - "postcss-normalize-string": "^6.0.2", - "postcss-normalize-timing-functions": "^6.0.2", - "postcss-normalize-unicode": "^6.1.0", - "postcss-normalize-url": "^6.0.2", - "postcss-normalize-whitespace": "^6.0.2", - "postcss-ordered-values": "^6.0.2", - "postcss-reduce-initial": "^6.1.0", - "postcss-reduce-transforms": "^6.0.2", - "postcss-svgo": "^6.0.3", - "postcss-unique-selectors": "^6.0.4" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-utils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", - "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "node_modules/detect-port": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", - "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dot-prop/node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", - "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/emojilib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", - "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/emoticon": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.1.0.tgz", - "integrity": "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", - "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-util-attach-comments": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", - "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", - "dependencies": { - "@types/estree": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-build-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", - "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-walker": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-to-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", - "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-value-to-estree": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.2.tgz", - "integrity": "sha512-S0gW2+XZkmsx00tU2uJ4L9hUT7IFabbml9pHh2WQqFmAbxit++YGZne0sKJbNwkj9Wvg9E4uqWl4nCIFQMmfag==", - "dependencies": { - "@types/estree": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/remcohaszing" - } - }, - "node_modules/estree-util-visit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", - "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eta": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", - "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "url": "https://github.com/eta-dev/eta?sponsor=1" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eval": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", - "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", - "dependencies": { - "@types/node": "*", - "require-like": ">= 0.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" - }, - "node_modules/express/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fault": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", - "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", - "dependencies": { - "format": "^0.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/feed": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", - "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", - "dependencies": { - "xml-js": "^1.6.11" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/file-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/file-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/file-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/file-loader/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/github-slugger": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", - "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/got/node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/gray-matter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-yarn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", - "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", - "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-estree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", - "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-attach-comments": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.4.0", - "unist-util-position": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", - "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", - "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", - "dependencies": { - "inline-style-parser": "0.2.4" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "node_modules/html-minifier-terser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", - "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "~5.3.2", - "commander": "^10.0.0", - "entities": "^4.4.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.15.1" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" - } - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/html-webpack-plugin/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", - "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=16.x" - } - }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/infima": { - "version": "0.2.0-alpha.44", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.44.tgz", - "integrity": "sha512-tuRkUSO/lB3rEhLJk25atwAjgLuzq070+pOW8XcvpHky/YbENnRRdPd85IBkyeTgttmOy5ah+yHYsK1HhUd4lQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-reference": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", - "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-yarn-global": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", - "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", - "dependencies": { - "package-json": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/markdown-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", - "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", - "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", - "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-frontmatter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", - "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "escape-string-regexp": "^5.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-extension-frontmatter": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", - "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", - "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", - "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", - "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", - "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-directive": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", - "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-frontmatter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", - "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", - "dependencies": { - "fault": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", - "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-mdx-expression": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", - "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-mdx-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz", - "integrity": "sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==", - "dependencies": { - "@types/acorn": "^4.0.0", - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-extension-mdx-md": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", - "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", - "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", - "dependencies": { - "acorn": "^8.0.0", - "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^3.0.0", - "micromark-extension-mdx-jsx": "^3.0.0", - "micromark-extension-mdx-md": "^2.0.0", - "micromark-extension-mdxjs-esm": "^3.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs-esm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", - "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", - "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", - "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-mdx-expression": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.2.tgz", - "integrity": "sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, - "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-space/node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-title": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", - "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", - "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-character/node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", - "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", - "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", - "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", - "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", - "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-events-to-acorn": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", - "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/acorn": "^4.0.0", - "@types/estree": "^1.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, - "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", - "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", - "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", - "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", - "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark/node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark/node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dependencies": { - "mime-db": "~1.33.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz", - "integrity": "sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==", - "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-emoji": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", - "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", - "dependencies": { - "@sindresorhus/is": "^4.6.0", - "char-regex": "^1.0.2", - "emojilib": "^2.4.0", - "skin-tone": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", - "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", - "dependencies": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-entities": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", - "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-numeric-range": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/periscopic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", - "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0" - } - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dependencies": { - "find-up": "^6.3.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", - "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-api": "^3.0.0", - "colord": "^2.9.3", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-convert-values": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", - "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", - "dependencies": { - "browserslist": "^4.23.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-comments": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", - "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", - "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-empty": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", - "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", - "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-unused": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", - "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", - "dependencies": { - "postcss-selector-parser": "^6.0.16" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-loader": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", - "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", - "dependencies": { - "cosmiconfig": "^8.3.5", - "jiti": "^1.20.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-merge-idents": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", - "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", - "dependencies": { - "cssnano-utils": "^4.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", - "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.1.1" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-rules": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", - "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^4.0.2", - "postcss-selector-parser": "^6.0.16" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", - "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", - "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", - "dependencies": { - "colord": "^2.9.3", - "cssnano-utils": "^4.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-params": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", - "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", - "dependencies": { - "browserslist": "^4.23.0", - "cssnano-utils": "^4.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", - "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.16" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", - "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", - "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", - "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", - "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-string": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", - "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", - "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", - "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", - "dependencies": { - "browserslist": "^4.23.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-url": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", - "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", - "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-ordered-values": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", - "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", - "dependencies": { - "cssnano-utils": "^4.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-idents": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", - "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", - "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", - "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-sort-media-queries": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", - "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", - "dependencies": { - "sort-css-media-queries": "2.2.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.4.23" - } - }, - "node_modules/postcss-svgo": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", - "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^3.2.0" - }, - "engines": { - "node": "^14 || ^16 || >= 18" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", - "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", - "dependencies": { - "postcss-selector-parser": "^6.0.16" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/postcss-zindex": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", - "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", - "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/prism-react-renderer": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.0.tgz", - "integrity": "sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw==", - "dependencies": { - "@types/prismjs": "^1.26.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.0.0" - } - }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "node_modules/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", - "dependencies": { - "escape-goat": "^4.0.0" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dependencies": { - "inherits": "~2.0.3" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-dev-utils/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/react-dev-utils/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-dev-utils/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" - }, - "node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" - }, - "node_modules/react-helmet-async": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", - "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "invariant": "^2.2.4", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.2.0", - "shallowequal": "^1.1.0" - }, - "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-json-view-lite": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", - "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-loadable": { - "name": "@docusaurus/react-loadable", - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", - "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", - "dependencies": { - "@types/react": "*" - }, - "peerDependencies": { - "react": "*" - } - }, - "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", - "dependencies": { - "@babel/runtime": "^7.10.3" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "react-loadable": "*", - "webpack": ">=4.41.1 || 5.x" - } - }, - "node_modules/react-router": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", - "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", - "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router-config": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", - "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", - "dependencies": { - "@babel/runtime": "^7.1.2" - }, - "peerDependencies": { - "react": ">=15", - "react-router": ">=5" - } - }, - "node_modules/react-router-dom": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", - "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", - "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.3.4", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dependencies": { - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remark-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", - "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-directive": "^3.0.0", - "micromark-extension-directive": "^3.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-emoji": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", - "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", - "dependencies": { - "@types/mdast": "^4.0.2", - "emoticon": "^4.0.1", - "mdast-util-find-and-replace": "^3.0.1", - "node-emoji": "^2.1.0", - "unified": "^11.0.4" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/remark-frontmatter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", - "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-frontmatter": "^2.0.0", - "micromark-extension-frontmatter": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", - "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", - "dependencies": { - "mdast-util-mdx": "^3.0.0", - "micromark-extension-mdxjs": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", - "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/renderkid/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/renderkid/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/renderkid/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/renderkid/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/renderkid/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/renderkid/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-like": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", - "engines": { - "node": "*" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rtl-detect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", - "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" - }, - "node_modules/rtlcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", - "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0", - "postcss": "^8.4.21", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "rtlcss": "bin/rtlcss.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/search-insights": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.2.tgz", - "integrity": "sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==", - "peer": true - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", - "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", - "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" - } - }, - "node_modules/serve-handler/node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/sitemap": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", - "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", - "dependencies": { - "@types/node": "^17.0.5", - "@types/sax": "^1.2.1", - "arg": "^5.0.0", - "sax": "^1.2.4" - }, - "bin": { - "sitemap": "dist/cli.js" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=5.6.0" - } - }, - "node_modules/sitemap/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" - }, - "node_modules/skin-tone": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", - "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", - "dependencies": { - "unicode-emoji-modifier-base": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/sort-css-media-queries": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", - "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", - "engines": { - "node": ">= 6.3.0" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/srcset": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", - "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-to-object": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", - "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", - "dependencies": { - "inline-style-parser": "0.1.1" - } - }, - "node_modules/stylehacks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", - "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", - "dependencies": { - "browserslist": "^4.23.0", - "postcss-selector-parser": "^6.0.16" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", - "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-emoji-modifier-base": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", - "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", - "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-notifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", - "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", - "dependencies": { - "boxen": "^7.0.0", - "chalk": "^5.0.1", - "configstore": "^6.0.0", - "has-yarn": "^3.0.0", - "import-lazy": "^4.0.0", - "is-ci": "^3.0.1", - "is-installed-globally": "^0.4.0", - "is-npm": "^6.0.0", - "is-yarn-global": "^0.4.0", - "latest-version": "^7.0.0", - "pupa": "^3.1.0", - "semver": "^7.3.7", - "semver-diff": "^4.0.0", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/boxen": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", - "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.1", - "chalk": "^5.2.0", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/update-notifier/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", - "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } - } - }, - "node_modules/url-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/url-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/url-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/url-loader/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/url-loader/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/url-loader/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" - }, - "node_modules/utility-types": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", - "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", - "dependencies": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.10.2", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", - "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", - "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "html-escaper": "^2.0.2", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-middleware/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/webpack/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpackbar": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", - "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.3", - "pretty-time": "^1.1.0", - "std-env": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "webpack": "3 || 4 || 5" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", - "dependencies": { - "sax": "^1.2.4" - }, - "bin": { - "xml-js": "bin/cli.js" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/quickjs-ng/docs/package.json b/quickjs-ng/docs/package.json deleted file mode 100644 index 4acf04c..0000000 --- a/quickjs-ng/docs/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "private": true, - "scripts": { - "docusaurus": "docusaurus", - "start": "docusaurus start", - "build": "docusaurus build", - "swizzle": "docusaurus swizzle", - "deploy": "docusaurus deploy", - "clear": "docusaurus clear", - "serve": "docusaurus serve", - "write-translations": "docusaurus write-translations", - "write-heading-ids": "docusaurus write-heading-ids" - }, - "dependencies": { - "@docusaurus/core": "3.5.2", - "@docusaurus/preset-classic": "3.5.2", - "@mdx-js/react": "3.0.1", - "clsx": "2.1.1", - "prism-react-renderer": "2.4.0", - "react": "18.3.1", - "react-dom": "18.3.1" - }, - "devDependencies": { - "@docusaurus/module-type-aliases": "3.5.2", - "@docusaurus/types": "3.5.2" - }, - "browserslist": { - "production": [ - ">0.5%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 3 chrome version", - "last 3 firefox version", - "last 5 safari version" - ] - }, - "engines": { - "node": ">=18.0" - } -} diff --git a/quickjs-ng/docs/sidebars.js b/quickjs-ng/docs/sidebars.js deleted file mode 100644 index 3efb4ff..0000000 --- a/quickjs-ng/docs/sidebars.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ - -// @ts-check - -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const sidebars = { - // By default, Docusaurus generates a sidebar from the docs folder structure - docsSidebar: [{type: 'autogenerated', dirName: '.'}], -}; - -export default sidebars; diff --git a/quickjs-ng/docs/src/css/custom.css b/quickjs-ng/docs/src/css/custom.css deleted file mode 100644 index 2bc6a4c..0000000 --- a/quickjs-ng/docs/src/css/custom.css +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. - */ - -/* You can override the default Infima variables here. */ -:root { - --ifm-color-primary: #2e8555; - --ifm-color-primary-dark: #29784c; - --ifm-color-primary-darker: #277148; - --ifm-color-primary-darkest: #205d3b; - --ifm-color-primary-light: #33925d; - --ifm-color-primary-lighter: #359962; - --ifm-color-primary-lightest: #3cad6e; - --ifm-code-font-size: 95%; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); -} - -/* For readability concerns, you should choose a lighter palette in dark mode. */ -[data-theme='dark'] { - --ifm-color-primary: #25c2a0; - --ifm-color-primary-dark: #21af90; - --ifm-color-primary-darker: #1fa588; - --ifm-color-primary-darkest: #1a8870; - --ifm-color-primary-light: #29d5b0; - --ifm-color-primary-lighter: #32d8b4; - --ifm-color-primary-lightest: #4fddbf; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); -} diff --git a/quickjs-ng/docs/static/img/favicon.ico b/quickjs-ng/docs/static/img/favicon.ico deleted file mode 100644 index c01d54b..0000000 Binary files a/quickjs-ng/docs/static/img/favicon.ico and /dev/null differ diff --git a/quickjs-ng/examples/meson.build b/quickjs-ng/examples/meson.build deleted file mode 100644 index 08c9d87..0000000 --- a/quickjs-ng/examples/meson.build +++ /dev/null @@ -1,19 +0,0 @@ -shared_module( - 'fib', - 'fib.c', - - name_prefix: '', - gnu_symbol_visibility: 'default', - c_args: ['-DJS_SHARED_LIBRARY'], - dependencies: host_system == 'windows' ? qjs_dep : [], -) - -shared_module( - 'point', - 'point.c', - - name_prefix: '', - gnu_symbol_visibility: 'default', - c_args: ['-DJS_SHARED_LIBRARY'], - dependencies: host_system == 'windows' ? qjs_dep : [], -) diff --git a/quickjs-ng/examples/test_fib.js b/quickjs-ng/examples/test_fib.js deleted file mode 100644 index f22c576..0000000 --- a/quickjs-ng/examples/test_fib.js +++ /dev/null @@ -1,8 +0,0 @@ -/* example of JS module importing a C module */ -import * as os from "qjs:os"; - -const isWin = os.platform === 'win32'; -const { fib } = await import(`./fib.${isWin ? 'dll' : 'so'}`); - -console.log("Hello World"); -console.log("fib(10)=", fib(10)); diff --git a/quickjs-ng/fuzz.c b/quickjs-ng/fuzz.c deleted file mode 100644 index fca8fa4..0000000 --- a/quickjs-ng/fuzz.c +++ /dev/null @@ -1,22 +0,0 @@ -// clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c -#include "quickjs.h" -#include "quickjs.c" -#include "cutils.c" -#include "libregexp.c" -#include "libunicode.c" -#include - -int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) -{ - JSRuntime *rt = JS_NewRuntime(); - if (!rt) - exit(1); - JSContext *ctx = JS_NewContext(rt); - if (!ctx) - exit(1); - JSValue val = JS_ReadObject(ctx, buf, len, /*flags*/0); - JS_FreeValue(ctx, val); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return 0; -} diff --git a/quickjs-ng/gen/function_source.c b/quickjs-ng/gen/function_source.c deleted file mode 100644 index b518a78..0000000 --- a/quickjs-ng/gen/function_source.c +++ /dev/null @@ -1,80 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include "quickjs-libc.h" - -const uint32_t qjsc_function_source_size = 324; - -const uint8_t qjsc_function_source[324] = { - 0x15, 0x05, 0x01, 0x30, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x0c, 0x61, 0x63, - 0x74, 0x75, 0x61, 0x6c, 0x01, 0x02, 0x66, 0x01, - 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x01, - 0x34, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34, - 0x32, 0x20, 0x7d, 0x0d, 0xc6, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x20, 0x0a, 0x01, 0xa2, - 0x01, 0x00, 0x05, 0x00, 0x03, 0x02, 0x01, 0x74, - 0x05, 0xc8, 0x03, 0x02, 0x00, 0x30, 0xca, 0x03, - 0x04, 0x00, 0x70, 0xc8, 0x03, 0x04, 0x02, 0x70, - 0x10, 0x00, 0x01, 0x00, 0xe4, 0x01, 0x00, 0x01, - 0x00, 0xcc, 0x03, 0x00, 0x0d, 0xca, 0x03, 0x01, - 0x01, 0x0c, 0x43, 0x0a, 0x01, 0xca, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0xbe, - 0x2a, 0x28, 0xc6, 0x03, 0x03, 0x01, 0x00, 0x1a, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34, 0x32, - 0x20, 0x7d, 0x0c, 0x03, 0xc4, 0x04, 0x08, 0xce, - 0x08, 0xec, 0x05, 0xc1, 0x00, 0xe4, 0x29, 0x04, - 0xe7, 0x00, 0x00, 0x00, 0xe3, 0x62, 0x00, 0x00, - 0xe0, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00, - 0x00, 0xcb, 0x63, 0x00, 0x00, 0x66, 0x00, 0x00, - 0xb0, 0xec, 0x0b, 0x39, 0x96, 0x00, 0x00, 0x00, - 0x63, 0x00, 0x00, 0xf1, 0x30, 0x62, 0x02, 0x00, - 0x62, 0x01, 0x00, 0x39, 0x3b, 0x00, 0x00, 0x00, - 0x66, 0x00, 0x00, 0x04, 0xe5, 0x00, 0x00, 0x00, - 0x9e, 0x32, 0x01, 0x00, 0x03, 0x00, 0xcc, 0x63, - 0x01, 0x00, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, - 0x00, 0x00, 0xcd, 0x63, 0x02, 0x00, 0x66, 0x00, - 0x00, 0xb0, 0xec, 0x0b, 0x39, 0x96, 0x00, 0x00, - 0x00, 0x63, 0x02, 0x00, 0xf1, 0x30, 0x69, 0x02, - 0x00, 0x69, 0x01, 0x00, 0x06, 0x2f, 0xc6, 0x03, - 0x01, 0x01, 0x18, 0x00, 0x1c, 0x0a, 0x2a, 0x26, - 0x03, 0x20, 0x1c, 0x1b, 0x0c, 0x00, 0x10, 0x08, - 0x27, 0x11, 0x12, 0x67, 0x0d, 0x26, 0x03, 0x20, - 0x1c, 0x1b, 0x0c, 0x00, -}; - -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx = JS_NewContext(rt); - if (!ctx) - return NULL; - return ctx; -} - -int main(int argc, char **argv) -{ - int r; - JSRuntime *rt; - JSContext *ctx; - r = 0; - rt = JS_NewRuntime(); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - ctx = JS_NewCustomContext(rt); - js_std_add_helpers(ctx, argc, argv); - js_std_eval_binary(ctx, qjsc_function_source, qjsc_function_source_size, 0); - r = js_std_loop(ctx); - if (r) { - js_std_dump_error(ctx); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return r; -} diff --git a/quickjs-ng/gen/hello.c b/quickjs-ng/gen/hello.c deleted file mode 100644 index 27dcd5d..0000000 --- a/quickjs-ng/gen/hello.c +++ /dev/null @@ -1,52 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include "quickjs-libc.h" - -const uint32_t qjsc_hello_size = 103; - -const uint8_t qjsc_hello[103] = { - 0x15, 0x04, 0x01, 0x22, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, - 0x6c, 0x6f, 0x2e, 0x6a, 0x73, 0x01, 0x0e, 0x63, - 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x01, 0x06, - 0x6c, 0x6f, 0x67, 0x01, 0x16, 0x48, 0x65, 0x6c, - 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, - 0x0d, 0xc6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x20, 0x0a, 0x01, 0xa2, 0x01, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x19, 0x00, 0x08, 0xec, - 0x02, 0x29, 0x39, 0xe4, 0x00, 0x00, 0x00, 0x43, - 0xe5, 0x00, 0x00, 0x00, 0x04, 0xe6, 0x00, 0x00, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0x06, 0x2f, 0xc6, - 0x03, 0x01, 0x01, 0x02, 0x48, 0x0e, 0x00, -}; - -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx = JS_NewContext(rt); - if (!ctx) - return NULL; - return ctx; -} - -int main(int argc, char **argv) -{ - int r; - JSRuntime *rt; - JSContext *ctx; - r = 0; - rt = JS_NewRuntime(); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - ctx = JS_NewCustomContext(rt); - js_std_add_helpers(ctx, argc, argv); - js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0); - r = js_std_loop(ctx); - if (r) { - js_std_dump_error(ctx); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return r; -} diff --git a/quickjs-ng/gen/hello_module.c b/quickjs-ng/gen/hello_module.c deleted file mode 100644 index 2eb98fc..0000000 --- a/quickjs-ng/gen/hello_module.c +++ /dev/null @@ -1,106 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include "quickjs-libc.h" - -const uint32_t qjsc_fib_module_size = 290; - -const uint8_t qjsc_fib_module[290] = { - 0x15, 0x03, 0x01, 0x2c, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62, - 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, - 0x6a, 0x73, 0x01, 0x06, 0x66, 0x69, 0x62, 0x01, - 0x02, 0x6e, 0x0d, 0xc6, 0x03, 0x00, 0x01, 0x00, - 0x00, 0xc8, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x20, - 0x0a, 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x09, 0x00, 0xc8, 0x03, 0x00, 0x01, - 0x0c, 0x43, 0x0a, 0x01, 0xc8, 0x03, 0x01, 0x00, - 0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xca, 0x03, - 0x00, 0x01, 0x00, 0xc8, 0x03, 0x00, 0x00, 0xd3, - 0xb6, 0xa8, 0xec, 0x03, 0xb6, 0x28, 0xd3, 0xb7, - 0xad, 0xec, 0x03, 0xb7, 0x28, 0xdf, 0xd3, 0xb7, - 0x9f, 0xf1, 0xdf, 0xd3, 0xb8, 0x9f, 0xf1, 0x9e, - 0x28, 0xc6, 0x03, 0x02, 0x08, 0x0e, 0x09, 0x0c, - 0x27, 0x0a, 0x28, 0x02, 0x07, 0x08, 0x11, 0x0a, - 0x07, 0x08, 0x07, 0x08, 0x8d, 0x01, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, - 0x69, 0x62, 0x28, 0x6e, 0x29, 0x0a, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, - 0x6e, 0x20, 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, - 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, - 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x29, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, - 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x66, 0x69, 0x62, 0x28, 0x6e, 0x20, 0x2d, - 0x20, 0x31, 0x29, 0x20, 0x2b, 0x20, 0x66, 0x69, - 0x62, 0x28, 0x6e, 0x20, 0x2d, 0x20, 0x32, 0x29, - 0x3b, 0x0a, 0x7d, 0x08, 0xec, 0x05, 0xc1, 0x00, - 0xe3, 0x29, 0x06, 0x2f, 0xc6, 0x03, 0x01, 0x01, - 0x00, 0x00, -}; - -const uint32_t qjsc_hello_module_size = 187; - -const uint8_t qjsc_hello_module[187] = { - 0x15, 0x07, 0x01, 0x30, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, - 0x6c, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x1e, 0x2e, 0x2f, - 0x66, 0x69, 0x62, 0x5f, 0x6d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x06, 0x66, - 0x69, 0x62, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73, - 0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67, - 0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, - 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66, - 0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d, - 0xc6, 0x03, 0x01, 0xc8, 0x03, 0x00, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x00, 0x00, 0x0c, 0x20, 0x0a, - 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, - 0x00, 0x32, 0x00, 0xca, 0x03, 0x00, 0x0c, 0x08, - 0xec, 0x02, 0x29, 0x39, 0xe6, 0x00, 0x00, 0x00, - 0x43, 0xe7, 0x00, 0x00, 0x00, 0x04, 0xe8, 0x00, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0xe6, - 0x00, 0x00, 0x00, 0x43, 0xe7, 0x00, 0x00, 0x00, - 0x04, 0xe9, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, - 0xbe, 0x0a, 0xf1, 0x24, 0x02, 0x00, 0x0e, 0x06, - 0x2f, 0xc6, 0x03, 0x01, 0x01, 0x0c, 0x00, 0x04, - 0x08, 0x00, 0x34, 0x10, 0x30, 0x0f, 0x34, 0x10, - 0x2a, 0x20, 0x00, -}; - -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx = JS_NewContext(rt); - if (!ctx) - return NULL; - js_std_eval_binary(ctx, qjsc_fib_module, qjsc_fib_module_size, 1); - return ctx; -} - -int main(int argc, char **argv) -{ - int r; - JSRuntime *rt; - JSContext *ctx; - r = 0; - rt = JS_NewRuntime(); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - ctx = JS_NewCustomContext(rt); - js_std_add_helpers(ctx, argc, argv); - js_std_eval_binary(ctx, qjsc_hello_module, qjsc_hello_module_size, 0); - r = js_std_loop(ctx); - if (r) { - js_std_dump_error(ctx); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return r; -} diff --git a/quickjs-ng/gen/repl.c b/quickjs-ng/gen/repl.c deleted file mode 100644 index 53b4664..0000000 --- a/quickjs-ng/gen/repl.c +++ /dev/null @@ -1,2929 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include - -const uint32_t qjsc_repl_size = 23360; - -const uint8_t qjsc_repl[23360] = { - 0x15, 0x96, 0x04, 0x01, 0x0e, 0x72, 0x65, 0x70, - 0x6c, 0x2e, 0x6a, 0x73, 0x01, 0x0e, 0x71, 0x6a, - 0x73, 0x3a, 0x73, 0x74, 0x64, 0x01, 0x0c, 0x71, - 0x6a, 0x73, 0x3a, 0x6f, 0x73, 0x01, 0x12, 0x71, - 0x6a, 0x73, 0x3a, 0x62, 0x6a, 0x73, 0x6f, 0x6e, - 0x01, 0x06, 0x73, 0x74, 0x64, 0x01, 0x04, 0x6f, - 0x73, 0x01, 0x0a, 0x62, 0x6a, 0x73, 0x6f, 0x6e, - 0x01, 0x02, 0x67, 0x01, 0x10, 0x69, 0x73, 0x46, - 0x69, 0x6e, 0x69, 0x74, 0x65, 0x01, 0x0a, 0x69, - 0x73, 0x4e, 0x61, 0x4e, 0x01, 0x10, 0x49, 0x6e, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x01, 0x0e, - 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x01, - 0x0c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x01, - 0x0c, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x01, - 0x0c, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x01, - 0x08, 0x75, 0x74, 0x66, 0x38, 0x01, 0x12, 0x73, - 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x01, 0x16, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, - 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x01, 0x16, 0x73, - 0x68, 0x6f, 0x77, 0x5f, 0x68, 0x69, 0x64, 0x64, - 0x65, 0x6e, 0x01, 0x14, 0x73, 0x68, 0x6f, 0x77, - 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x01, 0x10, - 0x68, 0x65, 0x78, 0x5f, 0x6d, 0x6f, 0x64, 0x65, - 0x01, 0x14, 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, - 0x72, 0x69, 0x63, 0x74, 0x01, 0x0e, 0x68, 0x69, - 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, 0x1a, 0x68, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x01, 0x14, 0x63, 0x6c, - 0x69, 0x70, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x01, 0x0c, 0x70, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x01, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, - 0x01, 0x08, 0x70, 0x6c, 0x65, 0x6e, 0x01, 0x06, - 0x70, 0x73, 0x31, 0x01, 0x06, 0x70, 0x73, 0x32, - 0x01, 0x1e, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x01, 0x12, 0x65, 0x76, 0x61, 0x6c, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x01, 0x0a, 0x6d, 0x65, - 0x78, 0x70, 0x72, 0x01, 0x0a, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x01, 0x06, 0x63, 0x6d, 0x64, 0x01, - 0x14, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x5f, - 0x70, 0x6f, 0x73, 0x01, 0x10, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x63, 0x6d, 0x64, 0x01, 0x1e, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, - 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x73, 0x01, 0x10, - 0x74, 0x68, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, - 0x01, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, - 0x75, 0x6e, 0x01, 0x14, 0x71, 0x75, 0x6f, 0x74, - 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x01, 0x14, - 0x75, 0x74, 0x66, 0x38, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x01, 0x10, 0x75, 0x74, 0x66, 0x38, - 0x5f, 0x76, 0x61, 0x6c, 0x01, 0x0e, 0x74, 0x65, - 0x72, 0x6d, 0x5f, 0x66, 0x64, 0x01, 0x1a, 0x74, - 0x65, 0x72, 0x6d, 0x5f, 0x72, 0x65, 0x61, 0x64, - 0x5f, 0x62, 0x75, 0x66, 0x01, 0x14, 0x74, 0x65, - 0x72, 0x6d, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x01, 0x1a, 0x74, 0x65, 0x72, 0x6d, 0x5f, 0x63, - 0x75, 0x72, 0x73, 0x6f, 0x72, 0x5f, 0x78, 0x01, - 0x10, 0x74, 0x65, 0x72, 0x6d, 0x49, 0x6e, 0x69, - 0x74, 0x01, 0x1c, 0x73, 0x69, 0x67, 0x69, 0x6e, - 0x74, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x72, 0x01, 0x22, 0x74, 0x65, 0x72, 0x6d, 0x5f, - 0x72, 0x65, 0x61, 0x64, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x72, 0x01, 0x16, 0x68, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x01, 0x10, 0x69, 0x73, 0x5f, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x01, 0x10, 0x69, 0x73, 0x5f, - 0x64, 0x69, 0x67, 0x69, 0x74, 0x01, 0x0e, 0x69, - 0x73, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x14, - 0x75, 0x63, 0x73, 0x5f, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x01, 0x2a, 0x69, 0x73, 0x5f, 0x74, - 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x75, 0x72, 0x72, 0x6f, 0x67, 0x61, 0x74, - 0x65, 0x01, 0x16, 0x69, 0x73, 0x5f, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x01, 0x20, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x5f, 0x74, 0x65, 0x78, 0x74, - 0x01, 0x12, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, - 0x63, 0x73, 0x69, 0x01, 0x16, 0x6d, 0x6f, 0x76, - 0x65, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x01, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x01, 0x0c, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, - 0x01, 0x1a, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x64, - 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x01, - 0x0a, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x01, 0x0a, - 0x61, 0x6c, 0x65, 0x72, 0x74, 0x01, 0x22, 0x62, - 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, - 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, 0x6e, 0x65, - 0x01, 0x16, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, - 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x01, 0x18, 0x66, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, - 0x68, 0x61, 0x72, 0x01, 0x1a, 0x62, 0x61, 0x63, - 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x68, - 0x61, 0x72, 0x01, 0x22, 0x73, 0x6b, 0x69, 0x70, - 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x66, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x01, 0x24, 0x73, - 0x6b, 0x69, 0x70, 0x5f, 0x77, 0x6f, 0x72, 0x64, - 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, - 0x64, 0x01, 0x18, 0x66, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, - 0x1a, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, - 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x18, - 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x73, 0x63, - 0x72, 0x65, 0x65, 0x6e, 0x01, 0x16, 0x61, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x5f, 0x6c, 0x69, 0x6e, - 0x65, 0x01, 0x16, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x01, 0x20, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x01, 0x18, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, 0x1c, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, - 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x01, 0x2e, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, - 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, - 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0x01, - 0x2c, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, - 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x01, - 0x1e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, - 0x63, 0x68, 0x61, 0x72, 0x5f, 0x64, 0x69, 0x72, - 0x01, 0x16, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x5f, 0x63, 0x68, 0x61, 0x72, 0x01, 0x12, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x64, - 0x01, 0x28, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, - 0x72, 0x64, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x01, 0x1e, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, - 0x65, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x01, - 0x1e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, - 0x73, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x73, - 0x01, 0x16, 0x75, 0x70, 0x63, 0x61, 0x73, 0x65, - 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x1a, 0x64, - 0x6f, 0x77, 0x6e, 0x63, 0x61, 0x73, 0x65, 0x5f, - 0x77, 0x6f, 0x72, 0x64, 0x01, 0x16, 0x6b, 0x69, - 0x6c, 0x6c, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x01, 0x12, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, - 0x6c, 0x69, 0x6e, 0x65, 0x01, 0x24, 0x62, 0x61, - 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6b, - 0x69, 0x6c, 0x6c, 0x5f, 0x6c, 0x69, 0x6e, 0x65, - 0x01, 0x12, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x77, - 0x6f, 0x72, 0x64, 0x01, 0x24, 0x62, 0x61, 0x63, - 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6b, 0x69, - 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, - 0x08, 0x79, 0x61, 0x6e, 0x6b, 0x01, 0x12, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x63, - 0x01, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x74, 0x01, - 0x20, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x5f, 0x77, 0x6f, 0x72, - 0x64, 0x01, 0x24, 0x67, 0x65, 0x74, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x01, 0x1e, 0x67, - 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x01, 0x14, - 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, - 0x6f, 0x6e, 0x01, 0x10, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x73, 0x01, 0x0c, 0x64, 0x75, - 0x70, 0x73, 0x74, 0x72, 0x01, 0x1a, 0x72, 0x65, - 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x73, 0x01, 0x1c, 0x72, 0x65, 0x61, - 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x01, 0x16, 0x72, 0x65, 0x61, - 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x62, - 0x01, 0x2a, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, - 0x6e, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, - 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x01, - 0x1c, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, - 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x01, - 0x16, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, - 0x63, 0x68, 0x61, 0x72, 0x01, 0x14, 0x68, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x01, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x01, 0x20, 0x62, 0x69, 0x67, 0x69, - 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x01, 0x08, 0x75, 0x74, - 0x69, 0x6c, 0x01, 0x0a, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x01, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x01, 0x08, 0x68, 0x65, 0x6c, - 0x70, 0x01, 0x08, 0x6c, 0x6f, 0x61, 0x64, 0x01, - 0x08, 0x65, 0x78, 0x69, 0x74, 0x01, 0x0e, 0x74, - 0x6f, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x01, 0x14, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x01, 0x12, 0x63, 0x6d, 0x64, 0x5f, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x01, 0x24, 0x63, - 0x6d, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6c, - 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x01, 0x26, 0x72, 0x65, 0x61, 0x64, 0x6c, - 0x69, 0x6e, 0x65, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x6c, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x01, 0x14, - 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x63, - 0x6d, 0x64, 0x01, 0x1c, 0x65, 0x76, 0x61, 0x6c, - 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x01, 0x22, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x20, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x61, - 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x01, - 0x1c, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, - 0x63, 0x6d, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x01, - 0x16, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x5f, 0x6a, 0x73, 0x01, 0x16, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x69, 0x6c, - 0x65, 0x01, 0x18, 0x73, 0x61, 0x76, 0x65, 0x5f, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, - 0x18, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x69, - 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, 0x16, 0x6c, - 0x6f, 0x61, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x01, 0x06, 0x74, 0x61, 0x62, 0x01, - 0x0c, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x01, - 0x0c, 0x69, 0x73, 0x61, 0x74, 0x74, 0x79, 0x01, - 0x1a, 0x74, 0x74, 0x79, 0x47, 0x65, 0x74, 0x57, - 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x01, 0x12, - 0x74, 0x74, 0x79, 0x53, 0x65, 0x74, 0x52, 0x61, - 0x77, 0x01, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x6c, 0x01, 0x0c, 0x53, 0x49, 0x47, 0x49, 0x4e, - 0x54, 0x01, 0x1c, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x61, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x72, 0x01, 0x02, 0x6c, 0x01, 0x02, 0x69, 0x01, - 0x08, 0x72, 0x65, 0x61, 0x64, 0x01, 0x0c, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x01, 0x02, 0x63, - 0x01, 0x02, 0x41, 0x01, 0x02, 0x5a, 0x01, 0x02, - 0x61, 0x01, 0x02, 0x7a, 0x01, 0x02, 0x5f, 0x01, - 0x02, 0x24, 0x01, 0x06, 0x73, 0x74, 0x72, 0x01, - 0x06, 0x6c, 0x65, 0x6e, 0x01, 0x0e, 0x73, 0x74, - 0x72, 0x5f, 0x6c, 0x65, 0x6e, 0x01, 0x14, 0x63, - 0x68, 0x61, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x41, - 0x74, 0x01, 0x02, 0x64, 0x01, 0x16, 0x63, 0x6f, - 0x64, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x74, 0x01, 0x02, 0x62, 0x01, 0x04, 0x28, 0x29, - 0x01, 0x04, 0x5b, 0x5d, 0x01, 0x04, 0x7b, 0x7d, - 0x01, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x01, - 0x16, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x01, 0x02, 0x6a, 0x01, - 0x0a, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x01, 0x08, - 0x70, 0x75, 0x74, 0x73, 0x01, 0x08, 0x6e, 0x6f, - 0x6e, 0x65, 0x01, 0x12, 0x73, 0x75, 0x62, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x01, 0x02, 0x6e, - 0x01, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x01, 0x04, - 0x1b, 0x5b, 0x01, 0x0a, 0x64, 0x65, 0x6c, 0x74, - 0x61, 0x01, 0x02, 0x0a, 0x01, 0x06, 0x6d, 0x69, - 0x6e, 0x01, 0x02, 0x43, 0x01, 0x02, 0x44, 0x01, - 0x0e, 0x63, 0x6d, 0x64, 0x5f, 0x6c, 0x65, 0x6e, - 0x01, 0x14, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x01, 0x04, 0x20, 0x08, - 0x01, 0x06, 0x1b, 0x5b, 0x4a, 0x01, 0x06, 0x6f, - 0x75, 0x74, 0x01, 0x0a, 0x66, 0x6c, 0x75, 0x73, - 0x68, 0x01, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x41, - 0x74, 0x01, 0x06, 0x70, 0x6f, 0x73, 0x01, 0x0a, - 0x63, 0x6c, 0x65, 0x61, 0x72, 0x01, 0x12, 0x74, - 0x72, 0x69, 0x6d, 0x52, 0x69, 0x67, 0x68, 0x74, - 0x01, 0x08, 0x70, 0x75, 0x73, 0x68, 0x01, 0x06, - 0x64, 0x69, 0x72, 0x01, 0x06, 0x65, 0x6e, 0x64, - 0x01, 0x04, 0x70, 0x31, 0x01, 0x04, 0x70, 0x32, - 0x01, 0x04, 0x70, 0x34, 0x01, 0x04, 0x70, 0x33, - 0x01, 0x16, 0x74, 0x6f, 0x55, 0x70, 0x70, 0x65, - 0x72, 0x43, 0x61, 0x73, 0x65, 0x01, 0x16, 0x74, - 0x6f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x43, 0x61, - 0x73, 0x65, 0x01, 0x02, 0x73, 0x01, 0x3c, 0x0a, - 0x28, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x43, - 0x74, 0x72, 0x6c, 0x2d, 0x43, 0x20, 0x61, 0x67, - 0x61, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x71, - 0x75, 0x69, 0x74, 0x29, 0x0a, 0x01, 0x08, 0x6c, - 0x69, 0x6e, 0x65, 0x01, 0x0a, 0x73, 0x6c, 0x69, - 0x63, 0x65, 0x01, 0x08, 0x62, 0x61, 0x73, 0x65, - 0x01, 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, - 0x6f, 0x73, 0x01, 0x06, 0x6f, 0x62, 0x6a, 0x01, - 0x02, 0x5c, 0x01, 0x02, 0x2e, 0x01, 0x12, 0x27, - 0x22, 0x60, 0x40, 0x23, 0x29, 0x5d, 0x7d, 0x5c, - 0x01, 0x0e, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, - 0x66, 0x01, 0x02, 0x27, 0x01, 0x02, 0x22, 0x01, - 0x02, 0x60, 0x01, 0x02, 0x5d, 0x01, 0x02, 0x2f, - 0x01, 0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x01, - 0x0e, 0x63, 0x74, 0x78, 0x5f, 0x6f, 0x62, 0x6a, - 0x01, 0x02, 0x72, 0x01, 0x0a, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x01, 0x0a, 0x70, 0x72, 0x6f, 0x70, - 0x73, 0x01, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x01, - 0x0c, 0x73, 0x79, 0x6d, 0x63, 0x6d, 0x70, 0x01, - 0x26, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x50, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x01, 0x14, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x73, 0x57, 0x69, 0x74, 0x68, - 0x01, 0x08, 0x73, 0x6f, 0x72, 0x74, 0x01, 0x06, - 0x63, 0x74, 0x78, 0x01, 0x06, 0x72, 0x65, 0x73, - 0x01, 0x02, 0x74, 0x01, 0x12, 0x6d, 0x61, 0x78, - 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x01, 0x06, - 0x63, 0x6f, 0x6c, 0x01, 0x0c, 0x6e, 0x5f, 0x63, - 0x6f, 0x6c, 0x73, 0x01, 0x06, 0x72, 0x6f, 0x77, - 0x01, 0x0c, 0x6e, 0x5f, 0x72, 0x6f, 0x77, 0x73, - 0x01, 0x02, 0x6d, 0x01, 0x02, 0x28, 0x01, 0x02, - 0x29, 0x01, 0x06, 0x6d, 0x61, 0x78, 0x01, 0x0a, - 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x01, 0x08, 0x63, - 0x65, 0x69, 0x6c, 0x01, 0x0c, 0x70, 0x61, 0x64, - 0x45, 0x6e, 0x64, 0x01, 0x0a, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x01, 0x0c, 0x64, 0x65, 0x66, 0x73, - 0x74, 0x72, 0x01, 0x04, 0x63, 0x62, 0x01, 0x02, - 0x20, 0x01, 0x0e, 0x74, 0x6f, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x01, 0x04, 0x63, 0x31, 0x01, 0x1a, - 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x64, 0x65, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x01, 0x02, 0x1b, - 0x01, 0x02, 0x5b, 0x01, 0x02, 0x4f, 0x01, 0x02, - 0x3b, 0x01, 0x06, 0x66, 0x75, 0x6e, 0x01, 0x0a, - 0x72, 0x61, 0x64, 0x69, 0x78, 0x01, 0x04, 0x2d, - 0x30, 0x01, 0x02, 0x2d, 0x01, 0x04, 0x30, 0x78, - 0x01, 0x06, 0x76, 0x61, 0x6c, 0x01, 0x12, 0x6d, - 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x01, 0x14, 0x75, 0x73, 0x65, 0x5f, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x73, 0x01, 0x0e, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x01, 0x16, 0x62, - 0x72, 0x65, 0x61, 0x6b, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x01, 0x1c, 0x6d, 0x61, 0x78, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x01, 0x1e, 0x6d, 0x61, 0x78, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x01, 0x1e, 0x6d, 0x61, 0x78, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x01, 0x08, 0x72, 0x65, - 0x66, 0x73, 0x01, 0x0c, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x01, 0x0c, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x01, 0x14, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x01, 0x12, - 0x71, 0x75, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x74, - 0x72, 0x01, 0x14, 0x70, 0x75, 0x73, 0x68, 0x5f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x01, 0x18, 0x61, - 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x01, 0x12, 0x63, 0x6c, 0x61, - 0x73, 0x73, 0x5f, 0x74, 0x61, 0x67, 0x01, 0x12, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x72, 0x65, - 0x63, 0x01, 0x14, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x5f, 0x73, 0x74, 0x72, 0x01, 0x1e, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x72, - 0x6f, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x01, 0x1a, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x01, 0x10, 0x69, - 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x01, - 0x16, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x01, 0x1a, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x69, 0x6e, - 0x67, 0x6c, 0x65, 0x01, 0x1a, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x01, 0x1a, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x6e, - 0x74, 0x01, 0x06, 0x6f, 0x70, 0x74, 0x01, 0x06, - 0x64, 0x65, 0x66, 0x01, 0x10, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x73, 0x01, 0x12, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, - 0x01, 0x14, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x41, 0x6c, 0x6c, 0x01, 0x04, 0x5c, 0x22, - 0x01, 0x02, 0x6f, 0x01, 0x08, 0x63, 0x61, 0x6c, - 0x6c, 0x01, 0x04, 0x6e, 0x30, 0x01, 0x02, 0x6b, - 0x01, 0x06, 0x6b, 0x65, 0x79, 0x01, 0x08, 0x74, - 0x79, 0x70, 0x65, 0x01, 0x0e, 0x69, 0x73, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x01, 0x0e, 0x6e, 0x6f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x01, 0x0c, 0x6e, - 0x6f, 0x6b, 0x65, 0x79, 0x73, 0x01, 0x0a, 0x62, - 0x72, 0x61, 0x63, 0x65, 0x01, 0x06, 0x73, 0x65, - 0x70, 0x01, 0x12, 0x6f, 0x62, 0x6a, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x01, 0x06, 0x74, 0x61, - 0x67, 0x01, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x01, - 0x08, 0x64, 0x65, 0x73, 0x63, 0x01, 0x0c, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x73, 0x01, 0x06, 0x2e, - 0x2e, 0x2e, 0x01, 0x16, 0x5b, 0x43, 0x69, 0x72, - 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x2a, 0x01, - 0x0a, 0x44, 0x61, 0x74, 0x65, 0x20, 0x01, 0x16, - 0x74, 0x6f, 0x47, 0x4d, 0x54, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x01, 0x04, 0x3a, 0x20, 0x01, - 0x0e, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x01, 0x06, 0x29, 0x20, 0x5b, 0x01, 0x16, 0x5b, - 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x3a, 0x20, 0x01, 0x2c, 0x5b, 0x46, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x61, - 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, - 0x29, 0x5d, 0x01, 0x04, 0x20, 0x5b, 0x01, 0x06, - 0x5d, 0x20, 0x7b, 0x01, 0x26, 0x3a, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x74, 0x79, 0x70, 0x65, 0x5d, 0x20, 0x7b, - 0x01, 0x04, 0x20, 0x7b, 0x01, 0x02, 0x7b, 0x01, - 0x02, 0x7d, 0x01, 0x02, 0x3c, 0x01, 0x1a, 0x20, - 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x3e, 0x01, 0x0e, 0x3c, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x3e, 0x01, 0x08, 0x2e, - 0x2e, 0x2e, 0x20, 0x01, 0x16, 0x20, 0x6d, 0x6f, - 0x72, 0x65, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, - 0x01, 0x02, 0x3a, 0x01, 0x0c, 0x47, 0x65, 0x74, - 0x74, 0x65, 0x72, 0x01, 0x0c, 0x53, 0x65, 0x74, - 0x74, 0x65, 0x72, 0x01, 0x20, 0x20, 0x6d, 0x6f, - 0x72, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x69, 0x65, 0x73, 0x01, 0x06, 0x70, - 0x6f, 0x70, 0x01, 0x0c, 0x3c, 0x72, 0x65, 0x66, - 0x20, 0x2a, 0x01, 0x04, 0x3e, 0x20, 0x01, 0x0a, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x01, 0x10, 0x70, - 0x72, 0x6f, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x01, - 0x0a, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x01, 0x0c, - 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x01, 0x14, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x01, 0x02, 0x2c, 0x01, 0x0a, 0x6f, - 0x74, 0x68, 0x65, 0x72, 0x01, 0x08, 0x64, 0x61, - 0x74, 0x65, 0x01, 0x06, 0x4e, 0x61, 0x4e, 0x01, - 0x0e, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, - 0x01, 0x02, 0x77, 0x01, 0x0a, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x01, 0x0c, 0x73, 0x65, 0x70, 0x6c, - 0x65, 0x6e, 0x01, 0x08, 0x6c, 0x61, 0x73, 0x74, - 0x01, 0x04, 0x2c, 0x20, 0x01, 0x0c, 0x72, 0x65, - 0x70, 0x65, 0x61, 0x74, 0x01, 0x0c, 0x69, 0x6e, - 0x64, 0x65, 0x6e, 0x74, 0x01, 0x16, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x5f, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x01, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x01, 0x08, 0x63, 0x6f, 0x6c, 0x73, 0x01, 0x10, - 0x63, 0x6f, 0x6c, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x01, 0x10, 0x65, 0x6e, 0x64, 0x73, 0x57, 0x69, - 0x74, 0x68, 0x01, 0x14, 0x73, 0x68, 0x6f, 0x77, - 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x01, 0x0a, - 0x64, 0x65, 0x70, 0x74, 0x68, 0x01, 0x0e, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x01, 0x0e, - 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x01, - 0x02, 0x70, 0x01, 0x02, 0x3f, 0x01, 0x08, 0x74, - 0x72, 0x69, 0x6d, 0x01, 0x26, 0x55, 0x6e, 0x6b, - 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x20, - 0x01, 0x06, 0x73, 0x65, 0x6c, 0x01, 0x32, 0x2e, - 0x68, 0x65, 0x6c, 0x70, 0x20, 0x20, 0x20, 0x20, - 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0a, - 0x01, 0x10, 0x2e, 0x78, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x01, 0x36, 0x68, 0x65, 0x78, 0x61, - 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x0a, 0x01, - 0x10, 0x2e, 0x64, 0x65, 0x63, 0x20, 0x20, 0x20, - 0x20, 0x01, 0x2e, 0x64, 0x65, 0x63, 0x69, 0x6d, - 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x0a, 0x01, 0x10, 0x2e, 0x74, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x20, 0x01, 0x2c, 0x74, 0x6f, - 0x67, 0x67, 0x6c, 0x65, 0x20, 0x74, 0x69, 0x6d, - 0x69, 0x6e, 0x67, 0x20, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x0a, 0x01, 0x10, 0x2e, 0x73, - 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x01, 0x3c, - 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, - 0x64, 0x65, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x01, 0x48, - 0x2e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x20, 0x20, - 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x70, 0x74, - 0x68, 0x20, 0x28, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x3a, 0x20, 0x01, 0x04, 0x29, 0x0a, - 0x01, 0x10, 0x2e, 0x68, 0x69, 0x64, 0x64, 0x65, - 0x6e, 0x20, 0x01, 0x42, 0x74, 0x6f, 0x67, 0x67, - 0x6c, 0x65, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, - 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x69, 0x65, 0x73, 0x20, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x0a, 0x01, 0x10, 0x2e, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x01, - 0x2c, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x20, - 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x64, 0x20, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x01, - 0x10, 0x2e, 0x64, 0x61, 0x72, 0x6b, 0x20, 0x20, - 0x20, 0x01, 0x08, 0x64, 0x61, 0x72, 0x6b, 0x01, - 0x30, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, - 0x64, 0x61, 0x72, 0x6b, 0x20, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x65, - 0x0a, 0x01, 0x10, 0x2e, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x20, 0x20, 0x01, 0x0a, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x01, 0x32, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x74, - 0x68, 0x65, 0x6d, 0x65, 0x0a, 0x01, 0x38, 0x2e, - 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x20, 0x20, - 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x0a, 0x01, 0x4c, 0x2e, 0x6c, 0x6f, - 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, - 0x61, 0x64, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, - 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x0a, 0x01, 0x1c, 0x2e, 0x71, 0x75, - 0x69, 0x74, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, - 0x69, 0x74, 0x0a, 0x01, 0x02, 0x65, 0x01, 0x16, - 0x6c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x4f, 0x66, 0x01, 0x06, 0x2e, 0x6a, 0x73, - 0x01, 0x14, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x01, 0x1c, 0x31, 0x20, - 0x74, 0x72, 0x75, 0x65, 0x20, 0x79, 0x65, 0x73, - 0x20, 0x59, 0x65, 0x73, 0x01, 0x0c, 0x1b, 0x5b, - 0x48, 0x1b, 0x5b, 0x4a, 0x01, 0x46, 0x51, 0x75, - 0x69, 0x63, 0x6b, 0x4a, 0x53, 0x2d, 0x6e, 0x67, - 0x20, 0x2d, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, - 0x22, 0x2e, 0x68, 0x65, 0x6c, 0x70, 0x22, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x6c, 0x70, - 0x0a, 0x01, 0x08, 0x20, 0x20, 0x20, 0x20, 0x01, - 0x08, 0x65, 0x78, 0x70, 0x72, 0x01, 0x0c, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x2a, 0x22, - 0x75, 0x73, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x63, 0x74, 0x22, 0x3b, 0x20, 0x76, 0x6f, 0x69, - 0x64, 0x20, 0x30, 0x3b, 0x01, 0x06, 0x6e, 0x6f, - 0x77, 0x01, 0x14, 0x65, 0x76, 0x61, 0x6c, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x01, 0x22, 0x62, - 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, - 0x5f, 0x62, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, - 0x01, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x01, - 0x0e, 0x54, 0x68, 0x72, 0x6f, 0x77, 0x3a, 0x20, - 0x01, 0x04, 0x67, 0x63, 0x01, 0x0a, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x01, 0x0e, 0x70, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x01, 0x12, 0x63, 0x61, - 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, - 0x14, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x01, 0x14, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, - 0x12, 0x70, 0x6f, 0x70, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x01, 0x26, 0x70, 0x61, 0x72, 0x73, - 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x01, - 0x24, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x6c, - 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x01, 0x18, 0x70, 0x61, 0x72, - 0x73, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x01, 0x16, 0x70, 0x61, 0x72, 0x73, 0x65, - 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, 0x18, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x01, 0x16, 0x6a, 0x73, - 0x5f, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, - 0x73, 0x01, 0x16, 0x6a, 0x73, 0x5f, 0x6e, 0x6f, - 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, 0x10, - 0x6a, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x01, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x01, 0x12, 0x73, 0x65, 0x74, 0x5f, - 0x73, 0x74, 0x79, 0x6c, 0x65, 0x01, 0x0e, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x01, 0x0a, - 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x01, 0x04, 0x69, - 0x31, 0x01, 0x02, 0x7c, 0x01, 0x14, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x01, 0x04, 0x74, 0x6f, 0x01, 0x6a, 0x62, 0x72, - 0x65, 0x61, 0x6b, 0x7c, 0x63, 0x61, 0x73, 0x65, - 0x7c, 0x63, 0x61, 0x74, 0x63, 0x68, 0x7c, 0x63, - 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x7c, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, - 0x7c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x7c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x7c, - 0x64, 0x6f, 0x7c, 0x01, 0x5e, 0x65, 0x6c, 0x73, - 0x65, 0x7c, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x6c, - 0x79, 0x7c, 0x66, 0x6f, 0x72, 0x7c, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x7c, 0x69, - 0x66, 0x7c, 0x69, 0x6e, 0x7c, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x7c, - 0x6e, 0x65, 0x77, 0x7c, 0x01, 0x5e, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x7c, 0x73, 0x77, 0x69, - 0x74, 0x63, 0x68, 0x7c, 0x74, 0x68, 0x69, 0x73, - 0x7c, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x7c, 0x74, - 0x72, 0x79, 0x7c, 0x74, 0x79, 0x70, 0x65, 0x6f, - 0x66, 0x7c, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x7c, - 0x77, 0x69, 0x74, 0x68, 0x7c, 0x01, 0x5a, 0x63, - 0x6c, 0x61, 0x73, 0x73, 0x7c, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x7c, 0x65, 0x6e, 0x75, 0x6d, 0x7c, - 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7c, 0x65, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x7c, 0x65, 0x78, - 0x74, 0x65, 0x6e, 0x64, 0x73, 0x7c, 0x73, 0x75, - 0x70, 0x65, 0x72, 0x7c, 0x01, 0x66, 0x69, 0x6d, - 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x7c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x7c, 0x6c, 0x65, 0x74, 0x7c, 0x70, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x7c, 0x70, - 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x7c, 0x70, - 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x7c, 0x01, 0x28, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x7c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x7c, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x7c, 0x01, - 0x4e, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x65, 0x64, 0x7c, 0x6e, 0x75, 0x6c, 0x6c, 0x7c, - 0x74, 0x72, 0x75, 0x65, 0x7c, 0x66, 0x61, 0x6c, - 0x73, 0x65, 0x7c, 0x49, 0x6e, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x79, 0x7c, 0x4e, 0x61, 0x4e, 0x7c, - 0x01, 0x1e, 0x65, 0x76, 0x61, 0x6c, 0x7c, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x7c, 0x01, 0x0c, 0x61, 0x77, 0x61, 0x69, 0x74, - 0x7c, 0x01, 0x7a, 0x7c, 0x74, 0x68, 0x69, 0x73, - 0x7c, 0x73, 0x75, 0x70, 0x65, 0x72, 0x7c, 0x75, - 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, - 0x7c, 0x6e, 0x75, 0x6c, 0x6c, 0x7c, 0x74, 0x72, - 0x75, 0x65, 0x7c, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x7c, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x79, 0x7c, 0x4e, 0x61, 0x4e, 0x7c, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x7c, - 0x01, 0x14, 0x7c, 0x76, 0x6f, 0x69, 0x64, 0x7c, - 0x76, 0x61, 0x72, 0x7c, 0x01, 0x02, 0x09, 0x01, - 0x02, 0x0d, 0x01, 0x02, 0x2b, 0x01, 0x0c, 0x67, - 0x65, 0x74, 0x65, 0x6e, 0x76, 0x01, 0x08, 0x48, - 0x4f, 0x4d, 0x45, 0x01, 0x16, 0x55, 0x53, 0x45, - 0x52, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, - 0x01, 0x02, 0x66, 0x01, 0x08, 0x6f, 0x70, 0x65, - 0x6e, 0x01, 0x18, 0x2e, 0x71, 0x6a, 0x73, 0x5f, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, - 0x0a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x01, 0x10, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, - 0x01, 0x12, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x46, - 0x47, 0x42, 0x47, 0x01, 0x10, 0x4e, 0x4f, 0x5f, - 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x01, 0x08, 0x1b, - 0x5b, 0x30, 0x6d, 0x01, 0x0a, 0x1b, 0x5b, 0x33, - 0x30, 0x6d, 0x01, 0x0a, 0x62, 0x6c, 0x61, 0x63, - 0x6b, 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x31, 0x6d, - 0x01, 0x06, 0x72, 0x65, 0x64, 0x01, 0x0a, 0x1b, - 0x5b, 0x33, 0x32, 0x6d, 0x01, 0x0a, 0x67, 0x72, - 0x65, 0x65, 0x6e, 0x01, 0x0a, 0x1b, 0x5b, 0x33, - 0x33, 0x6d, 0x01, 0x0c, 0x79, 0x65, 0x6c, 0x6c, - 0x6f, 0x77, 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x34, - 0x6d, 0x01, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x01, - 0x0a, 0x1b, 0x5b, 0x33, 0x35, 0x6d, 0x01, 0x0e, - 0x6d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x61, 0x01, - 0x0a, 0x1b, 0x5b, 0x33, 0x36, 0x6d, 0x01, 0x08, - 0x63, 0x79, 0x61, 0x6e, 0x01, 0x0a, 0x1b, 0x5b, - 0x33, 0x37, 0x6d, 0x01, 0x0a, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x30, - 0x3b, 0x31, 0x6d, 0x01, 0x08, 0x67, 0x72, 0x61, - 0x79, 0x01, 0x08, 0x67, 0x72, 0x65, 0x79, 0x01, - 0x0e, 0x1b, 0x5b, 0x33, 0x31, 0x3b, 0x31, 0x6d, - 0x01, 0x14, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x5f, 0x72, 0x65, 0x64, 0x01, 0x0e, 0x1b, 0x5b, - 0x33, 0x32, 0x3b, 0x31, 0x6d, 0x01, 0x18, 0x62, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x67, 0x72, - 0x65, 0x65, 0x6e, 0x01, 0x0e, 0x1b, 0x5b, 0x33, - 0x33, 0x3b, 0x31, 0x6d, 0x01, 0x1a, 0x62, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x79, 0x65, 0x6c, - 0x6c, 0x6f, 0x77, 0x01, 0x0e, 0x1b, 0x5b, 0x33, - 0x34, 0x3b, 0x31, 0x6d, 0x01, 0x16, 0x62, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x62, 0x6c, 0x75, - 0x65, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x35, 0x3b, - 0x31, 0x6d, 0x01, 0x1c, 0x62, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x5f, 0x6d, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x61, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x36, - 0x3b, 0x31, 0x6d, 0x01, 0x16, 0x62, 0x72, 0x69, - 0x67, 0x68, 0x74, 0x5f, 0x63, 0x79, 0x61, 0x6e, - 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x37, 0x3b, 0x31, - 0x6d, 0x01, 0x18, 0x62, 0x72, 0x69, 0x67, 0x68, - 0x74, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x01, - 0x0c, 0x71, 0x6a, 0x73, 0x20, 0x3e, 0x20, 0x01, - 0x0c, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x01, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x03, - 0x01, 0x02, 0x04, 0x01, 0x02, 0x05, 0x01, 0x02, - 0x06, 0x01, 0x02, 0x07, 0x01, 0x02, 0x08, 0x01, - 0x02, 0x0b, 0x01, 0x02, 0x0c, 0x01, 0x02, 0x0e, - 0x01, 0x02, 0x10, 0x01, 0x02, 0x11, 0x01, 0x02, - 0x12, 0x01, 0x02, 0x13, 0x01, 0x02, 0x14, 0x01, - 0x02, 0x17, 0x01, 0x02, 0x18, 0x01, 0x02, 0x19, - 0x01, 0x06, 0x1b, 0x4f, 0x41, 0x01, 0x06, 0x1b, - 0x4f, 0x42, 0x01, 0x06, 0x1b, 0x4f, 0x43, 0x01, - 0x06, 0x1b, 0x4f, 0x44, 0x01, 0x06, 0x1b, 0x4f, - 0x46, 0x01, 0x06, 0x1b, 0x4f, 0x48, 0x01, 0x0c, - 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x43, 0x01, 0x0c, - 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x44, 0x01, 0x08, - 0x1b, 0x5b, 0x31, 0x7e, 0x01, 0x08, 0x1b, 0x5b, - 0x33, 0x7e, 0x01, 0x08, 0x1b, 0x5b, 0x34, 0x7e, - 0x01, 0x08, 0x1b, 0x5b, 0x35, 0x7e, 0x01, 0x08, - 0x1b, 0x5b, 0x36, 0x7e, 0x01, 0x06, 0x1b, 0x5b, - 0x41, 0x01, 0x06, 0x1b, 0x5b, 0x42, 0x01, 0x06, - 0x1b, 0x5b, 0x43, 0x01, 0x06, 0x1b, 0x5b, 0x44, - 0x01, 0x06, 0x1b, 0x5b, 0x46, 0x01, 0x06, 0x1b, - 0x5b, 0x48, 0x01, 0x04, 0x1b, 0x7f, 0x01, 0x04, - 0x1b, 0x62, 0x01, 0x04, 0x1b, 0x64, 0x01, 0x04, - 0x1b, 0x66, 0x01, 0x04, 0x1b, 0x6b, 0x01, 0x04, - 0x1b, 0x6c, 0x01, 0x04, 0x1b, 0x74, 0x01, 0x04, - 0x1b, 0x75, 0x01, 0x02, 0x7f, 0x01, 0x02, 0x78, - 0x01, 0x06, 0x64, 0x65, 0x63, 0x01, 0x08, 0x74, - 0x69, 0x6d, 0x65, 0x01, 0x0c, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x01, 0x0c, 0x68, 0x69, 0x64, - 0x64, 0x65, 0x6e, 0x01, 0x08, 0x71, 0x75, 0x69, - 0x74, 0x0d, 0xc6, 0x03, 0x03, 0xc8, 0x03, 0xca, - 0x03, 0xcc, 0x03, 0x00, 0x00, 0x03, 0x00, 0xfe, - 0x01, 0x00, 0x01, 0xfe, 0x01, 0x01, 0x02, 0xfe, - 0x01, 0x02, 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa2, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x0f, - 0x00, 0xce, 0x03, 0x00, 0x0d, 0xd0, 0x03, 0x01, - 0x0d, 0xd2, 0x03, 0x02, 0x0d, 0x0c, 0x43, 0x02, - 0x01, 0x00, 0x01, 0x8a, 0x01, 0x01, 0x04, 0x03, - 0x5c, 0x83, 0x0d, 0x8b, 0x01, 0xd4, 0x03, 0x00, - 0x01, 0x40, 0xa8, 0x02, 0x00, 0x00, 0x40, 0xb0, - 0x02, 0x00, 0x01, 0x40, 0xae, 0x02, 0x00, 0x02, - 0x40, 0xb2, 0x02, 0x00, 0x03, 0x40, 0xe4, 0x02, - 0x00, 0x04, 0x40, 0xce, 0x02, 0x00, 0x05, 0x40, - 0xaa, 0x02, 0x00, 0x06, 0x40, 0xbc, 0x02, 0x00, - 0x07, 0x40, 0xc4, 0x02, 0x00, 0x08, 0x40, 0xac, - 0x02, 0x00, 0x09, 0x40, 0xb4, 0x02, 0x00, 0x0a, - 0x00, 0xb8, 0x02, 0x00, 0x0b, 0x40, 0xba, 0x02, - 0x00, 0x0c, 0x40, 0xd6, 0x03, 0x00, 0x0d, 0x40, - 0xd8, 0x03, 0x00, 0x0e, 0x40, 0xda, 0x03, 0x00, - 0x0f, 0x40, 0xdc, 0x03, 0x00, 0x10, 0x00, 0xde, - 0x03, 0x00, 0x11, 0x40, 0xe0, 0x03, 0x00, 0x12, - 0x40, 0xe2, 0x03, 0x00, 0x13, 0x40, 0xe4, 0x03, - 0x00, 0x14, 0x40, 0xe6, 0x03, 0x00, 0x15, 0x40, - 0xe8, 0x03, 0x00, 0x16, 0x40, 0xea, 0x03, 0x00, - 0x17, 0x40, 0xec, 0x03, 0x00, 0x18, 0x40, 0xee, - 0x03, 0x00, 0x19, 0x40, 0xf0, 0x03, 0x00, 0x1a, - 0x40, 0xf2, 0x03, 0x00, 0x1b, 0x40, 0xf4, 0x03, - 0x00, 0x1c, 0x40, 0xf6, 0x03, 0x00, 0x1d, 0x40, - 0xf8, 0x03, 0x00, 0x1e, 0x40, 0xfa, 0x03, 0x00, - 0x1f, 0x40, 0xfc, 0x03, 0x00, 0x20, 0x40, 0xfe, - 0x03, 0x00, 0x21, 0x40, 0x80, 0x04, 0x00, 0x22, - 0x40, 0x82, 0x04, 0x00, 0x23, 0x40, 0x84, 0x04, - 0x00, 0x24, 0x40, 0x86, 0x04, 0x00, 0x25, 0x40, - 0x88, 0x04, 0x00, 0x26, 0x40, 0x8a, 0x04, 0x00, - 0x27, 0x40, 0x8c, 0x04, 0x00, 0x28, 0x40, 0x8e, - 0x04, 0x00, 0x29, 0x40, 0x90, 0x04, 0x00, 0x2a, - 0x40, 0x92, 0x04, 0x00, 0x2b, 0x40, 0x94, 0x04, - 0x00, 0x2c, 0x40, 0x96, 0x04, 0x00, 0x2d, 0x40, - 0x98, 0x04, 0x00, 0x2e, 0x40, 0x9a, 0x04, 0x00, - 0x2f, 0x40, 0x9c, 0x04, 0x00, 0x30, 0x40, 0x9e, - 0x04, 0x00, 0x31, 0x40, 0xa0, 0x04, 0x00, 0x32, - 0x40, 0xa2, 0x04, 0x00, 0x33, 0x40, 0xa4, 0x04, - 0x00, 0x34, 0x00, 0xa6, 0x04, 0x00, 0x35, 0x40, - 0xa8, 0x04, 0x00, 0x36, 0x40, 0xaa, 0x04, 0x00, - 0x37, 0x40, 0xac, 0x04, 0x00, 0x38, 0x40, 0xae, - 0x04, 0x00, 0x39, 0x40, 0xb0, 0x04, 0x00, 0x3a, - 0x40, 0xb2, 0x04, 0x00, 0x3b, 0x40, 0xb4, 0x04, - 0x00, 0x3c, 0x40, 0xb6, 0x04, 0x00, 0x3d, 0x40, - 0xb8, 0x04, 0x00, 0x3e, 0x40, 0xba, 0x04, 0x00, - 0x3f, 0x40, 0xbc, 0x04, 0x00, 0x40, 0x40, 0xbe, - 0x04, 0x00, 0x41, 0x40, 0xc0, 0x04, 0x00, 0x42, - 0x40, 0xc2, 0x04, 0x00, 0x43, 0x00, 0xc4, 0x04, - 0x00, 0x44, 0x00, 0xc6, 0x04, 0x00, 0x45, 0x40, - 0xc8, 0x04, 0x00, 0x46, 0x00, 0xca, 0x04, 0x00, - 0x47, 0x00, 0xcc, 0x04, 0x00, 0x48, 0x00, 0xce, - 0x04, 0x00, 0x49, 0x00, 0xd0, 0x04, 0x00, 0x4a, - 0x40, 0xd2, 0x04, 0x00, 0x4b, 0x40, 0xd4, 0x04, - 0x00, 0x4c, 0x00, 0xd6, 0x04, 0x00, 0x4d, 0x00, - 0xd8, 0x04, 0x00, 0x4e, 0x00, 0xda, 0x04, 0x00, - 0x4f, 0x00, 0xdc, 0x04, 0x00, 0x50, 0x40, 0xde, - 0x04, 0x00, 0x51, 0x00, 0xe0, 0x04, 0x00, 0x52, - 0x00, 0xe2, 0x04, 0x00, 0x53, 0x40, 0xe4, 0x04, - 0x00, 0x54, 0x00, 0xe6, 0x04, 0x00, 0x55, 0x00, - 0xe8, 0x04, 0x00, 0x56, 0x40, 0xea, 0x04, 0x00, - 0x57, 0x00, 0xec, 0x04, 0x00, 0x58, 0x00, 0xee, - 0x04, 0x00, 0x59, 0x00, 0xf0, 0x04, 0x00, 0x5a, - 0x00, 0xf2, 0x04, 0x00, 0x5b, 0x00, 0xf4, 0x04, - 0x00, 0x5c, 0x00, 0xf6, 0x04, 0x00, 0x5d, 0x00, - 0xf8, 0x04, 0x00, 0x5e, 0x40, 0xfa, 0x04, 0x00, - 0x5f, 0x00, 0xfc, 0x04, 0x00, 0x60, 0x00, 0xfe, - 0x04, 0x00, 0x61, 0x00, 0x80, 0x05, 0x00, 0x62, - 0x00, 0x82, 0x05, 0x00, 0x63, 0x00, 0x84, 0x05, - 0x00, 0x64, 0x40, 0x86, 0x05, 0x00, 0x65, 0x00, - 0x88, 0x05, 0x00, 0x66, 0x40, 0x8a, 0x05, 0x00, - 0x67, 0x40, 0x8c, 0x05, 0x00, 0x68, 0x40, 0x8e, - 0x05, 0x00, 0x69, 0x40, 0x90, 0x05, 0x00, 0x6a, - 0x40, 0x92, 0x05, 0x00, 0x6b, 0x40, 0x94, 0x05, - 0x00, 0x6c, 0x40, 0x96, 0x05, 0x00, 0x6d, 0x40, - 0x98, 0x05, 0x00, 0x6e, 0x40, 0x9a, 0x05, 0x00, - 0x6f, 0x40, 0x9c, 0x05, 0x00, 0x70, 0x40, 0x9e, - 0x05, 0x00, 0x71, 0x40, 0xa0, 0x05, 0x00, 0x72, - 0x40, 0xa2, 0x05, 0x00, 0x73, 0x40, 0xa4, 0x05, - 0x00, 0x74, 0x40, 0xa6, 0x05, 0x00, 0x75, 0x40, - 0xa8, 0x05, 0x00, 0x76, 0x40, 0xaa, 0x05, 0x00, - 0x77, 0x40, 0xac, 0x05, 0x00, 0x78, 0x40, 0xae, - 0x05, 0x00, 0x79, 0x00, 0xb0, 0x05, 0x00, 0x7a, - 0x40, 0xb2, 0x05, 0x00, 0x7b, 0x40, 0xb4, 0x05, - 0x00, 0x7c, 0x40, 0xb6, 0x05, 0x00, 0x7d, 0x00, - 0xb8, 0x05, 0x00, 0x7e, 0x40, 0xba, 0x05, 0x00, - 0x7f, 0x40, 0xbc, 0x05, 0x00, 0x80, 0x01, 0x40, - 0xbe, 0x05, 0x00, 0x81, 0x01, 0x40, 0xc0, 0x05, - 0x00, 0x82, 0x01, 0x40, 0xc2, 0x05, 0x00, 0x83, - 0x01, 0x40, 0xc4, 0x05, 0x00, 0x84, 0x01, 0x40, - 0xc6, 0x05, 0x00, 0x85, 0x01, 0x40, 0xc8, 0x05, - 0x00, 0x86, 0x01, 0x40, 0xca, 0x05, 0x00, 0x87, - 0x01, 0x40, 0xcc, 0x05, 0x00, 0x88, 0x01, 0x00, - 0xce, 0x05, 0x00, 0x89, 0x01, 0x00, 0xce, 0x03, - 0x00, 0x0c, 0xd0, 0x03, 0x01, 0x0c, 0xd2, 0x03, - 0x02, 0x0c, 0x0c, 0x43, 0x02, 0x01, 0xa4, 0x04, - 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x89, 0x01, - 0x01, 0xd0, 0x05, 0x00, 0x00, 0x00, 0x9c, 0x04, - 0x30, 0x01, 0xce, 0x03, 0x00, 0x0c, 0xa0, 0x04, - 0x32, 0x01, 0xd0, 0x03, 0x01, 0x0c, 0xa6, 0x04, - 0x35, 0x01, 0x9e, 0x04, 0x31, 0x01, 0xce, 0x02, - 0x05, 0x01, 0xa8, 0x04, 0x36, 0x01, 0x66, 0x01, - 0x00, 0x42, 0x0d, 0x00, 0x00, 0x00, 0x43, 0x69, - 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0xe3, 0xbe, - 0x50, 0xe5, 0x66, 0x03, 0x00, 0x43, 0x6a, 0x01, - 0x00, 0x00, 0xdf, 0x24, 0x01, 0x00, 0xec, 0x35, - 0x66, 0x03, 0x00, 0x42, 0x6b, 0x01, 0x00, 0x00, - 0xec, 0x14, 0x66, 0x03, 0x00, 0x43, 0x6b, 0x01, - 0x00, 0x00, 0xdf, 0x24, 0x01, 0x00, 0xcf, 0xec, - 0x05, 0xc7, 0xb6, 0x48, 0xe5, 0x66, 0x03, 0x00, - 0x42, 0x6c, 0x01, 0x00, 0x00, 0xec, 0x0e, 0x66, - 0x03, 0x00, 0x43, 0x6c, 0x01, 0x00, 0x00, 0xdf, - 0x24, 0x01, 0x00, 0x0e, 0x66, 0x03, 0x00, 0x43, - 0x6d, 0x01, 0x00, 0x00, 0x66, 0x03, 0x00, 0x42, - 0x6e, 0x01, 0x00, 0x00, 0x5f, 0x04, 0x00, 0x24, - 0x02, 0x00, 0x0e, 0x5f, 0x06, 0x00, 0x11, 0xbe, - 0x40, 0x21, 0x01, 0x00, 0x60, 0x05, 0x00, 0x66, - 0x03, 0x00, 0x43, 0x6f, 0x01, 0x00, 0x00, 0xdf, - 0x5f, 0x07, 0x00, 0x24, 0x02, 0x00, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xa6, 0x04, 0x00, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x04, 0x00, 0xaa, 0x04, 0x37, - 0x01, 0xdf, 0xb9, 0xf1, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xa8, 0x04, 0x00, 0x02, 0x00, 0x06, 0x04, - 0x00, 0x28, 0x02, 0xe0, 0x05, 0x00, 0x00, 0x00, - 0xe2, 0x05, 0x00, 0x01, 0x00, 0xd0, 0x03, 0x01, - 0x0c, 0x9c, 0x04, 0x30, 0x01, 0x9e, 0x04, 0x31, - 0x01, 0xaa, 0x04, 0x37, 0x01, 0x66, 0x00, 0x00, - 0x43, 0x72, 0x01, 0x00, 0x00, 0xe0, 0xe1, 0x42, - 0x73, 0x01, 0x00, 0x00, 0xb6, 0xe1, 0xeb, 0x24, - 0x04, 0x00, 0xcb, 0xb6, 0xcc, 0xc8, 0xc7, 0xa7, - 0xec, 0x0b, 0xe2, 0xe1, 0xc8, 0x48, 0xf1, 0x0e, - 0x94, 0x01, 0xee, 0xf2, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xaa, 0x04, 0x01, 0x00, 0x01, 0x04, 0x04, - 0x00, 0x5f, 0x01, 0xe8, 0x05, 0x00, 0x01, 0x00, - 0xe4, 0x03, 0x14, 0x01, 0x9e, 0x05, 0x71, 0x01, - 0x98, 0x04, 0x2e, 0x01, 0x9a, 0x04, 0x2f, 0x01, - 0xdf, 0x97, 0xec, 0x06, 0xe0, 0xd3, 0xf1, 0x0e, - 0x29, 0xe1, 0xb6, 0xb0, 0xec, 0x24, 0xd3, 0xbf, - 0x80, 0x00, 0xaa, 0xec, 0x1d, 0xd3, 0xbf, 0xc0, - 0x00, 0xa7, 0xec, 0x16, 0xe2, 0xbc, 0xa0, 0xd3, - 0xbe, 0x3f, 0xa3, 0xa5, 0xe6, 0xe1, 0x8f, 0xe9, - 0xb6, 0xaf, 0xec, 0x33, 0xe0, 0xe2, 0xf1, 0x0e, - 0x29, 0xd3, 0xbf, 0xc0, 0x00, 0xaa, 0xec, 0x21, - 0xd3, 0xbf, 0xf8, 0x00, 0xa7, 0xec, 0x1a, 0xb7, - 0xd3, 0xbf, 0xe0, 0x00, 0xaa, 0x9e, 0xd3, 0xbf, - 0xf0, 0x00, 0xaa, 0x9e, 0xe5, 0xd3, 0xb7, 0xbc, - 0xe1, 0x9f, 0xa0, 0xb7, 0x9f, 0xa3, 0xe6, 0x29, - 0xb6, 0xe5, 0xe0, 0xd3, 0xf1, 0x0e, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xac, 0x04, 0x01, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x35, 0x01, 0xe8, 0x05, 0x00, - 0x01, 0x00, 0xd3, 0x98, 0x04, 0x49, 0x00, 0x00, - 0x00, 0xaf, 0x11, 0xec, 0x2a, 0x0e, 0xd3, 0x04, - 0x75, 0x01, 0x00, 0x00, 0xaa, 0x11, 0xec, 0x09, - 0x0e, 0xd3, 0x04, 0x76, 0x01, 0x00, 0x00, 0xa8, - 0x11, 0xed, 0x14, 0x0e, 0xd3, 0x04, 0x77, 0x01, - 0x00, 0x00, 0xaa, 0x11, 0xec, 0x09, 0x0e, 0xd3, - 0x04, 0x78, 0x01, 0x00, 0x00, 0xa8, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0xae, 0x04, 0x01, 0x00, 0x01, - 0x02, 0x00, 0x02, 0x19, 0x01, 0xe8, 0x05, 0x00, - 0x01, 0x00, 0x07, 0x02, 0x30, 0x07, 0x02, 0x39, - 0xd3, 0x98, 0x04, 0x49, 0x00, 0x00, 0x00, 0xaf, - 0x11, 0xec, 0x0e, 0x0e, 0xd3, 0xc0, 0x00, 0xaa, - 0x11, 0xec, 0x06, 0x0e, 0xd3, 0xc0, 0x01, 0xa8, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb0, 0x04, 0x01, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x2d, 0x01, 0xe8, - 0x05, 0x00, 0x01, 0x00, 0xac, 0x04, 0x38, 0x01, - 0xae, 0x04, 0x39, 0x01, 0xd3, 0x98, 0x04, 0x49, - 0x00, 0x00, 0x00, 0xaf, 0x11, 0xec, 0x22, 0x0e, - 0xdf, 0xd3, 0xf1, 0x11, 0xed, 0x1b, 0x0e, 0xe0, - 0xd3, 0xf1, 0x11, 0xed, 0x14, 0x0e, 0xd3, 0x04, - 0x79, 0x01, 0x00, 0x00, 0xad, 0x11, 0xed, 0x09, - 0x0e, 0xd3, 0x04, 0x7a, 0x01, 0x00, 0x00, 0xad, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb2, 0x04, 0x01, - 0x04, 0x01, 0x03, 0x00, 0x00, 0x32, 0x05, 0xf6, - 0x05, 0x00, 0x01, 0x00, 0xf8, 0x05, 0x00, 0x00, - 0x00, 0xe8, 0x05, 0x00, 0x01, 0x00, 0xe2, 0x05, - 0x00, 0x02, 0x00, 0xfa, 0x05, 0x00, 0x03, 0x00, - 0xd3, 0xeb, 0xce, 0xb6, 0xcb, 0xb6, 0xcd, 0xc9, - 0xca, 0xa7, 0xec, 0x25, 0xd3, 0x43, 0x7e, 0x01, - 0x00, 0x00, 0xc9, 0x24, 0x01, 0x00, 0xd0, 0x01, - 0x00, 0xdc, 0x00, 0x00, 0xa7, 0x11, 0xed, 0x09, - 0x0e, 0xc8, 0x01, 0x00, 0xe0, 0x00, 0x00, 0xaa, - 0xec, 0x03, 0x94, 0x00, 0x94, 0x02, 0xee, 0xd8, - 0xc7, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb4, 0x04, - 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x29, 0x02, - 0xe8, 0x05, 0x00, 0x01, 0x00, 0xfe, 0x05, 0x00, - 0x00, 0x00, 0xd3, 0x98, 0x04, 0x49, 0x00, 0x00, - 0x00, 0xb0, 0xec, 0x03, 0x09, 0x28, 0xd3, 0x43, - 0x80, 0x01, 0x00, 0x00, 0xb6, 0x24, 0x01, 0x00, - 0xcf, 0x01, 0x00, 0xdc, 0x00, 0x00, 0xaa, 0x11, - 0xec, 0x09, 0x0e, 0xc7, 0x01, 0x00, 0xe0, 0x00, - 0x00, 0xa7, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb6, - 0x04, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, 0x23, - 0x02, 0xee, 0x05, 0x00, 0x01, 0x00, 0x82, 0x06, - 0x00, 0x01, 0x00, 0xd3, 0xd4, 0x9e, 0x11, 0x04, - 0x82, 0x01, 0x00, 0x00, 0xaf, 0xed, 0x13, 0x11, - 0x04, 0x83, 0x01, 0x00, 0x00, 0xaf, 0xed, 0x0a, - 0x11, 0x04, 0x84, 0x01, 0x00, 0x00, 0xaf, 0xec, - 0x03, 0x0a, 0x28, 0x0e, 0x09, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0xb8, 0x04, 0x03, 0x03, 0x03, 0x06, - 0x03, 0x00, 0x62, 0x06, 0xf6, 0x05, 0x00, 0x01, - 0x00, 0x8a, 0x06, 0x00, 0x01, 0x00, 0x8c, 0x06, - 0x00, 0x01, 0x00, 0xe2, 0x05, 0x00, 0x00, 0x00, - 0x8e, 0x06, 0x00, 0x01, 0x00, 0x90, 0x06, 0x00, - 0x02, 0x00, 0xce, 0x03, 0x00, 0x0c, 0xde, 0x03, - 0x11, 0x01, 0xe2, 0x03, 0x13, 0x01, 0xd4, 0xcc, - 0xc8, 0xd3, 0xeb, 0xa7, 0xec, 0x5a, 0xd5, 0xc8, - 0xcf, 0x48, 0xcd, 0xc8, 0x90, 0xd0, 0xd3, 0xeb, - 0xa7, 0xec, 0x08, 0xd5, 0xc8, 0x48, 0xc9, 0xad, - 0xed, 0xf2, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0xe0, 0xe1, 0xc9, 0x48, 0x11, 0xed, - 0x07, 0x0e, 0x04, 0x8a, 0x01, 0x00, 0x00, 0x48, - 0x24, 0x01, 0x00, 0x0e, 0x66, 0x00, 0x00, 0x43, - 0x89, 0x01, 0x00, 0x00, 0xd3, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xc6, 0x24, 0x02, 0x00, 0x24, 0x01, - 0x00, 0x0e, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0xe0, 0x04, 0x8a, 0x01, 0x00, 0x00, - 0x48, 0x24, 0x01, 0x00, 0x0e, 0xee, 0xa2, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xba, 0x04, 0x02, 0x00, - 0x02, 0x05, 0x01, 0x00, 0x1d, 0x02, 0x98, 0x06, - 0x00, 0x01, 0x00, 0x9a, 0x06, 0x00, 0x01, 0x00, - 0xce, 0x03, 0x00, 0x0c, 0x66, 0x00, 0x00, 0x43, - 0x89, 0x01, 0x00, 0x00, 0x04, 0x8e, 0x01, 0x00, - 0x00, 0xd3, 0xb7, 0xae, 0xec, 0x04, 0xd3, 0xee, - 0x02, 0xc2, 0x9e, 0xd4, 0x9e, 0x24, 0x01, 0x00, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xbc, 0x04, 0x01, - 0x02, 0x01, 0x04, 0x05, 0x00, 0xa1, 0x01, 0x03, - 0x9e, 0x06, 0x00, 0x01, 0x00, 0xe2, 0x05, 0x00, - 0x00, 0x00, 0xe0, 0x05, 0x00, 0x01, 0x00, 0xa2, - 0x04, 0x33, 0x01, 0xa0, 0x04, 0x32, 0x01, 0xce, - 0x03, 0x00, 0x0c, 0xb8, 0x02, 0x0b, 0x01, 0xba, - 0x04, 0x3f, 0x01, 0xd3, 0xb6, 0xa9, 0xec, 0x4d, - 0xd3, 0xb6, 0xae, 0x6a, 0x97, 0x00, 0x00, 0x00, - 0xdf, 0xe0, 0xb7, 0x9f, 0xad, 0xec, 0x19, 0x66, - 0x02, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, - 0x90, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, - 0xb6, 0xe3, 0xd3, 0x8f, 0xd7, 0xee, 0xda, 0xe2, - 0x43, 0x91, 0x01, 0x00, 0x00, 0xe0, 0xb7, 0x9f, - 0xdf, 0x9f, 0xd3, 0x24, 0x02, 0x00, 0xcc, 0x5f, - 0x04, 0x00, 0xc8, 0x04, 0x92, 0x01, 0x00, 0x00, - 0xf2, 0x0e, 0xd3, 0xc8, 0x9f, 0xd7, 0xdf, 0xc8, - 0x9e, 0xe3, 0xee, 0xb5, 0xd3, 0x8d, 0xd7, 0xd3, - 0xb6, 0xae, 0xec, 0x48, 0xdf, 0xb6, 0xad, 0xec, - 0x22, 0x5f, 0x04, 0x00, 0xb7, 0x04, 0x75, 0x01, - 0x00, 0x00, 0xf2, 0x0e, 0x5f, 0x04, 0x00, 0xe0, - 0xb7, 0x9f, 0x04, 0x92, 0x01, 0x00, 0x00, 0xf2, - 0x0e, 0xd3, 0x8f, 0xd7, 0xe0, 0xb7, 0x9f, 0xe3, - 0xee, 0xd6, 0xe2, 0x43, 0x91, 0x01, 0x00, 0x00, - 0xd3, 0xdf, 0x24, 0x02, 0x00, 0xcc, 0x5f, 0x04, - 0x00, 0xc8, 0x04, 0x93, 0x01, 0x00, 0x00, 0xf2, - 0x0e, 0xd3, 0xc8, 0x9f, 0xd7, 0xdf, 0xc8, 0x9f, - 0xe3, 0xee, 0xb5, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xbe, 0x04, 0x00, 0x05, 0x00, 0x06, 0x0d, 0x00, - 0x9c, 0x02, 0x05, 0xe2, 0x05, 0x00, 0x00, 0x00, - 0xa8, 0x06, 0x00, 0x01, 0x00, 0xf6, 0x05, 0x00, - 0x02, 0x00, 0x8a, 0x06, 0x00, 0x03, 0x00, 0xaa, - 0x06, 0x00, 0x04, 0x00, 0x8a, 0x04, 0x27, 0x01, - 0x8e, 0x04, 0x29, 0x01, 0xe8, 0x03, 0x16, 0x01, - 0x90, 0x04, 0x2a, 0x01, 0xce, 0x03, 0x00, 0x0c, - 0xbc, 0x04, 0x40, 0x01, 0xb2, 0x04, 0x3b, 0x01, - 0x86, 0x04, 0x25, 0x01, 0xc6, 0x05, 0x85, 0x01, - 0x01, 0xb8, 0x04, 0x3e, 0x01, 0xa2, 0x04, 0x33, - 0x01, 0xa0, 0x04, 0x32, 0x01, 0x8c, 0x04, 0x28, - 0x01, 0xdf, 0xe0, 0xae, 0x6a, 0xc6, 0x00, 0x00, - 0x00, 0xe1, 0x97, 0xec, 0x32, 0xe0, 0x43, 0x8b, - 0x01, 0x00, 0x00, 0xb6, 0xe2, 0x24, 0x02, 0x00, - 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, 0xe2, - 0x24, 0x02, 0x00, 0xad, 0xec, 0x19, 0x66, 0x04, - 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0xdf, 0x43, - 0x8b, 0x01, 0x00, 0x00, 0xe2, 0x24, 0x01, 0x00, - 0x24, 0x01, 0x00, 0x0e, 0xee, 0x53, 0x5f, 0x05, - 0x00, 0x5f, 0x06, 0x00, 0xe0, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xb6, 0xe2, 0x24, 0x02, 0x00, 0xf1, - 0x8d, 0xf1, 0x0e, 0xe1, 0xec, 0x2e, 0x5f, 0x07, - 0x00, 0xec, 0x0e, 0x5f, 0x07, 0x00, 0x04, 0x90, - 0x01, 0x00, 0x00, 0x9e, 0xdf, 0x9e, 0xee, 0x02, - 0xdf, 0xd1, 0xeb, 0xdf, 0xeb, 0x9f, 0xce, 0x5f, - 0x08, 0x00, 0xc9, 0xf1, 0xc4, 0x04, 0x5f, 0x09, - 0x00, 0xc9, 0xca, 0xc3, 0x04, 0xb8, 0x48, 0xf3, - 0x0e, 0xee, 0x0e, 0x66, 0x04, 0x00, 0x43, 0x89, - 0x01, 0x00, 0x00, 0xdf, 0x24, 0x01, 0x00, 0x0e, - 0x5f, 0x0a, 0x00, 0x5f, 0x06, 0x00, 0xdf, 0xf1, - 0x9e, 0x5f, 0x0b, 0x00, 0x9d, 0x61, 0x0a, 0x00, - 0xb6, 0xad, 0xec, 0x12, 0x66, 0x04, 0x00, 0x43, - 0x89, 0x01, 0x00, 0x00, 0x04, 0x96, 0x01, 0x00, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0x66, 0x04, 0x00, - 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, 0x97, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xdf, 0xe4, - 0xdf, 0xeb, 0xe6, 0x5f, 0x0c, 0x00, 0xe2, 0xa9, - 0xec, 0x19, 0x5f, 0x05, 0x00, 0x5f, 0x06, 0x00, - 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xe2, 0x5f, - 0x0c, 0x00, 0x24, 0x02, 0x00, 0xf1, 0xf1, 0x0e, - 0xee, 0x1f, 0x5f, 0x0c, 0x00, 0xe2, 0xa7, 0xec, - 0x18, 0x5f, 0x05, 0x00, 0x5f, 0x06, 0x00, 0xdf, - 0x43, 0x8b, 0x01, 0x00, 0x00, 0x5f, 0x0c, 0x00, - 0xe2, 0x24, 0x02, 0x00, 0xf1, 0x8d, 0xf1, 0x0e, - 0x5f, 0x0c, 0x00, 0xe6, 0x66, 0x04, 0x00, 0x42, - 0x98, 0x01, 0x00, 0x00, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xc0, 0x04, 0x01, 0x00, 0x01, 0x04, 0x02, - 0x00, 0x22, 0x01, 0xf6, 0x05, 0x00, 0x01, 0x00, - 0x8a, 0x04, 0x27, 0x01, 0x8c, 0x04, 0x28, 0x01, - 0xd3, 0xec, 0x1f, 0xdf, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0xb6, 0xe0, 0x24, 0x02, 0x00, 0xd3, 0x9e, - 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xe0, 0x24, - 0x01, 0x00, 0x9e, 0xe3, 0xe0, 0xd3, 0xeb, 0x9e, - 0xe4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc2, 0x04, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, - 0x96, 0x04, 0x2d, 0x01, 0x0a, 0xe3, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xc4, 0x04, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x00, 0x07, 0x00, 0x8a, 0x04, 0x27, - 0x01, 0x8c, 0x04, 0x28, 0x01, 0xc2, 0xe3, 0xb6, - 0xe4, 0xbe, 0xfe, 0x28, 0x0c, 0x43, 0x02, 0x01, - 0xc6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc8, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, - 0x00, 0x8c, 0x04, 0x28, 0x01, 0xb6, 0xe3, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xca, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x00, 0x04, 0x00, 0x8c, 0x04, - 0x28, 0x01, 0x8a, 0x04, 0x27, 0x01, 0xe0, 0xeb, - 0xe3, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xcc, 0x04, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x1d, 0x00, - 0x8c, 0x04, 0x28, 0x01, 0x8a, 0x04, 0x27, 0x01, - 0xb4, 0x04, 0x3c, 0x01, 0xdf, 0xe0, 0xeb, 0xa7, - 0xec, 0x17, 0xdf, 0x90, 0xe3, 0xe1, 0xe0, 0x43, - 0x9a, 0x01, 0x00, 0x00, 0xdf, 0x24, 0x01, 0x00, - 0xf1, 0xec, 0x06, 0xdf, 0x90, 0xe3, 0xee, 0xee, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xce, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x1c, 0x00, 0x8c, - 0x04, 0x28, 0x01, 0xb4, 0x04, 0x3c, 0x01, 0x8a, - 0x04, 0x27, 0x01, 0xdf, 0xb6, 0xa9, 0xec, 0x17, - 0xdf, 0x8f, 0xe3, 0xe0, 0xe1, 0x43, 0x9a, 0x01, - 0x00, 0x00, 0xdf, 0x24, 0x01, 0x00, 0xf1, 0xec, - 0x06, 0xdf, 0x8f, 0xe3, 0xee, 0xee, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xd0, 0x04, 0x01, 0x00, 0x01, - 0x04, 0x02, 0x00, 0x35, 0x01, 0xb6, 0x06, 0x00, - 0x01, 0x00, 0x8a, 0x04, 0x27, 0x01, 0xb0, 0x04, - 0x3a, 0x01, 0xd3, 0xdf, 0xeb, 0xa7, 0xec, 0x15, - 0xe0, 0xdf, 0x43, 0x9a, 0x01, 0x00, 0x00, 0xd3, - 0x24, 0x01, 0x00, 0xf1, 0x97, 0xec, 0x06, 0xd3, - 0x90, 0xd7, 0xee, 0xe7, 0xd3, 0xdf, 0xeb, 0xa7, - 0xec, 0x14, 0xe0, 0xdf, 0x43, 0x9a, 0x01, 0x00, - 0x00, 0xd3, 0x24, 0x01, 0x00, 0xf1, 0xec, 0x06, - 0xd3, 0x90, 0xd7, 0xee, 0xe8, 0xd3, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0xd2, 0x04, 0x01, 0x00, 0x01, - 0x05, 0x02, 0x00, 0x37, 0x01, 0xb6, 0x06, 0x00, - 0x01, 0x00, 0xb0, 0x04, 0x3a, 0x01, 0x8a, 0x04, - 0x27, 0x01, 0xd3, 0xb6, 0xa9, 0xec, 0x17, 0xdf, - 0xe0, 0x43, 0x9a, 0x01, 0x00, 0x00, 0xd3, 0xb7, - 0x9f, 0x24, 0x01, 0x00, 0xf1, 0x97, 0xec, 0x06, - 0xd3, 0x8f, 0xd7, 0xee, 0xe6, 0xd3, 0xb6, 0xa9, - 0xec, 0x16, 0xdf, 0xe0, 0x43, 0x9a, 0x01, 0x00, - 0x00, 0xd3, 0xb7, 0x9f, 0x24, 0x01, 0x00, 0xf1, - 0xec, 0x06, 0xd3, 0x8f, 0xd7, 0xee, 0xe7, 0xd3, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xd4, 0x04, 0x00, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x05, 0x00, 0x8c, - 0x04, 0x28, 0x01, 0xd0, 0x04, 0x4a, 0x01, 0xe0, - 0xdf, 0xf1, 0xe3, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xd6, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, - 0x05, 0x00, 0x8c, 0x04, 0x28, 0x01, 0xd2, 0x04, - 0x4b, 0x01, 0xe0, 0xdf, 0xf1, 0xe3, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xd8, 0x04, 0x00, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x0e, 0x00, 0xb4, 0x05, 0x7c, - 0x01, 0xdf, 0x04, 0x9c, 0x01, 0x00, 0x00, 0x49, - 0x24, 0x00, 0x00, 0x0e, 0xbe, 0xfe, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0xda, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x17, 0x00, 0xce, 0x03, 0x00, - 0x0c, 0xdc, 0x04, 0x50, 0x01, 0x8a, 0x04, 0x27, - 0x01, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, 0x00, - 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, 0x01, - 0x00, 0x0e, 0xe0, 0xe1, 0xf1, 0x0e, 0xb5, 0x28, - 0x0c, 0x43, 0x02, 0x01, 0xdc, 0x04, 0x01, 0x00, - 0x01, 0x03, 0x02, 0x00, 0x36, 0x01, 0xf6, 0x05, - 0x00, 0x01, 0x00, 0xf2, 0x03, 0x1b, 0x01, 0xf4, - 0x03, 0x1c, 0x01, 0xd3, 0x43, 0x9d, 0x01, 0x00, - 0x00, 0x24, 0x00, 0x00, 0xdb, 0xec, 0x27, 0xdf, - 0xeb, 0xec, 0x18, 0xdf, 0xdf, 0xeb, 0xb7, 0x9f, - 0x48, 0x97, 0xec, 0x0f, 0xdf, 0x43, 0x32, 0x00, - 0x00, 0x00, 0x8f, 0x44, 0x32, 0x00, 0x00, 0x00, - 0xee, 0xe6, 0xdf, 0x43, 0x9e, 0x01, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0x0e, 0xdf, 0xeb, 0xe4, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xde, 0x04, 0x00, - 0x00, 0x00, 0x03, 0x04, 0x00, 0x20, 0x00, 0xf4, - 0x03, 0x1c, 0x01, 0xf2, 0x03, 0x1b, 0x01, 0x8a, - 0x04, 0x27, 0x01, 0x8c, 0x04, 0x28, 0x01, 0xdf, - 0xb6, 0xa9, 0xec, 0x1b, 0xdf, 0xe0, 0xeb, 0xad, - 0xec, 0x0c, 0xe0, 0x43, 0x9e, 0x01, 0x00, 0x00, - 0xe1, 0x24, 0x01, 0x00, 0x0e, 0xdf, 0x8f, 0xe3, - 0xe0, 0xdf, 0x48, 0xe9, 0xeb, 0xe6, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xe0, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x04, 0x00, 0x12, 0x00, 0xf4, 0x03, 0x1c, - 0x01, 0xf2, 0x03, 0x1b, 0x01, 0x8a, 0x04, 0x27, - 0x01, 0x8c, 0x04, 0x28, 0x01, 0xdf, 0xe0, 0xeb, - 0xb7, 0x9f, 0xa7, 0xec, 0x0a, 0xdf, 0x90, 0xe3, - 0xe0, 0xdf, 0x48, 0xe9, 0xeb, 0xe6, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xe2, 0x04, 0x01, 0x03, 0x01, - 0x05, 0x04, 0x00, 0x3d, 0x04, 0xbe, 0x06, 0x00, - 0x01, 0x00, 0xb6, 0x06, 0x00, 0x00, 0x00, 0xe2, - 0x05, 0x00, 0x01, 0x00, 0xb0, 0x01, 0x00, 0x02, - 0x00, 0x8c, 0x04, 0x28, 0x01, 0xf2, 0x03, 0x1b, - 0x01, 0xf4, 0x03, 0x1c, 0x01, 0x8a, 0x04, 0x27, - 0x01, 0xdf, 0xcb, 0xb7, 0xcc, 0xc8, 0xe0, 0xeb, - 0xa8, 0xec, 0x33, 0xe0, 0xeb, 0xc8, 0xd3, 0x9b, - 0x9e, 0xe1, 0x9e, 0xe0, 0xeb, 0x9d, 0xcd, 0xe0, - 0xc9, 0x48, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, - 0xc7, 0x24, 0x02, 0x00, 0xe2, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xb6, 0xc7, 0x24, 0x02, 0x00, 0xad, - 0xec, 0x08, 0xc9, 0xe5, 0xe0, 0xc9, 0x48, 0xe6, - 0x29, 0x94, 0x01, 0xee, 0xc9, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xe4, 0x04, 0x00, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x05, 0x00, 0xe2, 0x04, 0x53, 0x01, - 0xdf, 0xb5, 0x23, 0x01, 0x00, 0x0c, 0x43, 0x02, - 0x01, 0xe6, 0x04, 0x00, 0x00, 0x00, 0x02, 0x01, - 0x00, 0x05, 0x00, 0xe2, 0x04, 0x53, 0x01, 0xdf, - 0xb7, 0x23, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, - 0xe8, 0x04, 0x01, 0x02, 0x01, 0x04, 0x05, 0x00, - 0x65, 0x03, 0xbe, 0x06, 0x00, 0x01, 0x00, 0x8a, - 0x06, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x00, 0x01, - 0x00, 0x8c, 0x04, 0x28, 0x01, 0xb4, 0x04, 0x3c, - 0x01, 0x8a, 0x04, 0x27, 0x01, 0x94, 0x04, 0x2c, - 0x01, 0xf8, 0x04, 0x5e, 0x01, 0xdf, 0xcb, 0xd3, - 0xb6, 0xa7, 0xec, 0x15, 0x93, 0x00, 0xe0, 0xe1, - 0x43, 0x9a, 0x01, 0x00, 0x00, 0xc7, 0x24, 0x01, - 0x00, 0xf1, 0xec, 0x05, 0x93, 0x00, 0xee, 0xef, - 0xc7, 0xb7, 0x9e, 0xcc, 0xe0, 0xe1, 0x43, 0x9a, - 0x01, 0x00, 0x00, 0xc8, 0x24, 0x01, 0x00, 0xf1, - 0xec, 0x05, 0x94, 0x01, 0xee, 0xef, 0xc7, 0xb6, - 0xaa, 0xec, 0x2f, 0xc7, 0xe1, 0xeb, 0xa7, 0xec, - 0x29, 0xe2, 0x5f, 0x04, 0x00, 0xaf, 0xec, 0x09, - 0x5f, 0x04, 0x00, 0xc6, 0xd3, 0xf3, 0x0e, 0x29, - 0xe1, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, 0xc7, - 0x24, 0x02, 0x00, 0xe1, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0xc8, 0x24, 0x01, 0x00, 0x9e, 0xe5, 0xc7, - 0xe3, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xea, 0x04, - 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, - 0xe8, 0x04, 0x56, 0x01, 0xdf, 0xb7, 0xf1, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xec, 0x04, 0x00, 0x00, - 0x00, 0x03, 0x03, 0x00, 0x1f, 0x00, 0x8a, 0x04, - 0x27, 0x01, 0xce, 0x03, 0x00, 0x0c, 0xe8, 0x04, - 0x56, 0x01, 0xdf, 0xeb, 0xb6, 0xad, 0xec, 0x15, - 0x66, 0x01, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, - 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0xbe, 0xfd, 0x28, 0xe1, 0xb7, 0xf1, 0x0e, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xee, 0x04, 0x00, - 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0xe8, - 0x04, 0x56, 0x01, 0xdf, 0xb5, 0xf1, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xf0, 0x04, 0x00, 0x01, 0x00, - 0x06, 0x02, 0x00, 0x51, 0x01, 0xb6, 0x06, 0x00, - 0x00, 0x00, 0x8c, 0x04, 0x28, 0x01, 0x8a, 0x04, - 0x27, 0x01, 0xdf, 0xcb, 0xe0, 0xeb, 0xb7, 0xa9, - 0xec, 0x49, 0xc7, 0xb6, 0xa9, 0xec, 0x44, 0xc7, - 0xe0, 0xeb, 0xad, 0xec, 0x03, 0x93, 0x00, 0xe0, - 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, 0xc7, 0xb7, - 0x9f, 0x24, 0x02, 0x00, 0xe0, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xc7, 0xc7, 0xb7, 0x9e, 0x24, 0x02, - 0x00, 0x9e, 0xe0, 0x43, 0x8b, 0x01, 0x00, 0x00, - 0xc7, 0xb7, 0x9f, 0xc7, 0x24, 0x02, 0x00, 0x9e, - 0xe0, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xc7, 0xb7, - 0x9e, 0x24, 0x01, 0x00, 0x9e, 0xe4, 0xc7, 0xb7, - 0x9e, 0xe3, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf2, - 0x04, 0x00, 0x04, 0x00, 0x05, 0x04, 0x00, 0x55, - 0x04, 0xc2, 0x06, 0x00, 0x00, 0x00, 0xc4, 0x06, - 0x00, 0x01, 0x00, 0xc6, 0x06, 0x00, 0x02, 0x00, - 0xc8, 0x06, 0x00, 0x03, 0x00, 0xd2, 0x04, 0x4b, - 0x01, 0x8c, 0x04, 0x28, 0x01, 0xd0, 0x04, 0x4a, - 0x01, 0x8a, 0x04, 0x27, 0x01, 0xdf, 0xe0, 0xf1, - 0xcb, 0xe1, 0xc7, 0xf1, 0xcc, 0xe1, 0xe0, 0xf1, - 0xcd, 0xdf, 0xc9, 0xf1, 0xce, 0xc6, 0xa7, 0xec, - 0x41, 0xc8, 0xe0, 0xa8, 0xec, 0x3c, 0xe0, 0xca, - 0xa8, 0xec, 0x37, 0xca, 0xc9, 0xa7, 0xec, 0x32, - 0xe2, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, 0xc7, - 0x24, 0x02, 0x00, 0xe2, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0xca, 0xc9, 0x24, 0x02, 0x00, 0x9e, 0xe2, - 0x43, 0x8b, 0x01, 0x00, 0x00, 0xc8, 0xca, 0x24, - 0x02, 0x00, 0x9e, 0xe2, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0xc6, 0x24, 0x02, 0x00, 0x9e, 0xe6, 0xc9, - 0xe4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf4, 0x04, - 0x00, 0x01, 0x00, 0x05, 0x03, 0x00, 0x30, 0x01, - 0xc0, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x04, 0x4a, - 0x01, 0x8c, 0x04, 0x28, 0x01, 0x8a, 0x04, 0x27, - 0x01, 0xdf, 0xe0, 0xf1, 0xcb, 0xe1, 0x43, 0x8b, - 0x01, 0x00, 0x00, 0xb6, 0xe0, 0x24, 0x02, 0x00, - 0xe1, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xe0, 0xc7, - 0x24, 0x02, 0x00, 0x43, 0xa5, 0x01, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x9e, 0xe1, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xc7, 0x24, 0x01, 0x00, 0x9e, 0xe5, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf6, 0x04, 0x00, - 0x01, 0x00, 0x05, 0x03, 0x00, 0x30, 0x01, 0xc0, - 0x06, 0x00, 0x00, 0x00, 0xd0, 0x04, 0x4a, 0x01, - 0x8c, 0x04, 0x28, 0x01, 0x8a, 0x04, 0x27, 0x01, - 0xdf, 0xe0, 0xf1, 0xcb, 0xe1, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xb6, 0xe0, 0x24, 0x02, 0x00, 0xe1, - 0x43, 0x8b, 0x01, 0x00, 0x00, 0xe0, 0xc7, 0x24, - 0x02, 0x00, 0x43, 0xa6, 0x01, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x9e, 0xe1, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0xc7, 0x24, 0x01, 0x00, 0x9e, 0xe5, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xf8, 0x04, 0x03, 0x01, - 0x03, 0x04, 0x06, 0x00, 0x5e, 0x04, 0x8a, 0x06, - 0x00, 0x01, 0x00, 0xc0, 0x06, 0x00, 0x01, 0x00, - 0xbe, 0x06, 0x00, 0x01, 0x00, 0xce, 0x06, 0x00, - 0x00, 0x00, 0x8a, 0x04, 0x27, 0x01, 0x94, 0x04, - 0x2c, 0x01, 0xf8, 0x04, 0x5e, 0x01, 0xf6, 0x03, - 0x1d, 0x01, 0x8c, 0x04, 0x28, 0x01, 0x92, 0x04, - 0x2b, 0x01, 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, - 0xd3, 0xd4, 0x24, 0x02, 0x00, 0xcb, 0xe0, 0xe1, - 0xb0, 0xec, 0x05, 0xc7, 0xe6, 0xee, 0x10, 0xd5, - 0xb6, 0xa7, 0xec, 0x07, 0xc7, 0xe2, 0x9e, 0xe6, - 0xee, 0x05, 0xe2, 0xc7, 0x9e, 0xe6, 0xdf, 0x43, - 0x8b, 0x01, 0x00, 0x00, 0xb6, 0xd3, 0x24, 0x02, - 0x00, 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xd4, - 0x24, 0x01, 0x00, 0x9e, 0xe3, 0x5f, 0x04, 0x00, - 0xd4, 0xa9, 0xec, 0x0d, 0x5f, 0x04, 0x00, 0xd4, - 0xd3, 0x9f, 0x9f, 0x60, 0x04, 0x00, 0xee, 0x0c, - 0x5f, 0x04, 0x00, 0xd3, 0xa9, 0xec, 0x05, 0xd3, - 0x60, 0x04, 0x00, 0xe1, 0x60, 0x05, 0x00, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xfa, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x07, 0x00, 0xf8, 0x04, - 0x5e, 0x01, 0x8c, 0x04, 0x28, 0x01, 0x8a, 0x04, - 0x27, 0x01, 0xdf, 0xe0, 0xe1, 0xeb, 0xb7, 0xf3, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xfc, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x02, 0x00, 0x06, 0x00, 0xf8, - 0x04, 0x5e, 0x01, 0x8c, 0x04, 0x28, 0x01, 0xdf, - 0xb6, 0xe0, 0xb5, 0xf3, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x08, 0x00, 0xf8, 0x04, 0x5e, 0x01, 0x8c, - 0x04, 0x28, 0x01, 0xd0, 0x04, 0x4a, 0x01, 0xdf, - 0xe0, 0xe1, 0xe0, 0xf1, 0xb7, 0xf3, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0x80, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x08, 0x00, 0xf8, 0x04, 0x5e, - 0x01, 0xd2, 0x04, 0x4b, 0x01, 0x8c, 0x04, 0x28, - 0x01, 0xdf, 0xe0, 0xe1, 0xf1, 0xe1, 0xb5, 0xf3, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0x82, 0x05, 0x00, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x04, 0x00, 0xc0, - 0x04, 0x42, 0x01, 0xf6, 0x03, 0x1d, 0x01, 0xdf, - 0xe0, 0xf1, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x84, - 0x05, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x32, - 0x00, 0x94, 0x04, 0x2c, 0x01, 0x84, 0x05, 0x64, - 0x01, 0xce, 0x03, 0x00, 0x0c, 0xb0, 0x05, 0x7a, - 0x01, 0x9a, 0x05, 0x6f, 0x01, 0xdf, 0xe0, 0xaf, - 0xec, 0x17, 0x66, 0x02, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0xe2, 0xb6, 0xf1, 0x0e, 0x29, - 0x66, 0x02, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, - 0x04, 0xa8, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0x5f, 0x04, 0x00, 0xf0, 0x0e, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0x86, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x00, 0x05, 0x00, 0x8a, 0x04, 0x27, - 0x01, 0x8c, 0x04, 0x28, 0x01, 0xc2, 0xe3, 0xb6, - 0xe4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x88, 0x05, - 0x02, 0x01, 0x02, 0x04, 0x01, 0x00, 0x1f, 0x03, - 0xd2, 0x06, 0x00, 0x01, 0x00, 0xc0, 0x06, 0x00, - 0x01, 0x00, 0xb6, 0x06, 0x00, 0x00, 0x00, 0xb0, - 0x04, 0x3a, 0x01, 0xd4, 0xcb, 0xc7, 0xb6, 0xa9, - 0xec, 0x0e, 0xdf, 0xd3, 0xc7, 0xb7, 0x9f, 0x48, - 0xf1, 0xec, 0x05, 0x93, 0x00, 0xee, 0xef, 0xd3, - 0x43, 0xaa, 0x01, 0x00, 0x00, 0xc7, 0xd4, 0x25, - 0x02, 0x00, 0x0c, 0x43, 0x02, 0x01, 0x8a, 0x05, - 0x02, 0x04, 0x02, 0x05, 0x07, 0x04, 0x9f, 0x02, - 0x06, 0xd2, 0x06, 0x00, 0x01, 0x00, 0xb6, 0x06, - 0x00, 0x01, 0x00, 0xe8, 0x05, 0x00, 0x00, 0x00, - 0xd6, 0x06, 0x00, 0x01, 0x00, 0xd8, 0x06, 0x00, - 0x02, 0x00, 0xda, 0x06, 0x00, 0x03, 0x00, 0xd4, - 0x03, 0x00, 0x03, 0xb4, 0x05, 0x7c, 0x01, 0xb0, - 0x04, 0x3a, 0x01, 0x88, 0x05, 0x66, 0x01, 0xd8, - 0x03, 0x0e, 0x01, 0x8a, 0x05, 0x67, 0x01, 0xc4, - 0x02, 0x08, 0x01, 0x07, 0x02, 0x20, 0x07, 0x34, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x09, 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, - 0xff, 0xff, 0xff, 0x0c, 0x00, 0x01, 0x20, 0x0d, - 0x00, 0x0b, 0x07, 0x1a, 0x5e, 0x5b, 0x64, 0x67, - 0x69, 0x6d, 0x73, 0x75, 0x76, 0x79, 0x5d, 0x2b, - 0x24, 0x07, 0x96, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x43, 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, - 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, - 0x00, 0x06, 0x1d, 0x20, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, - 0x00, 0x00, 0x00, 0x16, 0x07, 0x00, 0x64, 0x00, - 0x64, 0x00, 0x67, 0x00, 0x67, 0x00, 0x69, 0x00, - 0x69, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x75, 0x00, 0x76, 0x00, 0x79, 0x00, - 0x79, 0x00, 0x0b, 0x07, 0x0d, 0x00, 0x0b, 0xd4, - 0xb6, 0xa8, 0xec, 0x03, 0xdf, 0x28, 0xd3, 0xd4, - 0xb7, 0x9f, 0x48, 0xcb, 0xd4, 0xb7, 0xaf, 0xec, - 0x17, 0xc7, 0x04, 0xae, 0x01, 0x00, 0x00, 0xaf, - 0x11, 0xed, 0x09, 0x0e, 0xc7, 0x04, 0xaf, 0x01, - 0x00, 0x00, 0xaf, 0xec, 0x03, 0xe0, 0x28, 0x04, - 0xb0, 0x01, 0x00, 0x00, 0x43, 0xb1, 0x01, 0x00, - 0x00, 0xc7, 0x24, 0x01, 0x00, 0xb6, 0xaa, 0xec, - 0x02, 0x29, 0xc7, 0x04, 0xaf, 0x01, 0x00, 0x00, - 0xaf, 0x6a, 0xda, 0x00, 0x00, 0x00, 0xd4, 0x8f, - 0xd8, 0xd3, 0xd4, 0xb7, 0x9f, 0x48, 0xcf, 0x11, - 0x04, 0xb2, 0x01, 0x00, 0x00, 0xaf, 0xed, 0x13, - 0x11, 0x04, 0xb3, 0x01, 0x00, 0x00, 0xaf, 0xed, - 0x0a, 0x11, 0x04, 0xb4, 0x01, 0x00, 0x00, 0xaf, - 0xec, 0x07, 0x04, 0x77, 0x01, 0x00, 0x00, 0x28, - 0x11, 0x04, 0xb5, 0x01, 0x00, 0x00, 0xaf, 0xec, - 0x05, 0x26, 0x00, 0x00, 0x28, 0x11, 0x04, 0xb6, - 0x01, 0x00, 0x00, 0xaf, 0xec, 0x07, 0xc0, 0x00, - 0xc0, 0x01, 0x34, 0x28, 0xe1, 0xc7, 0xf1, 0x6a, - 0x89, 0x00, 0x00, 0x00, 0xe2, 0xd3, 0xd4, 0xf2, - 0xcc, 0xd4, 0xc8, 0xeb, 0x9f, 0xcd, 0xc8, 0x04, - 0x03, 0x00, 0x00, 0x00, 0xaf, 0x11, 0xed, 0x09, - 0x0e, 0xc8, 0x04, 0x02, 0x00, 0x00, 0x00, 0xaf, - 0xec, 0x03, 0x0a, 0x28, 0xc8, 0x04, 0x01, 0x00, - 0x00, 0x00, 0xaf, 0xec, 0x03, 0x07, 0x28, 0xc8, - 0x04, 0x08, 0x00, 0x00, 0x00, 0xaf, 0xec, 0x03, - 0xdf, 0x28, 0x5f, 0x04, 0x00, 0xc8, 0x8e, 0xf1, - 0x97, 0xec, 0x03, 0xb6, 0x28, 0x5f, 0x05, 0x00, - 0xd3, 0xc9, 0xf2, 0xd2, 0xf5, 0x11, 0xed, 0x04, - 0x0e, 0xca, 0xf4, 0xec, 0x03, 0xca, 0x28, 0xca, - 0xc8, 0x48, 0xf6, 0xed, 0x05, 0xca, 0xc8, 0x48, - 0x28, 0xc9, 0xb9, 0xaa, 0xec, 0x24, 0xd3, 0xc9, - 0xb7, 0x9f, 0x48, 0x04, 0xb6, 0x01, 0x00, 0x00, - 0xaf, 0xec, 0x17, 0xc8, 0x43, 0xb7, 0x01, 0x00, - 0x00, 0xc0, 0x02, 0xc0, 0x03, 0x34, 0x24, 0x01, - 0x00, 0xec, 0x07, 0x5f, 0x06, 0x00, 0x23, 0x00, - 0x00, 0x0e, 0x0b, 0x28, 0xdf, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0x8c, 0x05, 0x02, 0x0a, 0x02, 0x04, - 0x03, 0x01, 0xee, 0x01, 0x0c, 0xd2, 0x06, 0x00, - 0x01, 0x00, 0xb6, 0x06, 0x00, 0x01, 0x00, 0xce, - 0x06, 0x00, 0x00, 0x00, 0xda, 0x06, 0x00, 0x01, - 0x00, 0xf0, 0x06, 0x00, 0x02, 0x00, 0xf2, 0x06, - 0x00, 0x03, 0x00, 0xe2, 0x05, 0x00, 0x04, 0x00, - 0x8e, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x06, 0x00, - 0x06, 0x00, 0xf6, 0x06, 0x00, 0x07, 0x00, 0xf8, - 0x06, 0x00, 0x08, 0x00, 0xfa, 0x06, 0x08, 0x00, - 0x21, 0x88, 0x05, 0x66, 0x01, 0x8a, 0x05, 0x67, - 0x01, 0xa8, 0x02, 0x00, 0x01, 0x0c, 0x43, 0x02, - 0x01, 0xfa, 0x06, 0x02, 0x00, 0x02, 0x03, 0x00, - 0x00, 0x34, 0x02, 0xee, 0x05, 0x00, 0x01, 0x00, - 0x82, 0x06, 0x00, 0x01, 0x00, 0xd3, 0xb6, 0x48, - 0xd4, 0xb6, 0x48, 0xae, 0xec, 0x1b, 0xd3, 0xb6, - 0x48, 0x04, 0x79, 0x01, 0x00, 0x00, 0xad, 0xec, - 0x03, 0xb7, 0x28, 0xd4, 0xb6, 0x48, 0x04, 0x79, - 0x01, 0x00, 0x00, 0xad, 0xec, 0x03, 0xb5, 0x28, - 0xd3, 0xd4, 0xa7, 0xec, 0x03, 0xb5, 0x28, 0xd3, - 0xd4, 0xa9, 0xec, 0x04, 0xb7, 0x8e, 0x28, 0xb6, - 0x28, 0xdf, 0xd3, 0xd4, 0xf2, 0xcb, 0xe0, 0xd3, - 0xd4, 0xc7, 0xeb, 0x9f, 0xf2, 0xcd, 0x26, 0x00, - 0x00, 0xce, 0xb6, 0xc4, 0x04, 0xc9, 0xcc, 0xc3, - 0x04, 0xbe, 0x0a, 0xa7, 0xec, 0x67, 0xc8, 0xf5, - 0xed, 0x63, 0xc8, 0x06, 0xb0, 0xec, 0x5e, 0xe1, - 0x43, 0xbe, 0x01, 0x00, 0x00, 0xc8, 0x24, 0x01, - 0x00, 0xc4, 0x07, 0xb6, 0xc4, 0x05, 0xc3, 0x05, - 0xc3, 0x07, 0xeb, 0xa7, 0xec, 0x38, 0xc3, 0x07, - 0xc3, 0x05, 0x48, 0xc5, 0x08, 0x98, 0x04, 0x49, - 0x00, 0x00, 0x00, 0xad, 0xec, 0x24, 0xc2, 0xc3, - 0x08, 0x8e, 0x9e, 0xc3, 0x08, 0xae, 0xec, 0x1a, - 0xc3, 0x08, 0x43, 0xbf, 0x01, 0x00, 0x00, 0xc7, - 0x24, 0x01, 0x00, 0xec, 0x0d, 0xca, 0x43, 0x9e, - 0x01, 0x00, 0x00, 0xc3, 0x08, 0x24, 0x01, 0x00, - 0x0e, 0x94, 0x05, 0xee, 0xc2, 0xe1, 0x43, 0x60, - 0x00, 0x00, 0x00, 0xc8, 0x24, 0x01, 0x00, 0xcc, - 0x94, 0x04, 0xee, 0x94, 0xca, 0xeb, 0xb7, 0xa9, - 0xec, 0x51, 0xc1, 0x00, 0xc4, 0x09, 0xc1, 0x00, - 0x0e, 0xca, 0x43, 0xc0, 0x01, 0x00, 0x00, 0x63, - 0x09, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xb7, 0xc5, - 0x05, 0xc4, 0x04, 0xc3, 0x04, 0xca, 0xeb, 0xa7, - 0xec, 0x29, 0xca, 0xc3, 0x04, 0x48, 0xca, 0xc3, - 0x04, 0xb7, 0x9f, 0x48, 0xae, 0xec, 0x18, 0xca, - 0xc3, 0x05, 0x92, 0xc4, 0x05, 0x1b, 0x11, 0xb1, - 0xed, 0x04, 0x1b, 0x72, 0x1b, 0x1b, 0xca, 0xc3, - 0x04, 0x48, 0x1b, 0x72, 0x1b, 0x4a, 0x94, 0x04, - 0xee, 0xd2, 0xca, 0xc3, 0x05, 0x44, 0x32, 0x00, - 0x00, 0x00, 0x0b, 0xca, 0x4d, 0x68, 0x01, 0x00, - 0x00, 0xc7, 0xeb, 0x4d, 0x9b, 0x01, 0x00, 0x00, - 0xc9, 0x4d, 0xc1, 0x01, 0x00, 0x00, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0x8e, 0x05, 0x00, 0x0d, 0x00, - 0x07, 0x0a, 0x00, 0x8f, 0x03, 0x0d, 0xd0, 0x05, - 0x00, 0x00, 0x00, 0x84, 0x07, 0x00, 0x01, 0x00, - 0xce, 0x06, 0x00, 0x02, 0x00, 0xe2, 0x05, 0x00, - 0x03, 0x00, 0x8e, 0x06, 0x00, 0x04, 0x00, 0xf8, - 0x05, 0x00, 0x05, 0x00, 0x86, 0x07, 0x00, 0x06, - 0x00, 0x88, 0x07, 0x00, 0x07, 0x00, 0x8a, 0x07, - 0x00, 0x08, 0x00, 0x8c, 0x07, 0x00, 0x09, 0x00, - 0x8e, 0x07, 0x00, 0x0a, 0x00, 0x90, 0x07, 0x00, - 0x0b, 0x00, 0x92, 0x07, 0x00, 0x0c, 0x00, 0x8c, - 0x05, 0x68, 0x01, 0x8a, 0x04, 0x27, 0x01, 0x8c, - 0x04, 0x28, 0x01, 0xc0, 0x04, 0x42, 0x01, 0x94, - 0x04, 0x2c, 0x01, 0x8e, 0x05, 0x69, 0x01, 0xb8, - 0x02, 0x0b, 0x01, 0xa0, 0x04, 0x32, 0x01, 0xce, - 0x03, 0x00, 0x0c, 0x9a, 0x05, 0x6f, 0x01, 0xdf, - 0xe0, 0xe1, 0xf2, 0xd0, 0x42, 0x68, 0x01, 0x00, - 0x00, 0xcf, 0xeb, 0xb6, 0xaf, 0xec, 0x02, 0x29, - 0xc7, 0xb6, 0x48, 0xd1, 0xeb, 0xc4, 0x05, 0xb7, - 0xce, 0xca, 0xc7, 0xeb, 0xa7, 0xec, 0x2a, 0xc7, - 0xca, 0x48, 0xc4, 0x06, 0xb6, 0xc4, 0x04, 0xc3, - 0x04, 0xc3, 0x05, 0xa7, 0xec, 0x17, 0xc3, 0x06, - 0xc3, 0x04, 0x48, 0xc9, 0xc3, 0x04, 0x48, 0xb0, - 0xec, 0x07, 0xc3, 0x04, 0xc4, 0x05, 0xee, 0x05, - 0x94, 0x04, 0xee, 0xe4, 0x94, 0x03, 0xee, 0xd2, - 0xc8, 0x42, 0x9b, 0x01, 0x00, 0x00, 0xce, 0xca, - 0xc3, 0x05, 0xa7, 0xec, 0x0b, 0xe2, 0xc9, 0xca, - 0x48, 0xf1, 0x0e, 0x94, 0x03, 0xee, 0xf1, 0x5f, - 0x04, 0x00, 0x5f, 0x05, 0x00, 0xaf, 0xec, 0x42, - 0xc7, 0xeb, 0xb7, 0xad, 0xec, 0x3c, 0xc8, 0x42, - 0xc1, 0x01, 0x00, 0x00, 0xc7, 0xb6, 0x48, 0x48, - 0xc5, 0x0c, 0xf7, 0xec, 0x1a, 0xe2, 0x04, 0xca, - 0x01, 0x00, 0x00, 0xf1, 0x0e, 0xc3, 0x0c, 0xeb, - 0xb6, 0xad, 0xec, 0x1e, 0xe2, 0x04, 0xcb, 0x01, - 0x00, 0x00, 0xf1, 0x0e, 0xee, 0x14, 0xc3, 0x0c, - 0x98, 0x04, 0x4a, 0x00, 0x00, 0x00, 0xad, 0xec, - 0x09, 0xe2, 0x04, 0xaf, 0x01, 0x00, 0x00, 0xf1, - 0x0e, 0x5f, 0x04, 0x00, 0x5f, 0x05, 0x00, 0xaf, - 0x6a, 0xdc, 0x00, 0x00, 0x00, 0xc7, 0xeb, 0xb8, - 0xaa, 0x6a, 0xd3, 0x00, 0x00, 0x00, 0xb6, 0xc4, - 0x07, 0xb6, 0xce, 0xca, 0xc7, 0xeb, 0xa7, 0xec, - 0x18, 0x5f, 0x06, 0x00, 0x43, 0xcc, 0x01, 0x00, - 0x00, 0xc3, 0x07, 0xc7, 0xca, 0x48, 0xeb, 0x24, - 0x02, 0x00, 0xc4, 0x07, 0x94, 0x03, 0xee, 0xe4, - 0xb8, 0x95, 0x07, 0x5f, 0x06, 0x00, 0x43, 0xcc, - 0x01, 0x00, 0x00, 0xb7, 0x5f, 0x06, 0x00, 0x43, - 0xcd, 0x01, 0x00, 0x00, 0x5f, 0x07, 0x00, 0xb7, - 0x9e, 0xc3, 0x07, 0x9c, 0x24, 0x01, 0x00, 0x24, - 0x02, 0x00, 0xc4, 0x09, 0x5f, 0x06, 0x00, 0x43, - 0xce, 0x01, 0x00, 0x00, 0xc7, 0xeb, 0xc3, 0x09, - 0x9c, 0x24, 0x01, 0x00, 0xc4, 0x0b, 0x66, 0x08, - 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, 0x90, - 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xb6, - 0xc4, 0x0a, 0xc3, 0x0a, 0xc3, 0x0b, 0xa7, 0xec, - 0x58, 0xb6, 0xc4, 0x08, 0xc3, 0x08, 0xc3, 0x09, - 0xa7, 0xec, 0x39, 0xc3, 0x08, 0xc3, 0x0b, 0x9b, - 0xc3, 0x0a, 0x9e, 0xd2, 0xc7, 0xeb, 0xaa, 0xed, - 0x2b, 0xc7, 0xca, 0x48, 0xcd, 0xc3, 0x08, 0xc3, - 0x09, 0xb7, 0x9f, 0xae, 0xec, 0x0d, 0xc9, 0x43, - 0xcf, 0x01, 0x00, 0x00, 0xc3, 0x07, 0x24, 0x01, - 0x00, 0xcd, 0x66, 0x08, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0xc9, 0x24, 0x01, 0x00, 0x0e, 0x94, - 0x08, 0xee, 0xc2, 0x66, 0x08, 0x00, 0x43, 0x89, - 0x01, 0x00, 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x0e, 0x94, 0x0a, 0xee, 0xa3, - 0x5f, 0x09, 0x00, 0xf0, 0x0e, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0x92, 0x05, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x10, 0x03, 0xf6, 0x05, 0x00, 0x01, - 0x00, 0xa0, 0x07, 0x00, 0x01, 0x00, 0x84, 0x07, - 0x00, 0x00, 0x00, 0xc2, 0xcb, 0xd4, 0x91, 0xd8, - 0xb6, 0xa9, 0xec, 0x06, 0xd3, 0x95, 0x00, 0xee, - 0xf5, 0xc7, 0x28, 0x0c, 0x43, 0x02, 0x01, 0x9a, - 0x05, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x1e, - 0x00, 0xce, 0x03, 0x00, 0x0c, 0xfa, 0x03, 0x1f, - 0x01, 0xa2, 0x04, 0x33, 0x01, 0xb2, 0x04, 0x3b, - 0x01, 0xa0, 0x04, 0x32, 0x01, 0x8e, 0x04, 0x29, - 0x01, 0x90, 0x04, 0x2a, 0x01, 0x66, 0x00, 0x00, - 0x43, 0x89, 0x01, 0x00, 0x00, 0xe0, 0x24, 0x01, - 0x00, 0x0e, 0xe2, 0xe0, 0xf1, 0x5f, 0x04, 0x00, - 0x9d, 0xe5, 0xc2, 0x60, 0x05, 0x00, 0xb6, 0x60, - 0x06, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9c, - 0x05, 0x02, 0x01, 0x02, 0x05, 0x11, 0x00, 0x80, - 0x01, 0x03, 0xa2, 0x07, 0x00, 0x01, 0x00, 0xa4, - 0x07, 0x00, 0x01, 0x00, 0x86, 0x07, 0x00, 0x00, - 0x00, 0x8a, 0x04, 0x27, 0x01, 0x8c, 0x04, 0x28, - 0x01, 0xf4, 0x03, 0x1c, 0x01, 0xf2, 0x03, 0x1b, - 0x01, 0x98, 0x05, 0x6e, 0x01, 0xfa, 0x03, 0x1f, - 0x01, 0xf8, 0x03, 0x1e, 0x01, 0x86, 0x04, 0x25, - 0x01, 0x92, 0x05, 0x6b, 0x01, 0xfc, 0x03, 0x20, - 0x01, 0x80, 0x04, 0x22, 0x01, 0xe6, 0x03, 0x15, - 0x01, 0x84, 0x04, 0x24, 0x01, 0xfe, 0x03, 0x21, - 0x01, 0x9a, 0x05, 0x6f, 0x01, 0xbe, 0x04, 0x41, - 0x01, 0x96, 0x05, 0x6d, 0x01, 0xd3, 0x11, 0xed, - 0x03, 0x0e, 0xc2, 0xe7, 0xeb, 0xe4, 0xe2, 0xeb, - 0xe5, 0xd4, 0x60, 0x04, 0x00, 0x5f, 0x06, 0x00, - 0x60, 0x05, 0x00, 0x5f, 0x07, 0x00, 0xec, 0x22, - 0x5f, 0x05, 0x00, 0x5f, 0x08, 0x00, 0x04, 0xd3, - 0x01, 0x00, 0x00, 0x5f, 0x09, 0x00, 0x5f, 0x05, - 0x00, 0xeb, 0x9f, 0xf2, 0x9e, 0x61, 0x05, 0x00, - 0x5f, 0x0a, 0x00, 0x9e, 0x60, 0x05, 0x00, 0xee, - 0x36, 0x5f, 0x0b, 0x00, 0xec, 0x20, 0x5f, 0x0c, - 0x00, 0xbf, 0xe8, 0x03, 0x9c, 0xcb, 0x5f, 0x05, - 0x00, 0xc7, 0x43, 0xd4, 0x01, 0x00, 0x00, 0xbc, - 0x24, 0x01, 0x00, 0x04, 0xd3, 0x01, 0x00, 0x00, - 0x9e, 0x9e, 0x60, 0x05, 0x00, 0x5f, 0x05, 0x00, - 0xeb, 0x60, 0x09, 0x00, 0x5f, 0x05, 0x00, 0x5f, - 0x0d, 0x00, 0x9e, 0x60, 0x05, 0x00, 0x5f, 0x0e, - 0x00, 0xf0, 0x0e, 0x5f, 0x0f, 0x00, 0xf0, 0x0e, - 0xb6, 0x60, 0x10, 0x00, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0x9e, 0x05, 0x01, 0x01, 0x01, 0x03, 0x04, - 0x02, 0x86, 0x01, 0x02, 0xaa, 0x07, 0x00, 0x01, - 0x00, 0xe8, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x02, - 0x01, 0x01, 0x96, 0x05, 0x6d, 0x01, 0x94, 0x05, - 0x6c, 0x01, 0xa0, 0x05, 0x72, 0x01, 0x07, 0x02, - 0x30, 0x07, 0x02, 0x39, 0xdf, 0x43, 0xd6, 0x01, - 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0xcb, 0xe0, - 0x11, 0xb6, 0xaf, 0xec, 0x14, 0xc7, 0x04, 0xd7, - 0x01, 0x00, 0x00, 0xad, 0xec, 0x06, 0xc7, 0xe5, - 0xb7, 0xe4, 0x29, 0xe2, 0xc7, 0xf1, 0x0e, 0x29, - 0x11, 0xb7, 0xaf, 0xec, 0x24, 0xe1, 0xc7, 0x9e, - 0xe5, 0xc7, 0x04, 0xd8, 0x01, 0x00, 0x00, 0xad, - 0xec, 0x04, 0xb8, 0xe4, 0x29, 0xc7, 0x04, 0xd9, - 0x01, 0x00, 0x00, 0xad, 0xec, 0x04, 0xb9, 0xe4, - 0x29, 0xe2, 0xe1, 0xf1, 0x0e, 0xb6, 0xe4, 0x29, - 0x11, 0xb8, 0xaf, 0xec, 0x26, 0xe1, 0xc7, 0x9e, - 0xe5, 0xc7, 0x04, 0xda, 0x01, 0x00, 0x00, 0xad, - 0x11, 0xed, 0x0e, 0x0e, 0xc7, 0xc0, 0x00, 0xaa, - 0x11, 0xec, 0x06, 0x0e, 0xc7, 0xc0, 0x01, 0xa8, - 0x97, 0xec, 0x17, 0xe2, 0xe1, 0xf1, 0x0e, 0xb6, - 0xe4, 0x29, 0x11, 0xb9, 0xaf, 0xec, 0x0b, 0xe1, - 0xc7, 0x9e, 0xe5, 0xe2, 0xe1, 0xf1, 0x0e, 0xb6, - 0xe4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa0, 0x05, - 0x01, 0x01, 0x01, 0x05, 0x0e, 0x00, 0xb6, 0x01, - 0x02, 0x60, 0x00, 0x01, 0x00, 0xb6, 0x07, 0x00, - 0x00, 0x00, 0x96, 0x04, 0x2d, 0x01, 0xb2, 0x04, - 0x3b, 0x01, 0xc0, 0x04, 0x42, 0x01, 0x90, 0x05, - 0x6a, 0x01, 0x92, 0x04, 0x2b, 0x01, 0x98, 0x05, - 0x6e, 0x01, 0x8a, 0x04, 0x27, 0x01, 0xd0, 0x03, - 0x01, 0x0c, 0x9c, 0x04, 0x30, 0x01, 0xca, 0x05, - 0x87, 0x01, 0x01, 0x94, 0x04, 0x2c, 0x01, 0xc6, - 0x04, 0x45, 0x01, 0x8c, 0x04, 0x28, 0x01, 0xbe, - 0x04, 0x41, 0x01, 0xdf, 0xec, 0x11, 0xe0, 0xd3, - 0xf1, 0xb7, 0xaf, 0xec, 0x05, 0xe1, 0xd3, 0xf1, - 0x0e, 0x09, 0xe3, 0xef, 0x80, 0x00, 0xe2, 0xd3, - 0x48, 0xcf, 0xec, 0x5a, 0xc7, 0x60, 0x04, 0x00, - 0xc7, 0xd3, 0xf1, 0x11, 0xb5, 0xaf, 0xec, 0x09, - 0x5f, 0x05, 0x00, 0x5f, 0x06, 0x00, 0xf1, 0x29, - 0x11, 0xbe, 0xfe, 0xaf, 0xec, 0x07, 0x5f, 0x05, - 0x00, 0x07, 0xf1, 0x29, 0x11, 0xbe, 0xfd, 0xaf, - 0xec, 0x2b, 0x66, 0x07, 0x00, 0x43, 0x6d, 0x01, - 0x00, 0x00, 0x66, 0x07, 0x00, 0x42, 0x6e, 0x01, - 0x00, 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x66, - 0x07, 0x00, 0x43, 0x6f, 0x01, 0x00, 0x00, 0x5f, - 0x08, 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x5f, - 0x09, 0x00, 0xf0, 0x29, 0x0e, 0x5f, 0x04, 0x00, - 0x60, 0x0a, 0x00, 0xee, 0x20, 0xe0, 0xd3, 0xf1, - 0xb7, 0xaf, 0xec, 0x14, 0xd3, 0x04, 0xd3, 0x01, - 0x00, 0x00, 0xaa, 0xec, 0x0b, 0xe1, 0xd3, 0xf1, - 0x0e, 0xe1, 0x60, 0x0a, 0x00, 0xee, 0x06, 0x5f, - 0x0b, 0x00, 0xf0, 0x0e, 0x5f, 0x0c, 0x00, 0xb6, - 0xa7, 0xec, 0x04, 0xb6, 0xee, 0x14, 0x5f, 0x0c, - 0x00, 0x5f, 0x06, 0x00, 0xeb, 0xa9, 0xec, 0x07, - 0x5f, 0x06, 0x00, 0xeb, 0xee, 0x04, 0x5f, 0x0c, - 0x00, 0x60, 0x0c, 0x00, 0x5f, 0x0d, 0x00, 0xf0, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa2, 0x05, 0x02, - 0x01, 0x02, 0x05, 0x02, 0x01, 0x70, 0x03, 0xee, - 0x05, 0x00, 0x01, 0x00, 0xb8, 0x07, 0x00, 0x01, - 0x00, 0xce, 0x06, 0x00, 0x00, 0x00, 0xd6, 0x03, - 0x0d, 0x01, 0xb8, 0x02, 0x0b, 0x01, 0x07, 0x02, - 0x30, 0xdf, 0xd3, 0xf1, 0x97, 0xec, 0x0a, 0xd3, - 0x43, 0x38, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, - 0xd3, 0xb6, 0xad, 0xec, 0x15, 0xb7, 0xd3, 0x9c, - 0xb6, 0xa7, 0xec, 0x09, 0x04, 0xdd, 0x01, 0x00, - 0x00, 0xcb, 0xee, 0x4c, 0xc0, 0x00, 0xcb, 0xee, - 0x47, 0xd4, 0xbe, 0x10, 0xad, 0xec, 0x37, 0xd3, - 0xe0, 0x43, 0xcd, 0x01, 0x00, 0x00, 0xd3, 0x24, - 0x01, 0x00, 0xaf, 0xec, 0x29, 0xd3, 0xb6, 0xa7, - 0xec, 0x0c, 0xd3, 0x8d, 0xd7, 0x04, 0xde, 0x01, - 0x00, 0x00, 0xcb, 0xee, 0x03, 0xc2, 0xcb, 0xc7, - 0x04, 0xdf, 0x01, 0x00, 0x00, 0xd3, 0x43, 0x38, - 0x00, 0x00, 0x00, 0xbe, 0x10, 0x24, 0x01, 0x00, - 0x9e, 0x9e, 0xcb, 0xee, 0x0b, 0xd3, 0x43, 0x38, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcb, 0xc7, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xa4, 0x05, 0x02, - 0x01, 0x02, 0x05, 0x00, 0x00, 0x40, 0x03, 0xee, - 0x05, 0x00, 0x01, 0x00, 0xb8, 0x07, 0x00, 0x01, - 0x00, 0xce, 0x06, 0x00, 0x00, 0x00, 0xd4, 0xbe, - 0x10, 0xad, 0xec, 0x29, 0xd3, 0xb6, 0xa7, 0xec, - 0x0c, 0xd3, 0x8d, 0xd7, 0x04, 0xde, 0x01, 0x00, - 0x00, 0xcb, 0xee, 0x03, 0xc2, 0xcb, 0xc7, 0x04, - 0xdf, 0x01, 0x00, 0x00, 0xd3, 0x43, 0x38, 0x00, - 0x00, 0x00, 0xbe, 0x10, 0x24, 0x01, 0x00, 0x9e, - 0x9e, 0xcb, 0xee, 0x0b, 0xd3, 0x43, 0x38, 0x00, - 0x00, 0x00, 0x24, 0x00, 0x00, 0xcb, 0xc7, 0x04, - 0x8c, 0x01, 0x00, 0x00, 0x9e, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0x00, 0x04, 0x18, 0x04, 0x06, 0x12, - 0x0e, 0xea, 0x01, 0x1c, 0xc0, 0x07, 0x00, 0x01, - 0x00, 0xea, 0x03, 0x00, 0x01, 0x40, 0xc2, 0x07, - 0x00, 0x01, 0x40, 0xc4, 0x07, 0x00, 0x01, 0x40, - 0xc6, 0x07, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, - 0x01, 0x00, 0xc8, 0x07, 0x00, 0x02, 0x40, 0xca, - 0x07, 0x00, 0x03, 0x40, 0xcc, 0x07, 0x00, 0x04, - 0x40, 0xce, 0x07, 0x00, 0x05, 0x40, 0xd0, 0x07, - 0x00, 0x06, 0x40, 0x6c, 0x00, 0x07, 0x40, 0xd2, - 0x07, 0x00, 0x08, 0x40, 0xd4, 0x07, 0x00, 0x09, - 0x40, 0xd6, 0x07, 0x00, 0x0a, 0x40, 0xd8, 0x07, - 0x00, 0x0b, 0x40, 0xda, 0x07, 0x00, 0x0c, 0x40, - 0xdc, 0x07, 0x00, 0x0d, 0x40, 0xde, 0x07, 0x00, - 0x0e, 0x40, 0xe0, 0x07, 0x00, 0x0f, 0x40, 0xe2, - 0x07, 0x00, 0x10, 0x40, 0xe4, 0x07, 0x00, 0x11, - 0x40, 0xe6, 0x07, 0x00, 0x12, 0x40, 0xe8, 0x07, - 0x00, 0x13, 0x40, 0xea, 0x07, 0x00, 0x14, 0x40, - 0xec, 0x07, 0x00, 0x15, 0x40, 0xee, 0x07, 0x00, - 0x16, 0x40, 0xf0, 0x07, 0x00, 0x17, 0x40, 0xda, - 0x03, 0x0f, 0x01, 0xba, 0x02, 0x0c, 0x01, 0xa8, - 0x02, 0x00, 0x01, 0xa2, 0x05, 0x73, 0x01, 0xee, - 0x03, 0x19, 0x01, 0xa4, 0x05, 0x74, 0x01, 0xb0, - 0x02, 0x01, 0x01, 0xbc, 0x02, 0x07, 0x01, 0xc4, - 0x02, 0x08, 0x01, 0xb2, 0x02, 0x03, 0x01, 0xae, - 0x02, 0x02, 0x01, 0xe4, 0x02, 0x04, 0x01, 0xaa, - 0x02, 0x06, 0x01, 0xce, 0x02, 0x05, 0x01, 0xde, - 0x03, 0x11, 0x01, 0xe2, 0x03, 0x13, 0x01, 0xb8, - 0x02, 0x0b, 0x01, 0xa0, 0x04, 0x32, 0x01, 0x0c, - 0x43, 0x02, 0x01, 0x86, 0x01, 0x02, 0x00, 0x02, - 0x01, 0x01, 0x00, 0x0e, 0x02, 0xf2, 0x07, 0x00, - 0x01, 0x00, 0xf4, 0x07, 0x00, 0x01, 0x00, 0xda, - 0x03, 0x00, 0x00, 0xd3, 0xf6, 0xec, 0x03, 0xd4, - 0x28, 0xd3, 0xf5, 0xec, 0x03, 0xdf, 0x28, 0xd3, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xd8, 0x07, 0x01, - 0x00, 0x01, 0x04, 0x01, 0x00, 0x54, 0x01, 0xce, - 0x06, 0x00, 0x01, 0x00, 0xba, 0x02, 0x01, 0x00, - 0xd3, 0x43, 0xfb, 0x01, 0x00, 0x00, 0x04, 0xb2, - 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xec, 0x0b, - 0xdf, 0x43, 0xfc, 0x01, 0x00, 0x00, 0xd3, 0x25, - 0x01, 0x00, 0xdf, 0x43, 0xfc, 0x01, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0x43, 0xaa, 0x01, 0x00, - 0x00, 0xb7, 0xb5, 0x24, 0x02, 0x00, 0x43, 0xfd, - 0x01, 0x00, 0x00, 0x04, 0xfe, 0x01, 0x00, 0x00, - 0x04, 0xb3, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, - 0xd7, 0x04, 0xb2, 0x01, 0x00, 0x00, 0x43, 0x5d, - 0x00, 0x00, 0x00, 0xd3, 0x04, 0xb2, 0x01, 0x00, - 0x00, 0x25, 0x02, 0x00, 0x0c, 0x43, 0x02, 0x01, - 0xda, 0x07, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, - 0x0d, 0x01, 0xce, 0x06, 0x00, 0x01, 0x00, 0xd2, - 0x07, 0x08, 0x01, 0xdf, 0x43, 0x9e, 0x01, 0x00, - 0x00, 0xc2, 0xd3, 0x9e, 0x24, 0x01, 0x00, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xdc, 0x07, 0x01, 0x00, - 0x01, 0x04, 0x01, 0x00, 0x0c, 0x01, 0xce, 0x06, - 0x00, 0x01, 0x00, 0xd2, 0x07, 0x08, 0x01, 0xdf, - 0xdf, 0xeb, 0xb7, 0x9f, 0x73, 0x13, 0x48, 0xd3, - 0x9e, 0x4a, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xde, - 0x07, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x1f, - 0x01, 0xfe, 0x07, 0x00, 0x01, 0x00, 0xa8, 0x02, - 0x02, 0x00, 0xdf, 0x42, 0x3c, 0x00, 0x00, 0x00, - 0x42, 0x38, 0x00, 0x00, 0x00, 0x43, 0x00, 0x02, - 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0x43, 0xaa, - 0x01, 0x00, 0x00, 0xbe, 0x08, 0xb5, 0x25, 0x02, - 0x00, 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x07, 0x02, - 0x13, 0x02, 0x09, 0x1a, 0x02, 0xdc, 0x0b, 0x15, - 0xee, 0x05, 0x00, 0x01, 0x00, 0x88, 0x04, 0x00, - 0x01, 0x00, 0x98, 0x06, 0x00, 0x00, 0x00, 0x82, - 0x08, 0x00, 0x01, 0x00, 0xe2, 0x05, 0x00, 0x02, - 0x00, 0x84, 0x08, 0x00, 0x03, 0x00, 0x60, 0x00, - 0x04, 0x00, 0x86, 0x08, 0x00, 0x05, 0x00, 0x88, - 0x08, 0x00, 0x06, 0x00, 0x8a, 0x08, 0x00, 0x07, - 0x00, 0x8c, 0x08, 0x00, 0x08, 0x00, 0x8e, 0x08, - 0x00, 0x09, 0x00, 0x90, 0x08, 0x00, 0x0a, 0x00, - 0x92, 0x08, 0x00, 0x0b, 0x00, 0x94, 0x08, 0x00, - 0x0c, 0x00, 0x96, 0x08, 0x00, 0x0d, 0x00, 0x98, - 0x08, 0x00, 0x0e, 0x00, 0xf8, 0x05, 0x00, 0x0f, - 0x00, 0x8a, 0x06, 0x00, 0x10, 0x00, 0x9a, 0x08, - 0x00, 0x11, 0x00, 0x9c, 0x08, 0x00, 0x12, 0x00, - 0xda, 0x07, 0x0c, 0x01, 0xa2, 0x05, 0x03, 0x00, - 0xee, 0x03, 0x04, 0x00, 0xa4, 0x05, 0x05, 0x00, - 0xce, 0x07, 0x05, 0x01, 0xd8, 0x07, 0x0b, 0x01, - 0xb0, 0x02, 0x06, 0x00, 0xd0, 0x07, 0x06, 0x01, - 0x6c, 0x07, 0x01, 0xd2, 0x07, 0x08, 0x01, 0xde, - 0x07, 0x0e, 0x01, 0xbc, 0x02, 0x07, 0x00, 0xba, - 0x02, 0x01, 0x00, 0xc4, 0x02, 0x08, 0x00, 0xb2, - 0x02, 0x09, 0x00, 0xae, 0x02, 0x0a, 0x00, 0xe4, - 0x02, 0x0b, 0x00, 0xaa, 0x02, 0x0c, 0x00, 0xce, - 0x02, 0x0d, 0x00, 0xc2, 0x07, 0x02, 0x03, 0xe0, - 0x07, 0x0f, 0x01, 0xca, 0x07, 0x03, 0x01, 0xea, - 0x03, 0x01, 0x03, 0xa8, 0x02, 0x02, 0x00, 0xdc, - 0x07, 0x0d, 0x01, 0xcc, 0x07, 0x04, 0x01, 0x07, - 0x32, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, - 0x5a, 0x5f, 0x24, 0x5d, 0x5b, 0x30, 0x2d, 0x39, - 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5f, 0x24, - 0x5d, 0x2a, 0x07, 0xaa, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x4d, 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, - 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, - 0x0c, 0x00, 0x06, 0x16, 0x04, 0x00, 0x24, 0x00, - 0x24, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, 0x00, - 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x1d, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, - 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x30, 0x00, - 0x39, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, 0x00, - 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, 0x0d, - 0x00, 0x0b, 0xd3, 0x98, 0xc5, 0x06, 0x11, 0x04, - 0x46, 0x00, 0x00, 0x00, 0xaf, 0xed, 0x0a, 0x11, - 0x04, 0x48, 0x00, 0x00, 0x00, 0xaf, 0xec, 0x06, - 0xdf, 0xd3, 0xf1, 0x0e, 0x29, 0x11, 0x04, 0x47, - 0x00, 0x00, 0x00, 0xaf, 0xec, 0x11, 0xdf, 0xe0, - 0xd3, 0xe1, 0xec, 0x05, 0xbe, 0x10, 0xee, 0x03, - 0xbe, 0x0a, 0xf2, 0xf1, 0x0e, 0x29, 0x11, 0x04, - 0x8e, 0x00, 0x00, 0x00, 0xaf, 0xec, 0x11, 0xdf, - 0xe2, 0xd3, 0xe1, 0xec, 0x05, 0xbe, 0x10, 0xee, - 0x03, 0xbe, 0x0a, 0xf2, 0xf1, 0x0e, 0x29, 0x11, - 0x04, 0x49, 0x00, 0x00, 0x00, 0xaf, 0xec, 0x26, - 0xd3, 0xeb, 0x5f, 0x04, 0x00, 0xa9, 0xec, 0x15, - 0xd3, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb6, 0x5f, - 0x04, 0x00, 0x24, 0x02, 0x00, 0x04, 0x0f, 0x02, - 0x00, 0x00, 0x9e, 0xd7, 0xdf, 0x5f, 0x05, 0x00, - 0xd3, 0xf1, 0xf1, 0x0e, 0x29, 0x11, 0x04, 0x4b, - 0x00, 0x00, 0x00, 0xaf, 0xec, 0x0a, 0xdf, 0x5f, - 0x06, 0x00, 0xd3, 0xf1, 0xf1, 0x0e, 0x29, 0x11, - 0x04, 0x4a, 0x00, 0x00, 0x00, 0xaf, 0xed, 0x0d, - 0x11, 0x04, 0x1b, 0x00, 0x00, 0x00, 0xaf, 0x6a, - 0x35, 0x05, 0x00, 0x00, 0xd3, 0xf5, 0xec, 0x06, - 0xdf, 0xd3, 0xf1, 0x0e, 0x29, 0x5f, 0x07, 0x00, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, - 0x00, 0xcf, 0xb6, 0xaa, 0xec, 0x18, 0xdf, 0x04, - 0x10, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0xc7, 0x04, 0xb5, 0x01, 0x00, 0x00, 0x24, - 0x02, 0x00, 0xf1, 0x0e, 0x29, 0x5f, 0x08, 0x00, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, - 0x00, 0xcf, 0xb6, 0xaa, 0xec, 0x2c, 0xdf, 0x04, - 0x10, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0x5f, 0x07, 0x00, 0xeb, 0x04, 0xb5, 0x01, - 0x00, 0x00, 0x24, 0x02, 0x00, 0xf1, 0x0e, 0x5f, - 0x07, 0x00, 0x43, 0x9e, 0x01, 0x00, 0x00, 0x5f, - 0x08, 0x00, 0xc7, 0x48, 0x24, 0x01, 0x00, 0x0e, - 0x29, 0x5f, 0x09, 0x00, 0xeb, 0xc4, 0x0c, 0x5f, - 0x0a, 0x00, 0xd3, 0xf1, 0xc4, 0x0d, 0x5f, 0x08, - 0x00, 0x43, 0x9e, 0x01, 0x00, 0x00, 0xd3, 0x24, - 0x01, 0x00, 0x0e, 0xd3, 0x5f, 0x0b, 0x00, 0xab, - 0xec, 0x28, 0xdf, 0x04, 0x11, 0x02, 0x00, 0x00, - 0x43, 0x5d, 0x00, 0x00, 0x00, 0x5f, 0x0c, 0x00, - 0x43, 0xfc, 0x01, 0x00, 0x00, 0xd3, 0x43, 0x12, - 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x01, - 0x00, 0x24, 0x01, 0x00, 0xf1, 0x0e, 0xef, 0xad, - 0x01, 0xd3, 0x5f, 0x0d, 0x00, 0xab, 0xec, 0x10, - 0xdf, 0xd3, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, - 0x00, 0x00, 0xf1, 0x0e, 0xef, 0x97, 0x01, 0xd3, - 0x5f, 0x0e, 0x00, 0xab, 0x11, 0xed, 0x10, 0x0e, - 0xd3, 0x5f, 0x0f, 0x00, 0xab, 0x11, 0xed, 0x07, - 0x0e, 0xd3, 0x5f, 0x10, 0x00, 0xab, 0xec, 0x21, - 0xdf, 0x04, 0xd8, 0x01, 0x00, 0x00, 0x43, 0x5d, - 0x00, 0x00, 0x00, 0xc3, 0x0d, 0x04, 0x13, 0x02, - 0x00, 0x00, 0xd3, 0x04, 0xb5, 0x01, 0x00, 0x00, - 0x24, 0x04, 0x00, 0xf1, 0x0e, 0xef, 0x5e, 0x01, - 0xd3, 0x5f, 0x06, 0x00, 0xab, 0xec, 0x2c, 0xdf, - 0x04, 0xd8, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, - 0x00, 0x00, 0xc3, 0x0d, 0x04, 0x13, 0x02, 0x00, - 0x00, 0x5f, 0x05, 0x00, 0xd3, 0xf1, 0x04, 0xb5, - 0x01, 0x00, 0x00, 0x24, 0x04, 0x00, 0xf1, 0x0e, - 0xd3, 0xeb, 0xc4, 0x0f, 0xb7, 0xc4, 0x08, 0xef, - 0x2c, 0x01, 0x5f, 0x11, 0x00, 0x43, 0x14, 0x02, - 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0xec, 0x0f, - 0xdf, 0x04, 0xd8, 0x01, 0x00, 0x00, 0xf1, 0x0e, - 0xb7, 0xc4, 0x07, 0xef, 0x10, 0x01, 0xc3, 0x0d, - 0x43, 0xfb, 0x01, 0x00, 0x00, 0x04, 0x95, 0x00, - 0x00, 0x00, 0x24, 0x01, 0x00, 0xec, 0x2d, 0xd3, - 0x5f, 0x12, 0x00, 0x42, 0x45, 0x00, 0x00, 0x00, - 0xab, 0xec, 0x21, 0xdf, 0xc2, 0x43, 0x5d, 0x00, - 0x00, 0x00, 0xc3, 0x0d, 0x04, 0xca, 0x01, 0x00, - 0x00, 0xd3, 0xeb, 0x04, 0x15, 0x02, 0x00, 0x00, - 0x24, 0x04, 0x00, 0xf1, 0x0e, 0xb7, 0xc4, 0x07, - 0xef, 0xd3, 0x00, 0xc3, 0x06, 0x04, 0x1b, 0x00, - 0x00, 0x00, 0xaf, 0xec, 0x32, 0xd3, 0x42, 0x37, - 0x00, 0x00, 0x00, 0xec, 0x1f, 0xdf, 0x04, 0x16, - 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, - 0xd3, 0x42, 0x37, 0x00, 0x00, 0x00, 0x04, 0xb5, - 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf1, 0x0e, - 0xef, 0xa3, 0x00, 0xdf, 0x04, 0x17, 0x02, 0x00, - 0x00, 0xf1, 0x0e, 0xef, 0x98, 0x00, 0xd3, 0x42, - 0x3d, 0x00, 0x00, 0x00, 0x11, 0xec, 0x0d, 0x0e, - 0xd3, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x42, 0x37, - 0x00, 0x00, 0x00, 0x11, 0xed, 0x07, 0x0e, 0x04, - 0x94, 0x00, 0x00, 0x00, 0xc4, 0x0e, 0xc3, 0x0d, - 0x04, 0x94, 0x00, 0x00, 0x00, 0xb0, 0xec, 0x1d, - 0xdf, 0xc2, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xc3, - 0x0e, 0x04, 0x18, 0x02, 0x00, 0x00, 0xc3, 0x0d, - 0x04, 0x19, 0x02, 0x00, 0x00, 0x24, 0x04, 0x00, - 0xf1, 0x0e, 0xee, 0x4a, 0xd3, 0x42, 0x45, 0x00, - 0x00, 0x00, 0xf5, 0xec, 0x1a, 0xdf, 0x04, 0xd8, - 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, - 0xc3, 0x0e, 0x04, 0x1a, 0x02, 0x00, 0x00, 0x24, - 0x02, 0x00, 0xf1, 0x0e, 0xee, 0x28, 0xc3, 0x0e, - 0x04, 0x94, 0x00, 0x00, 0x00, 0xb0, 0xec, 0x16, - 0xdf, 0xc2, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xc3, - 0x0e, 0x04, 0x1b, 0x02, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xf1, 0x0e, 0xee, 0x09, 0xdf, 0x04, 0x1c, - 0x02, 0x00, 0x00, 0xf1, 0x0e, 0x04, 0x1d, 0x02, - 0x00, 0x00, 0xc4, 0x0a, 0x07, 0xc4, 0x04, 0xb6, - 0xcb, 0xb6, 0xcc, 0xb6, 0xce, 0xc3, 0x07, 0x6a, - 0xcb, 0x00, 0x00, 0x00, 0x04, 0xb5, 0x01, 0x00, - 0x00, 0xc4, 0x0a, 0xd3, 0xeb, 0xc4, 0x0f, 0xd4, - 0x5f, 0x13, 0x00, 0xa9, 0xec, 0x12, 0xc3, 0x0f, - 0xec, 0x0e, 0xdf, 0x04, 0x0f, 0x02, 0x00, 0x00, - 0xf1, 0x0e, 0xdf, 0xc3, 0x0a, 0xf1, 0x29, 0xb6, - 0xcd, 0xc9, 0xc3, 0x0f, 0xa7, 0x6a, 0x89, 0x00, - 0x00, 0x00, 0x94, 0x03, 0xc9, 0xd3, 0xac, 0xec, - 0x0e, 0x5f, 0x14, 0x00, 0xd3, 0xc9, 0x48, 0xd4, - 0xb7, 0x9e, 0xf2, 0x0e, 0xee, 0x43, 0xc9, 0xc4, - 0x10, 0xc9, 0xb7, 0x9e, 0xc3, 0x0f, 0xa7, 0xec, - 0x0d, 0xc9, 0xb7, 0x9e, 0xd3, 0xac, 0x97, 0xec, - 0x05, 0x94, 0x02, 0xee, 0xed, 0xc9, 0xc3, 0x10, - 0xa9, 0xec, 0x1e, 0xdf, 0x04, 0x1e, 0x02, 0x00, - 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xc9, 0xc3, - 0x10, 0x9f, 0xb7, 0x9e, 0x04, 0x1f, 0x02, 0x00, - 0x00, 0x24, 0x02, 0x00, 0xf1, 0x0e, 0xee, 0x09, - 0xdf, 0x04, 0x20, 0x02, 0x00, 0x00, 0xf1, 0x0e, - 0xca, 0x5f, 0x15, 0x00, 0xaa, 0xec, 0x24, 0xc3, - 0x0f, 0xca, 0x9f, 0xbb, 0xa9, 0xec, 0x1c, 0xdf, - 0x04, 0x21, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, - 0x00, 0x00, 0xc3, 0x0f, 0xca, 0x9f, 0x04, 0x22, - 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf1, 0x0e, - 0xee, 0x06, 0x94, 0x02, 0xef, 0x74, 0xff, 0xb7, - 0xc4, 0x08, 0xc9, 0xc3, 0x0f, 0xb0, 0xec, 0x0c, - 0xc3, 0x0f, 0xbf, 0xe8, 0x03, 0xa9, 0xec, 0x04, - 0xb7, 0xc4, 0x09, 0xc3, 0x09, 0x97, 0xec, 0x24, - 0x5f, 0x16, 0x00, 0xec, 0x0f, 0x5f, 0x17, 0x00, - 0x43, 0xbe, 0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, - 0x00, 0xee, 0x0d, 0x5f, 0x17, 0x00, 0x43, 0x30, - 0x00, 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0xc5, - 0x04, 0xeb, 0xcb, 0xc3, 0x08, 0xec, 0x1e, 0xc8, - 0xc7, 0xa7, 0xec, 0x19, 0xc3, 0x04, 0xc8, 0x48, - 0x8e, 0xd1, 0xc9, 0xb6, 0xa2, 0xb0, 0x11, 0xed, - 0x06, 0x0e, 0xc9, 0xc3, 0x0f, 0xaa, 0xed, 0x05, - 0x94, 0x01, 0xee, 0xe4, 0xc8, 0xc7, 0xa7, 0x6a, - 0x5a, 0x01, 0x00, 0x00, 0xc3, 0x0a, 0x97, 0xec, - 0x12, 0x5f, 0x18, 0x00, 0x04, 0x1b, 0x02, 0x00, - 0x00, 0xf1, 0x0e, 0x04, 0x1d, 0x02, 0x00, 0x00, - 0xc4, 0x0a, 0xd4, 0x5f, 0x13, 0x00, 0xa9, 0xec, - 0x13, 0xc8, 0xc7, 0xa7, 0xec, 0x0e, 0xdf, 0x04, - 0x0f, 0x02, 0x00, 0x00, 0xf1, 0x0e, 0xdf, 0xc3, - 0x0a, 0xf1, 0x29, 0xc8, 0xcd, 0xc9, 0xc7, 0xa7, - 0x6a, 0x21, 0x01, 0x00, 0x00, 0xc3, 0x04, 0xc9, - 0x48, 0xc4, 0x05, 0x5f, 0x17, 0x00, 0x43, 0x67, - 0x00, 0x00, 0x00, 0xd3, 0xc3, 0x05, 0x24, 0x02, - 0x00, 0xc5, 0x11, 0x97, 0x6b, 0x00, 0x01, 0x00, - 0x00, 0xc3, 0x11, 0x42, 0x40, 0x00, 0x00, 0x00, - 0x97, 0xec, 0x1e, 0xdf, 0x04, 0xd8, 0x01, 0x00, - 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0x5f, 0x06, - 0x00, 0xc3, 0x05, 0xf1, 0x04, 0xb5, 0x01, 0x00, - 0x00, 0x24, 0x02, 0x00, 0xf1, 0x0e, 0xee, 0x2e, - 0xc3, 0x05, 0x8e, 0xc3, 0x05, 0xb6, 0xa2, 0xaf, - 0x11, 0xed, 0x11, 0x0e, 0xc3, 0x05, 0x43, 0xb7, - 0x01, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0x34, - 0x24, 0x01, 0x00, 0xec, 0x08, 0xdf, 0xc3, 0x05, - 0xf1, 0x0e, 0xee, 0x0a, 0xdf, 0x5f, 0x05, 0x00, - 0xc3, 0x05, 0xf1, 0xf1, 0x0e, 0xdf, 0x04, 0x23, - 0x02, 0x00, 0x00, 0xf1, 0x0e, 0x04, 0x41, 0x00, - 0x00, 0x00, 0xc3, 0x11, 0xac, 0xec, 0x12, 0x5f, - 0x14, 0x00, 0xc3, 0x11, 0x42, 0x41, 0x00, 0x00, - 0x00, 0xd4, 0xb7, 0x9e, 0xf2, 0x0e, 0xee, 0x5c, - 0x26, 0x00, 0x00, 0xc4, 0x12, 0xc3, 0x11, 0x42, - 0x42, 0x00, 0x00, 0x00, 0xec, 0x11, 0xc3, 0x12, - 0x43, 0x9e, 0x01, 0x00, 0x00, 0x04, 0x24, 0x02, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xc3, 0x11, - 0x42, 0x43, 0x00, 0x00, 0x00, 0xec, 0x11, 0xc3, - 0x12, 0x43, 0x9e, 0x01, 0x00, 0x00, 0x04, 0x25, - 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xdf, - 0x04, 0xd8, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, - 0x00, 0x00, 0xc3, 0x12, 0x43, 0x5c, 0x00, 0x00, - 0x00, 0x04, 0xb6, 0x01, 0x00, 0x00, 0x24, 0x01, - 0x00, 0x04, 0xb5, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xf1, 0x0e, 0x94, 0x03, 0xca, 0x5f, 0x19, - 0x00, 0xa9, 0xec, 0x22, 0xc7, 0xca, 0x9f, 0xbb, - 0xa9, 0xec, 0x1b, 0xdf, 0x04, 0x21, 0x02, 0x00, - 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xc7, 0xca, - 0x9f, 0x04, 0x26, 0x02, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xf1, 0x0e, 0xee, 0x06, 0x94, 0x02, 0xef, - 0xdd, 0xfe, 0xc3, 0x0a, 0xec, 0x06, 0xdf, 0xc3, - 0x0a, 0xf1, 0x0e, 0x5f, 0x08, 0x00, 0x43, 0x27, - 0x02, 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0x0e, - 0x5f, 0x07, 0x00, 0x43, 0xb1, 0x01, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0xd1, 0xb6, 0xa9, 0xec, - 0x35, 0x5f, 0x09, 0x00, 0xc3, 0x0c, 0x1b, 0x11, - 0xb1, 0xed, 0x04, 0x1b, 0x72, 0x1b, 0x1b, 0x04, - 0x28, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0xc9, 0x04, 0x29, 0x02, 0x00, 0x00, 0x5f, - 0x09, 0x00, 0xc3, 0x0c, 0x48, 0x24, 0x03, 0x00, - 0x1b, 0x72, 0x1b, 0x4a, 0x29, 0xdf, 0x5f, 0x06, - 0x00, 0xd3, 0xf1, 0xf1, 0x0e, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xe2, 0x07, 0x02, 0x01, 0x02, 0x03, - 0x05, 0x00, 0x3d, 0x03, 0xce, 0x06, 0x00, 0x01, - 0x00, 0x90, 0x06, 0x00, 0x01, 0x00, 0xd4, 0x08, - 0x00, 0x00, 0x00, 0xc4, 0x07, 0x03, 0x03, 0xd6, - 0x07, 0x0a, 0x01, 0xd4, 0x07, 0x09, 0x01, 0xde, - 0x03, 0x0e, 0x00, 0xe2, 0x03, 0x0f, 0x00, 0xdf, - 0xec, 0x30, 0xe0, 0xd4, 0xb0, 0xec, 0x13, 0xe1, - 0x43, 0x9e, 0x01, 0x00, 0x00, 0xe2, 0x42, 0x8a, - 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xd4, - 0xe4, 0xd4, 0xec, 0x16, 0xe2, 0x5f, 0x04, 0x00, - 0xd4, 0x48, 0x48, 0xcf, 0xec, 0x0c, 0xe1, 0x43, - 0x9e, 0x01, 0x00, 0x00, 0xc7, 0x24, 0x01, 0x00, - 0x0e, 0xe1, 0x43, 0x9e, 0x01, 0x00, 0x00, 0xd3, - 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xe4, 0x07, 0x01, 0x00, 0x01, 0x03, 0x01, 0x02, - 0x2c, 0x01, 0xce, 0x06, 0x00, 0x01, 0x00, 0xe2, - 0x07, 0x10, 0x01, 0x07, 0x02, 0x30, 0x07, 0x02, - 0x39, 0xd3, 0xb6, 0x48, 0xc0, 0x00, 0xaa, 0xec, - 0x14, 0xd3, 0xb6, 0x48, 0xc0, 0x01, 0xa8, 0xec, - 0x0c, 0xdf, 0xd3, 0x04, 0x47, 0x00, 0x00, 0x00, - 0xf2, 0x0e, 0xee, 0x0a, 0xdf, 0xd3, 0x04, 0x2b, - 0x02, 0x00, 0x00, 0xf2, 0x0e, 0xdf, 0x04, 0x13, - 0x02, 0x00, 0x00, 0xf1, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xe6, 0x07, 0x01, 0x04, 0x01, 0x05, 0x03, - 0x14, 0xa1, 0x04, 0x05, 0xce, 0x06, 0x00, 0x01, - 0x00, 0x90, 0x06, 0x00, 0x00, 0x00, 0xd8, 0x08, - 0x00, 0x01, 0x00, 0xf8, 0x05, 0x00, 0x02, 0x00, - 0x92, 0x07, 0x00, 0x03, 0x00, 0xc4, 0x07, 0x03, - 0x03, 0xe2, 0x07, 0x10, 0x01, 0xe8, 0x07, 0x13, - 0x01, 0x07, 0x20, 0x5e, 0x22, 0x28, 0x5b, 0x5e, - 0x5c, 0x5c, 0x22, 0x5d, 0x7c, 0x5c, 0x5c, 0x2e, - 0x29, 0x2a, 0x22, 0x07, 0x98, 0x01, 0x00, 0x00, - 0x02, 0x01, 0x44, 0x00, 0x00, 0x00, 0x09, 0x06, - 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, - 0xff, 0x0c, 0x00, 0x06, 0x01, 0x22, 0x0e, 0x01, - 0x01, 0x0a, 0x27, 0x00, 0x00, 0x00, 0x1a, 0x0c, - 0x01, 0x0a, 0x14, 0x00, 0x00, 0x00, 0x16, 0x03, - 0x00, 0x00, 0x00, 0x21, 0x00, 0x23, 0x00, 0x5b, - 0x00, 0x5d, 0x00, 0xff, 0xff, 0x08, 0x03, 0x00, - 0x00, 0x00, 0x01, 0x5c, 0x04, 0x0d, 0x01, 0x1b, - 0x08, 0xd4, 0xff, 0xff, 0xff, 0x01, 0x22, 0x0d, - 0x00, 0x0b, 0x07, 0x20, 0x5e, 0x27, 0x28, 0x5b, - 0x5e, 0x5c, 0x5c, 0x27, 0x5d, 0x7c, 0x5c, 0x5c, - 0x2e, 0x29, 0x2a, 0x27, 0x07, 0x98, 0x01, 0x00, - 0x00, 0x02, 0x01, 0x44, 0x00, 0x00, 0x00, 0x09, - 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, - 0xff, 0xff, 0x0c, 0x00, 0x06, 0x01, 0x27, 0x0e, - 0x01, 0x01, 0x0a, 0x27, 0x00, 0x00, 0x00, 0x1a, - 0x0c, 0x01, 0x0a, 0x14, 0x00, 0x00, 0x00, 0x16, - 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x28, 0x00, - 0x5b, 0x00, 0x5d, 0x00, 0xff, 0xff, 0x08, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x5c, 0x04, 0x0d, 0x01, - 0x1b, 0x08, 0xd4, 0xff, 0xff, 0xff, 0x01, 0x27, - 0x0d, 0x00, 0x0b, 0x07, 0x16, 0x5e, 0x5c, 0x3c, - 0x5b, 0x5e, 0x5c, 0x3e, 0x5d, 0x2b, 0x5c, 0x3e, - 0x07, 0x74, 0x00, 0x00, 0x01, 0x00, 0x32, 0x00, - 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x05, - 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x06, - 0x01, 0x3c, 0x1d, 0x0c, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, - 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x3f, 0x00, 0xff, 0xff, 0x0b, 0x01, - 0x3e, 0x0d, 0x00, 0x0b, 0x07, 0x16, 0x5e, 0x5c, - 0x5b, 0x5b, 0x5e, 0x5c, 0x5d, 0x5d, 0x2b, 0x5c, - 0x5d, 0x07, 0x74, 0x00, 0x00, 0x01, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, - 0x06, 0x01, 0x5b, 0x1d, 0x0c, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, - 0x01, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x00, - 0x00, 0x5c, 0x00, 0x5e, 0x00, 0xff, 0xff, 0x0b, - 0x01, 0x5d, 0x0d, 0x00, 0x0b, 0x07, 0x02, 0x30, - 0x07, 0x02, 0x31, 0x07, 0x02, 0x32, 0x07, 0x02, - 0x33, 0x07, 0x02, 0x34, 0x07, 0x02, 0x35, 0x07, - 0x02, 0x36, 0x07, 0x02, 0x37, 0x07, 0x02, 0x38, - 0x07, 0x02, 0x39, 0x07, 0x56, 0x5e, 0x5b, 0x30, - 0x2d, 0x39, 0x61, 0x2d, 0x7a, 0x5f, 0x5d, 0x2b, - 0x5b, 0x2e, 0x5d, 0x3f, 0x5b, 0x30, 0x2d, 0x39, - 0x61, 0x2d, 0x7a, 0x5f, 0x5d, 0x2a, 0x5b, 0x65, - 0x45, 0x70, 0x50, 0x5d, 0x3f, 0x5b, 0x2b, 0x2d, - 0x5d, 0x3f, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2a, - 0x07, 0x9e, 0x03, 0x00, 0x00, 0x01, 0x00, 0xc7, - 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, - 0x06, 0x1d, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, - 0x00, 0x00, 0x16, 0x03, 0x00, 0x30, 0x00, 0x39, - 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, - 0x00, 0x0b, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x2e, 0x00, - 0x2e, 0x00, 0x0b, 0x1d, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, - 0x01, 0x00, 0x00, 0x00, 0x16, 0x03, 0x00, 0x30, - 0x00, 0x39, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x61, - 0x00, 0x7a, 0x00, 0x0b, 0x1d, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x04, 0x00, - 0x45, 0x00, 0x45, 0x00, 0x50, 0x00, 0x50, 0x00, - 0x65, 0x00, 0x65, 0x00, 0x70, 0x00, 0x70, 0x00, - 0x0b, 0x1d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x16, 0x02, 0x00, 0x2b, 0x00, 0x2b, - 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x0b, 0x1d, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, - 0x01, 0x00, 0x30, 0x00, 0x39, 0x00, 0x0b, 0x0d, - 0x00, 0x0b, 0xdf, 0x97, 0xec, 0x05, 0xe0, 0xd3, - 0xf1, 0x29, 0xd3, 0xeb, 0xb6, 0xa9, 0x6a, 0x13, - 0x02, 0x00, 0x00, 0x04, 0x8a, 0x01, 0x00, 0x00, - 0xcb, 0xd3, 0xcc, 0xb6, 0xcd, 0x07, 0xce, 0xd3, - 0xb6, 0x48, 0x11, 0x04, 0xb3, 0x01, 0x00, 0x00, - 0xaf, 0xec, 0x19, 0x04, 0x49, 0x00, 0x00, 0x00, - 0xcb, 0xd3, 0x43, 0xb7, 0x01, 0x00, 0x00, 0xc0, - 0x00, 0xc0, 0x01, 0x34, 0x24, 0x01, 0x00, 0xce, - 0xef, 0xb3, 0x01, 0x11, 0x04, 0xb2, 0x01, 0x00, - 0x00, 0xaf, 0xec, 0x19, 0x04, 0x49, 0x00, 0x00, - 0x00, 0xcb, 0xd3, 0x43, 0xb7, 0x01, 0x00, 0x00, - 0xc0, 0x02, 0xc0, 0x03, 0x34, 0x24, 0x01, 0x00, - 0xce, 0xef, 0x92, 0x01, 0x11, 0x04, 0xb6, 0x01, - 0x00, 0x00, 0xaf, 0xec, 0x0a, 0x04, 0x2d, 0x02, - 0x00, 0x00, 0xcb, 0xef, 0x80, 0x01, 0x11, 0x04, - 0x1e, 0x02, 0x00, 0x00, 0xaf, 0xec, 0x1e, 0xd3, - 0x43, 0xb7, 0x01, 0x00, 0x00, 0xc0, 0x04, 0xc0, - 0x05, 0x34, 0x24, 0x01, 0x00, 0xd2, 0x6a, 0x65, - 0x01, 0x00, 0x00, 0x04, 0x2e, 0x02, 0x00, 0x00, - 0xcb, 0xef, 0x5a, 0x01, 0x11, 0x04, 0xd8, 0x01, - 0x00, 0x00, 0xaf, 0xec, 0x1b, 0xd3, 0x43, 0xb7, - 0x01, 0x00, 0x00, 0xc0, 0x06, 0xc0, 0x07, 0x34, - 0x24, 0x01, 0x00, 0xd2, 0xec, 0x2e, 0x04, 0x2e, - 0x02, 0x00, 0x00, 0xcb, 0xef, 0x37, 0x01, 0x11, - 0x04, 0xb5, 0x01, 0x00, 0x00, 0xaf, 0xed, 0x1c, - 0x11, 0x04, 0x1d, 0x02, 0x00, 0x00, 0xaf, 0xed, - 0x13, 0x11, 0x04, 0x2f, 0x02, 0x00, 0x00, 0xaf, - 0xed, 0x0a, 0x11, 0x04, 0xd3, 0x01, 0x00, 0x00, - 0xaf, 0xec, 0x0c, 0x04, 0x30, 0x02, 0x00, 0x00, - 0xcb, 0xb7, 0xcd, 0xef, 0x08, 0x01, 0x11, 0x04, - 0xaf, 0x01, 0x00, 0x00, 0xaf, 0xec, 0x0a, 0x04, - 0x2e, 0x02, 0x00, 0x00, 0xcb, 0xef, 0xf6, 0x00, - 0x11, 0xc0, 0x08, 0xaf, 0xed, 0x37, 0x11, 0xc0, - 0x09, 0xaf, 0xed, 0x31, 0x11, 0xc0, 0x0a, 0xaf, - 0xed, 0x2b, 0x11, 0xc0, 0x0b, 0xaf, 0xed, 0x25, - 0x11, 0xc0, 0x0c, 0xaf, 0xed, 0x1f, 0x11, 0xc0, - 0x0d, 0xaf, 0xed, 0x19, 0x11, 0xc0, 0x0e, 0xaf, - 0xed, 0x13, 0x11, 0xc0, 0x0f, 0xaf, 0xed, 0x0d, - 0x11, 0xc0, 0x10, 0xaf, 0xed, 0x07, 0x11, 0xc0, - 0x11, 0xaf, 0xec, 0x19, 0x04, 0x47, 0x00, 0x00, - 0x00, 0xcb, 0xd3, 0x43, 0xb7, 0x01, 0x00, 0x00, - 0xc0, 0x12, 0xc0, 0x13, 0x34, 0x24, 0x01, 0x00, - 0xce, 0xef, 0xa2, 0x00, 0x11, 0x04, 0xde, 0x01, - 0x00, 0x00, 0xaf, 0xec, 0x06, 0xb7, 0xcd, 0xef, - 0x94, 0x00, 0xe1, 0xd3, 0xf1, 0xec, 0x06, 0xd3, - 0xeb, 0xb7, 0x9f, 0xcd, 0xd3, 0x43, 0xbf, 0x01, - 0x00, 0x00, 0x04, 0x9e, 0x00, 0x00, 0x00, 0x24, - 0x01, 0x00, 0xec, 0x09, 0x04, 0x31, 0x02, 0x00, - 0x00, 0xcb, 0xee, 0x71, 0xd3, 0x43, 0xbf, 0x01, - 0x00, 0x00, 0x04, 0x9a, 0x00, 0x00, 0x00, 0x24, - 0x01, 0x00, 0xec, 0x09, 0x04, 0x4b, 0x00, 0x00, - 0x00, 0xcb, 0xee, 0x59, 0xd3, 0x04, 0xed, 0x00, - 0x00, 0x00, 0xaf, 0x11, 0xed, 0x09, 0x0e, 0xd3, - 0x04, 0x32, 0x02, 0x00, 0x00, 0xaf, 0xec, 0x09, - 0x04, 0x33, 0x02, 0x00, 0x00, 0xcb, 0xee, 0x3d, - 0xd3, 0x04, 0x03, 0x00, 0x00, 0x00, 0xaf, 0x11, - 0xed, 0x09, 0x0e, 0xd3, 0x04, 0x02, 0x00, 0x00, - 0x00, 0xaf, 0xec, 0x09, 0x04, 0x48, 0x00, 0x00, - 0x00, 0xcb, 0xee, 0x21, 0xd3, 0x04, 0x01, 0x00, - 0x00, 0x00, 0xaf, 0xec, 0x09, 0x04, 0x01, 0x00, - 0x00, 0x00, 0xcb, 0xee, 0x10, 0xd3, 0x04, 0x46, - 0x00, 0x00, 0x00, 0xaf, 0xec, 0x07, 0x04, 0x46, - 0x00, 0x00, 0x00, 0xcb, 0x0e, 0xca, 0xec, 0x06, - 0xca, 0xb6, 0x48, 0xeb, 0xcd, 0xc9, 0xb6, 0xa9, - 0xec, 0x0d, 0xd3, 0x43, 0xaa, 0x01, 0x00, 0x00, - 0xb6, 0xc9, 0x24, 0x02, 0x00, 0xcc, 0xe0, 0xc8, - 0xc7, 0xf2, 0x0e, 0xd3, 0x43, 0xaa, 0x01, 0x00, - 0x00, 0xc8, 0xeb, 0x24, 0x01, 0x00, 0xd7, 0xef, - 0xea, 0xfd, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe8, - 0x07, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x19, - 0x02, 0xce, 0x06, 0x00, 0x01, 0x00, 0xe8, 0x05, - 0x00, 0x00, 0x00, 0xd3, 0xd3, 0xeb, 0xb7, 0x9f, - 0x48, 0xcf, 0x04, 0xd8, 0x01, 0x00, 0x00, 0xaf, - 0x11, 0xed, 0x09, 0x0e, 0xc7, 0x04, 0x1c, 0x02, - 0x00, 0x00, 0xaf, 0x28, 0x0c, 0x43, 0x02, 0x01, - 0xea, 0x07, 0x01, 0x04, 0x01, 0x08, 0x03, 0x00, - 0x7c, 0x05, 0xe2, 0x05, 0x00, 0x01, 0x00, 0xe8, - 0x08, 0x00, 0x00, 0x00, 0xea, 0x08, 0x00, 0x01, - 0x00, 0xec, 0x08, 0x00, 0x02, 0x00, 0xce, 0x06, - 0x00, 0x03, 0x00, 0xd2, 0x07, 0x08, 0x01, 0xe8, - 0x07, 0x13, 0x01, 0xea, 0x07, 0x14, 0x01, 0xdf, - 0xd3, 0x48, 0xeb, 0xcb, 0xdf, 0xd3, 0xb7, 0x9e, - 0x48, 0x04, 0x23, 0x02, 0x00, 0x00, 0xaf, 0xec, - 0x0e, 0xd3, 0xb8, 0x9e, 0xd7, 0xc7, 0xb8, 0xdf, - 0xd3, 0x48, 0xeb, 0x9e, 0x9e, 0xcb, 0xc7, 0xcc, - 0xe0, 0xdf, 0xd3, 0x48, 0xf1, 0xec, 0x4f, 0xb7, - 0xcd, 0xd3, 0x90, 0xdb, 0xdf, 0xeb, 0xa7, 0xec, - 0x45, 0xc9, 0x95, 0x01, 0xdf, 0xd3, 0x48, 0xd2, - 0x04, 0xb5, 0x01, 0x00, 0x00, 0xaf, 0x11, 0xed, - 0x09, 0x0e, 0xca, 0x04, 0x1d, 0x02, 0x00, 0x00, - 0xaf, 0xed, 0x2b, 0xee, 0x1c, 0x11, 0x7f, 0x7b, - 0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, - 0x0e, 0x3e, 0x7a, 0x34, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x82, 0x02, 0x0e, 0x3e, 0x85, 0xee, 0x06, - 0xe1, 0xd3, 0xf1, 0xee, 0xe1, 0x0e, 0xc7, 0x95, - 0x01, 0xb8, 0xcd, 0xee, 0xb5, 0xd3, 0xc8, 0x26, - 0x02, 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xec, - 0x07, 0x02, 0x02, 0x02, 0x03, 0x05, 0x00, 0x67, - 0x04, 0xe2, 0x05, 0x00, 0x01, 0x00, 0xee, 0x08, - 0x00, 0x01, 0x00, 0x92, 0x08, 0x00, 0x00, 0x00, - 0xce, 0x06, 0x00, 0x01, 0x00, 0xd2, 0x07, 0x08, - 0x01, 0xe2, 0x07, 0x10, 0x01, 0xe4, 0x07, 0x11, - 0x01, 0xe6, 0x07, 0x12, 0x01, 0xe8, 0x07, 0x13, - 0x01, 0xc2, 0xcb, 0xd3, 0xd4, 0xa8, 0xec, 0x60, - 0xdf, 0xd3, 0x92, 0xd7, 0x48, 0xd0, 0x04, 0xb5, - 0x01, 0x00, 0x00, 0xaf, 0x11, 0xed, 0x09, 0x0e, - 0xc8, 0x04, 0x1d, 0x02, 0x00, 0x00, 0xaf, 0xec, - 0x11, 0xc7, 0xeb, 0xb7, 0xa9, 0xec, 0x27, 0xe0, - 0x04, 0xd3, 0x01, 0x00, 0x00, 0xf1, 0x0e, 0xee, - 0x1d, 0xe0, 0xc7, 0xf1, 0x0e, 0xdf, 0xd3, 0x48, - 0x04, 0x23, 0x02, 0x00, 0x00, 0xaf, 0xec, 0x0e, - 0xe1, 0xc8, 0xf1, 0x0e, 0xd3, 0x90, 0xd7, 0xdf, - 0xd3, 0x92, 0xd7, 0x48, 0xcc, 0xe2, 0xc8, 0xf1, - 0x0e, 0x5f, 0x04, 0x00, 0xc8, 0xf1, 0xec, 0x08, - 0x04, 0xd3, 0x01, 0x00, 0x00, 0xee, 0x06, 0x04, - 0x38, 0x02, 0x00, 0x00, 0xcb, 0xee, 0x9d, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xee, 0x07, 0x02, 0x00, - 0x02, 0x04, 0x01, 0x00, 0x1a, 0x02, 0xce, 0x06, - 0x00, 0x01, 0x00, 0xa0, 0x07, 0x00, 0x01, 0x00, - 0xe2, 0x07, 0x10, 0x01, 0xd4, 0xb6, 0xa9, 0xec, - 0x12, 0xd3, 0x04, 0xd3, 0x01, 0x00, 0x00, 0x43, - 0x39, 0x02, 0x00, 0x00, 0xd4, 0x24, 0x01, 0x00, - 0x9e, 0xd7, 0xdf, 0xd3, 0xf1, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xf0, 0x07, 0x02, 0x0c, 0x02, 0x08, - 0x0b, 0x00, 0x8f, 0x05, 0x0e, 0xf4, 0x08, 0x00, - 0x01, 0x00, 0xf6, 0x01, 0x00, 0x01, 0x00, 0xf6, - 0x08, 0x00, 0x00, 0x00, 0xee, 0x08, 0x00, 0x01, - 0x00, 0xea, 0x08, 0x00, 0x02, 0x00, 0x92, 0x08, - 0x00, 0x03, 0x00, 0xf8, 0x08, 0x00, 0x04, 0x00, - 0xe2, 0x05, 0x00, 0x05, 0x00, 0xe8, 0x08, 0x00, - 0x06, 0x00, 0x84, 0x08, 0x00, 0x07, 0x00, 0x8a, - 0x07, 0x00, 0x08, 0x00, 0xfa, 0x08, 0x00, 0x09, - 0x00, 0xd0, 0x05, 0x00, 0x0a, 0x00, 0xfc, 0x08, - 0x00, 0x0b, 0x00, 0xc8, 0x07, 0x02, 0x01, 0xea, - 0x07, 0x14, 0x01, 0xec, 0x07, 0x15, 0x01, 0xd2, - 0x07, 0x08, 0x01, 0xe4, 0x07, 0x11, 0x01, 0xe6, - 0x07, 0x12, 0x01, 0xe8, 0x07, 0x13, 0x01, 0xb8, - 0x02, 0x10, 0x00, 0xe2, 0x07, 0x10, 0x01, 0xee, - 0x07, 0x16, 0x01, 0xf0, 0x07, 0x17, 0x01, 0xdf, - 0xd3, 0x9f, 0xb8, 0x9f, 0xcb, 0x06, 0x11, 0xf4, - 0xed, 0x0d, 0x7f, 0x82, 0x00, 0x0e, 0xcc, 0x82, - 0x00, 0x0e, 0xcd, 0x85, 0xee, 0x07, 0x0e, 0xe0, - 0xd4, 0xf1, 0xee, 0xef, 0xc9, 0xc7, 0xa8, 0xec, - 0x0c, 0xe1, 0xd4, 0xc8, 0xf2, 0x0e, 0xc8, 0xc9, - 0x26, 0x02, 0x00, 0x28, 0xe2, 0xd4, 0xb7, 0x9e, - 0x48, 0x04, 0x23, 0x02, 0x00, 0x00, 0xaf, 0xec, - 0x0d, 0x5f, 0x04, 0x00, 0xe2, 0xd4, 0x48, 0xf1, - 0x0e, 0xd4, 0xb8, 0x9e, 0xd8, 0x5f, 0x05, 0x00, - 0xe2, 0xd4, 0x48, 0xf1, 0x0e, 0x5f, 0x06, 0x00, - 0xe2, 0xd4, 0x48, 0xf1, 0x97, 0xec, 0x07, 0xd4, - 0xc9, 0x26, 0x02, 0x00, 0x28, 0xd3, 0xb8, 0x9e, - 0xd7, 0xc7, 0xb8, 0x9f, 0xcb, 0xc2, 0xce, 0xd4, - 0xb7, 0x9e, 0xc4, 0x04, 0xe2, 0xd4, 0x48, 0x43, - 0x3f, 0x02, 0x00, 0x00, 0x04, 0xd8, 0x01, 0x00, - 0x00, 0x24, 0x01, 0x00, 0x6a, 0xa9, 0x01, 0x00, - 0x00, 0xb6, 0xc4, 0x07, 0x26, 0x00, 0x00, 0xc4, - 0x0a, 0xc3, 0x04, 0xc4, 0x05, 0xc3, 0x05, 0xc8, - 0xa7, 0xec, 0x5d, 0xe2, 0xc3, 0x05, 0x48, 0xb6, - 0x48, 0x04, 0xaf, 0x01, 0x00, 0x00, 0xaf, 0x11, - 0xed, 0x0e, 0x0e, 0xe2, 0xc3, 0x05, 0xb7, 0x9e, - 0x48, 0x04, 0x23, 0x02, 0x00, 0x00, 0xaf, 0xed, - 0x3f, 0xee, 0x1c, 0x11, 0x7f, 0x7a, 0x71, 0x01, - 0x00, 0x00, 0x05, 0x00, 0x82, 0x02, 0x0e, 0x3e, - 0x7a, 0x34, 0x02, 0x00, 0x00, 0x06, 0x00, 0x82, - 0x02, 0x0e, 0x3e, 0x85, 0xee, 0x07, 0xe0, 0xc3, - 0x05, 0xf1, 0xee, 0xe0, 0x0e, 0xc3, 0x0a, 0xc3, - 0x07, 0x92, 0xc4, 0x07, 0x1b, 0x11, 0xb1, 0xed, - 0x04, 0x1b, 0x72, 0x1b, 0x1b, 0xc3, 0x06, 0x1b, - 0x72, 0x1b, 0x4a, 0x94, 0x05, 0xee, 0x9f, 0x5f, - 0x07, 0x00, 0x43, 0x91, 0x01, 0x00, 0x00, 0xc7, - 0xb9, 0x9c, 0xc3, 0x0a, 0xeb, 0xbe, 0x10, 0x24, - 0x03, 0x00, 0xc4, 0x09, 0xc3, 0x09, 0xb7, 0xa9, - 0xec, 0x73, 0x26, 0x00, 0x00, 0xc4, 0x0b, 0xb6, - 0xc4, 0x08, 0xb6, 0xc4, 0x07, 0xc3, 0x07, 0xc3, - 0x0a, 0xeb, 0xa7, 0xec, 0x3b, 0xc3, 0x0b, 0xc3, - 0x08, 0x1b, 0x11, 0xb1, 0xed, 0x04, 0x1b, 0x72, - 0x1b, 0x1b, 0x5f, 0x07, 0x00, 0x43, 0xcc, 0x01, - 0x00, 0x00, 0xc3, 0x0b, 0xc3, 0x08, 0x48, 0x11, - 0xed, 0x03, 0x0e, 0xb6, 0xc3, 0x0a, 0xc3, 0x07, - 0x48, 0xb8, 0x9e, 0x24, 0x02, 0x00, 0x1b, 0x72, - 0x1b, 0x4a, 0xc3, 0x08, 0xb7, 0x9e, 0xc3, 0x09, - 0x9d, 0xc4, 0x08, 0x94, 0x07, 0xee, 0xbf, 0xb6, - 0xc4, 0x06, 0xb6, 0xc4, 0x08, 0xc3, 0x08, 0xc3, - 0x09, 0xa7, 0xec, 0x0f, 0xc3, 0x06, 0xc3, 0x0b, - 0xc3, 0x08, 0x48, 0x9e, 0xc4, 0x06, 0x94, 0x08, - 0xee, 0xec, 0xc3, 0x06, 0xc7, 0xa8, 0xed, 0x05, - 0x93, 0x09, 0xee, 0x89, 0xc3, 0x09, 0xb7, 0xa9, - 0x6a, 0xa5, 0x00, 0x00, 0x00, 0xb6, 0xc4, 0x06, - 0xc3, 0x09, 0xb7, 0x9f, 0xc4, 0x08, 0xc3, 0x04, - 0xc4, 0x05, 0xc3, 0x05, 0xc8, 0xa7, 0x6a, 0x8b, - 0x00, 0x00, 0x00, 0xe2, 0xc3, 0x05, 0x48, 0xb6, - 0x48, 0x04, 0xaf, 0x01, 0x00, 0x00, 0xaf, 0x11, - 0xed, 0x0e, 0x0e, 0xe2, 0xc3, 0x05, 0xb7, 0x9e, - 0x48, 0x04, 0x23, 0x02, 0x00, 0x00, 0xaf, 0xed, - 0x6a, 0xc3, 0x06, 0xca, 0xeb, 0x9e, 0xc4, 0x06, - 0x5f, 0x08, 0x00, 0xca, 0xf1, 0x0e, 0x04, 0x2f, - 0x02, 0x00, 0x00, 0xce, 0xc3, 0x08, 0xc3, 0x09, - 0xb7, 0x9f, 0xaf, 0xec, 0x11, 0x5f, 0x09, 0x00, - 0x04, 0x90, 0x01, 0x00, 0x00, 0xd3, 0xf2, 0x0e, - 0xb6, 0xc4, 0x08, 0xee, 0x2f, 0x5f, 0x09, 0x00, - 0xc2, 0xc3, 0x0b, 0xc3, 0x08, 0x92, 0xc4, 0x08, - 0x48, 0xc3, 0x06, 0x9f, 0xf2, 0x0e, 0xee, 0x1c, - 0x11, 0x7f, 0x7a, 0x71, 0x01, 0x00, 0x00, 0x05, - 0x00, 0x82, 0x02, 0x0e, 0x3e, 0x7a, 0x34, 0x02, - 0x00, 0x00, 0x06, 0x00, 0x82, 0x02, 0x0e, 0x3e, - 0x85, 0xee, 0x0a, 0x5f, 0x0a, 0x00, 0xd3, 0xc3, - 0x05, 0xf2, 0xee, 0xdd, 0x0e, 0x94, 0x05, 0xef, - 0x72, 0xff, 0xc3, 0x05, 0xc4, 0x04, 0xc3, 0x04, - 0xc4, 0x05, 0xc3, 0x05, 0xc8, 0xa7, 0xec, 0x43, - 0x5f, 0x08, 0x00, 0xca, 0xf1, 0x0e, 0x04, 0x2f, - 0x02, 0x00, 0x00, 0xce, 0x5f, 0x09, 0x00, 0x04, - 0x90, 0x01, 0x00, 0x00, 0xd3, 0xf2, 0x0e, 0xee, - 0x1c, 0x11, 0x7f, 0x7a, 0x71, 0x01, 0x00, 0x00, - 0x05, 0x00, 0x82, 0x02, 0x0e, 0x3e, 0x7a, 0x34, - 0x02, 0x00, 0x00, 0x06, 0x00, 0x82, 0x02, 0x0e, - 0x3e, 0x85, 0xee, 0x0a, 0x5f, 0x0a, 0x00, 0xd3, - 0xc3, 0x05, 0xf2, 0xee, 0xdd, 0x0e, 0x94, 0x05, - 0xee, 0xb9, 0x5f, 0x09, 0x00, 0x04, 0x90, 0x01, - 0x00, 0x00, 0xd3, 0xb8, 0x9f, 0xdb, 0xf2, 0x0e, - 0x5f, 0x05, 0x00, 0xe2, 0xc8, 0x48, 0xf1, 0x0e, - 0xc8, 0xdf, 0x26, 0x02, 0x00, 0x28, 0xc1, 0x00, - 0xcc, 0xc1, 0x01, 0xc4, 0x0b, 0xc1, 0x02, 0xc4, - 0x0c, 0xc1, 0x03, 0xc4, 0x0d, 0xc1, 0x04, 0xc4, - 0x0e, 0xc1, 0x05, 0xc4, 0x0f, 0xc1, 0x06, 0xc4, - 0x10, 0xc1, 0x07, 0xc4, 0x11, 0xc1, 0x08, 0xc4, - 0x12, 0xc1, 0x09, 0xc4, 0x13, 0xc1, 0x0a, 0xc4, - 0x14, 0xc1, 0x0b, 0xc4, 0x15, 0xc1, 0x0c, 0xc4, - 0x16, 0xc1, 0x0d, 0xc4, 0x17, 0x0b, 0xcb, 0xd4, - 0x98, 0x04, 0x4a, 0x00, 0x00, 0x00, 0xaf, 0xec, - 0x1c, 0xd4, 0x07, 0xb0, 0xec, 0x17, 0xd4, 0xcf, - 0x42, 0x40, 0x02, 0x00, 0x00, 0xd8, 0xc7, 0x42, - 0x41, 0x02, 0x00, 0x00, 0xd9, 0xc7, 0x42, 0xef, - 0x00, 0x00, 0x00, 0xda, 0xd4, 0x98, 0x04, 0x48, - 0x00, 0x00, 0x00, 0xb0, 0xec, 0x03, 0x09, 0xd8, - 0xc8, 0xd5, 0xb8, 0xf2, 0xd9, 0xc8, 0xd6, 0x0a, - 0xf2, 0xda, 0xc8, 0xc7, 0x42, 0xe4, 0x01, 0x00, - 0x00, 0x5f, 0x10, 0x00, 0x43, 0x91, 0x01, 0x00, - 0x00, 0x5f, 0x11, 0x00, 0xbe, 0x50, 0x24, 0x02, - 0x00, 0xf2, 0xcd, 0xc8, 0xc7, 0x42, 0xe5, 0x01, - 0x00, 0x00, 0xbe, 0x64, 0xf2, 0xce, 0xc8, 0xc7, - 0x42, 0xe6, 0x01, 0x00, 0x00, 0xca, 0xbe, 0x0a, - 0x9e, 0xf2, 0xc4, 0x04, 0xc8, 0xc7, 0x42, 0xe7, - 0x01, 0x00, 0x00, 0xbe, 0x4e, 0xf2, 0xc4, 0x05, - 0x0b, 0x26, 0x01, 0x00, 0xc4, 0x06, 0x26, 0x00, - 0x00, 0xc4, 0x07, 0x26, 0x00, 0x00, 0xc4, 0x08, - 0x26, 0x00, 0x00, 0xc4, 0x09, 0x04, 0x8a, 0x01, - 0x00, 0x00, 0xc4, 0x0a, 0xc3, 0x0f, 0xd3, 0xb6, - 0xf2, 0x0e, 0xc3, 0x17, 0xb6, 0xb6, 0xf2, 0x0e, - 0xc3, 0x10, 0xc2, 0xf1, 0x0e, 0xc3, 0x09, 0x43, - 0x5c, 0x00, 0x00, 0x00, 0xc2, 0x25, 0x01, 0x00, - 0x0c, 0x43, 0x02, 0x01, 0xa8, 0x05, 0x01, 0x00, - 0x01, 0x07, 0x05, 0x00, 0x3c, 0x01, 0xc0, 0x07, - 0x00, 0x01, 0x00, 0xce, 0x03, 0x00, 0x0c, 0xa6, - 0x05, 0x75, 0x01, 0xec, 0x03, 0x18, 0x01, 0xe8, - 0x03, 0x16, 0x01, 0xea, 0x03, 0x17, 0x01, 0x66, - 0x00, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0xe0, - 0x43, 0x42, 0x02, 0x00, 0x00, 0xd3, 0x0b, 0xe1, - 0x4d, 0x41, 0x02, 0x00, 0x00, 0xe2, 0x4d, 0xef, - 0x00, 0x00, 0x00, 0x5f, 0x04, 0x00, 0x4d, 0x40, - 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0x24, 0x01, - 0x00, 0x0e, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xaa, - 0x05, 0x01, 0x05, 0x01, 0x06, 0x03, 0x00, 0xb4, - 0x01, 0x06, 0xee, 0x05, 0x00, 0x01, 0x00, 0xb6, - 0x06, 0x00, 0x00, 0x00, 0x8a, 0x04, 0x00, 0x01, - 0x00, 0x86, 0x09, 0x00, 0x02, 0x00, 0xb6, 0x07, - 0x00, 0x03, 0x00, 0x88, 0x09, 0x00, 0x04, 0x00, - 0xac, 0x05, 0x78, 0x01, 0xb4, 0x05, 0x7c, 0x01, - 0xce, 0x03, 0x00, 0x0c, 0xd3, 0x04, 0x45, 0x02, - 0x00, 0x00, 0xaf, 0xec, 0x06, 0xdf, 0xf0, 0x0e, - 0x0a, 0x28, 0xd3, 0xb6, 0x48, 0x04, 0xae, 0x01, - 0x00, 0x00, 0xb0, 0xec, 0x0e, 0xd3, 0xb6, 0x48, - 0x04, 0xaf, 0x01, 0x00, 0x00, 0xb0, 0xec, 0x03, - 0x09, 0x28, 0xb7, 0xcb, 0xc7, 0xd3, 0xeb, 0xa7, - 0xec, 0x10, 0xd3, 0xc7, 0x48, 0x04, 0xd3, 0x01, - 0x00, 0x00, 0xb0, 0xec, 0x05, 0x94, 0x00, 0xee, - 0xec, 0xd3, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xb7, - 0xc7, 0x24, 0x02, 0x00, 0xcc, 0xb6, 0xcd, 0xe0, - 0x7e, 0xee, 0x21, 0xc4, 0x04, 0xc3, 0x04, 0x43, - 0xbf, 0x01, 0x00, 0x00, 0xc8, 0x24, 0x01, 0x00, - 0xec, 0x12, 0xe0, 0xc3, 0x04, 0x48, 0xce, 0x94, - 0x02, 0xc3, 0x04, 0xc8, 0xaf, 0xec, 0x05, 0xb6, - 0xcd, 0xee, 0x05, 0x81, 0xec, 0xde, 0x0e, 0x0e, - 0xca, 0xec, 0x1d, 0xc9, 0xb8, 0xa7, 0xec, 0x18, - 0xca, 0xd3, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xc7, - 0x24, 0x01, 0x00, 0x43, 0x46, 0x02, 0x00, 0x00, - 0x24, 0x00, 0x00, 0xf1, 0x0e, 0xee, 0x20, 0x66, - 0x02, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, - 0x47, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0xc8, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, - 0x02, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x0a, 0x28, - 0x0c, 0x43, 0x02, 0x01, 0xac, 0x05, 0x00, 0x01, - 0x00, 0x07, 0x09, 0x01, 0xdc, 0x01, 0x01, 0x90, - 0x09, 0x00, 0x00, 0x00, 0xce, 0x03, 0x00, 0x0c, - 0xee, 0x03, 0x19, 0x01, 0xe6, 0x03, 0x15, 0x01, - 0xf0, 0x03, 0x1a, 0x01, 0xec, 0x03, 0x18, 0x01, - 0xea, 0x03, 0x17, 0x01, 0xe8, 0x03, 0x16, 0x01, - 0xe2, 0x03, 0x13, 0x01, 0xe0, 0x03, 0x12, 0x01, - 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x0f, 0x01, 0x98, 0x06, 0x00, - 0x01, 0x00, 0xd3, 0xec, 0x07, 0x04, 0x7f, 0x00, - 0x00, 0x00, 0x28, 0x04, 0xd3, 0x01, 0x00, 0x00, - 0x28, 0xc1, 0x00, 0x4e, 0x48, 0x02, 0x00, 0x00, - 0xcb, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, 0x00, - 0x00, 0x04, 0x49, 0x02, 0x00, 0x00, 0x04, 0x4a, - 0x02, 0x00, 0x00, 0x9e, 0xc7, 0xe0, 0xf1, 0x9e, - 0x04, 0x4b, 0x02, 0x00, 0x00, 0x9e, 0x04, 0x4c, - 0x02, 0x00, 0x00, 0x9e, 0xc7, 0xe0, 0x97, 0xf1, - 0x9e, 0x04, 0x4d, 0x02, 0x00, 0x00, 0x9e, 0x04, - 0x4e, 0x02, 0x00, 0x00, 0x9e, 0xc7, 0xe1, 0xf1, - 0x9e, 0x04, 0x4f, 0x02, 0x00, 0x00, 0x9e, 0x04, - 0x50, 0x02, 0x00, 0x00, 0x9e, 0xc7, 0xe2, 0xf1, - 0x9e, 0x04, 0x51, 0x02, 0x00, 0x00, 0x9e, 0x04, - 0x52, 0x02, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0x5f, 0x04, 0x00, 0x04, 0x53, 0x02, 0x00, - 0x00, 0x24, 0x02, 0x00, 0x9e, 0x04, 0x54, 0x02, - 0x00, 0x00, 0x9e, 0xc7, 0x5f, 0x05, 0x00, 0xf1, - 0x9e, 0x04, 0x55, 0x02, 0x00, 0x00, 0x9e, 0x04, - 0x56, 0x02, 0x00, 0x00, 0x9e, 0xc7, 0x5f, 0x06, - 0x00, 0xf1, 0x9e, 0x04, 0x57, 0x02, 0x00, 0x00, - 0x9e, 0x04, 0x58, 0x02, 0x00, 0x00, 0x9e, 0xc7, - 0x5f, 0x07, 0x00, 0x5f, 0x08, 0x00, 0x42, 0x59, - 0x02, 0x00, 0x00, 0xad, 0xf1, 0x9e, 0x04, 0x5a, - 0x02, 0x00, 0x00, 0x9e, 0x04, 0x5b, 0x02, 0x00, - 0x00, 0x9e, 0xc7, 0x5f, 0x07, 0x00, 0x5f, 0x08, - 0x00, 0x42, 0x5c, 0x02, 0x00, 0x00, 0xad, 0xf1, - 0x9e, 0x04, 0x5d, 0x02, 0x00, 0x00, 0x9e, 0x04, - 0x5e, 0x02, 0x00, 0x00, 0x9e, 0x04, 0x5f, 0x02, - 0x00, 0x00, 0x9e, 0x04, 0x60, 0x02, 0x00, 0x00, - 0x9e, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xae, 0x05, 0x01, 0x01, 0x01, 0x07, 0x01, - 0x00, 0x5f, 0x02, 0xce, 0x06, 0x00, 0x01, 0x00, - 0xc2, 0x09, 0x04, 0x00, 0x03, 0xce, 0x03, 0x00, - 0x0c, 0xd3, 0x43, 0x62, 0x02, 0x00, 0x00, 0x04, - 0xaf, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xd3, - 0x43, 0x62, 0x02, 0x00, 0x00, 0x04, 0xb6, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0xa8, 0xec, 0x09, - 0xd3, 0x04, 0x63, 0x02, 0x00, 0x00, 0x9e, 0xd7, - 0x6d, 0x13, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, - 0x43, 0x64, 0x02, 0x00, 0x00, 0xd3, 0x24, 0x01, - 0x00, 0x0e, 0x0e, 0x29, 0xcb, 0x6d, 0x21, 0x00, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0xc2, 0x43, 0x5d, 0x00, 0x00, 0x00, - 0xc7, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0x0e, 0x29, 0x30, - 0x0c, 0x43, 0x02, 0x01, 0xb0, 0x05, 0x01, 0x00, - 0x01, 0x03, 0x02, 0x00, 0x10, 0x01, 0xc2, 0x09, - 0x00, 0x01, 0x00, 0xca, 0x05, 0x87, 0x01, 0x01, - 0xce, 0x03, 0x00, 0x0c, 0xdf, 0xf0, 0x0e, 0x66, - 0x01, 0x00, 0x43, 0x58, 0x01, 0x00, 0x00, 0xd3, - 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xb2, 0x05, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, - 0x14, 0x02, 0xce, 0x06, 0x00, 0x01, 0x00, 0xf4, - 0x07, 0x00, 0x01, 0x00, 0xd3, 0xec, 0x10, 0x04, - 0x65, 0x02, 0x00, 0x00, 0x43, 0xfb, 0x01, 0x00, - 0x00, 0xd3, 0x24, 0x01, 0x00, 0x28, 0xd4, 0x28, - 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x03, 0x02, 0x00, 0x06, 0x01, 0xce, 0x06, 0x00, - 0x01, 0x00, 0xee, 0x03, 0x19, 0x01, 0xb2, 0x05, - 0x7b, 0x01, 0xe0, 0xd3, 0x0a, 0xf2, 0xe3, 0x29, - 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x03, 0x02, 0x00, 0x07, 0x01, 0xce, 0x06, 0x00, - 0x01, 0x00, 0xee, 0x03, 0x19, 0x01, 0xb2, 0x05, - 0x7b, 0x01, 0xe0, 0xd3, 0x0a, 0xf2, 0x97, 0xe3, - 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x03, 0x02, 0x00, 0x07, 0x01, 0xce, 0x06, - 0x00, 0x01, 0x00, 0xe6, 0x03, 0x15, 0x01, 0xb2, - 0x05, 0x7b, 0x01, 0xe0, 0xd3, 0xdf, 0x97, 0xf2, - 0xe3, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x03, 0x02, 0x00, 0x07, 0x01, 0xce, - 0x06, 0x00, 0x01, 0x00, 0xf0, 0x03, 0x1a, 0x01, - 0xb2, 0x05, 0x7b, 0x01, 0xe0, 0xd3, 0xdf, 0x97, - 0xf2, 0xe3, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x09, 0x01, - 0xce, 0x06, 0x00, 0x01, 0x00, 0xec, 0x03, 0x18, - 0x01, 0xd3, 0x8e, 0x11, 0xed, 0x03, 0x0e, 0xb8, - 0xe3, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x03, 0x02, 0x00, 0x07, 0x01, 0xce, - 0x06, 0x00, 0x01, 0x00, 0xea, 0x03, 0x17, 0x01, - 0xb2, 0x05, 0x7b, 0x01, 0xe0, 0xd3, 0xdf, 0x97, - 0xf2, 0xe3, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x03, 0x02, 0x00, 0x07, 0x01, - 0xce, 0x06, 0x00, 0x01, 0x00, 0xe8, 0x03, 0x16, - 0x01, 0xb2, 0x05, 0x7b, 0x01, 0xe0, 0xd3, 0xdf, - 0x97, 0xf2, 0xe3, 0x29, 0x0c, 0x42, 0x02, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x08, - 0x00, 0xe2, 0x03, 0x13, 0x01, 0xe0, 0x03, 0x12, - 0x01, 0xe0, 0x42, 0x59, 0x02, 0x00, 0x00, 0xe3, - 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x00, 0x08, 0x00, 0xe2, 0x03, - 0x13, 0x01, 0xe0, 0x03, 0x12, 0x01, 0xe0, 0x42, - 0x5c, 0x02, 0x00, 0x00, 0xe3, 0x29, 0x0c, 0x42, - 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, - 0x00, 0x11, 0x00, 0xce, 0x03, 0x00, 0x0c, 0x66, - 0x00, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, - 0x66, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x29, - 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x04, 0x00, 0xb0, 0x05, 0x7a, - 0x01, 0xdf, 0xb6, 0xf1, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xb6, 0x05, 0x00, 0x00, 0x00, 0x03, 0x02, - 0x00, 0x14, 0x00, 0xce, 0x03, 0x00, 0x0c, 0xb8, - 0x05, 0x7e, 0x01, 0x66, 0x00, 0x00, 0x43, 0x89, - 0x01, 0x00, 0x00, 0x04, 0x67, 0x02, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x0e, 0xe0, 0xf0, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xb8, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x04, 0x00, 0x0c, 0x00, 0x9c, 0x05, 0x70, - 0x01, 0x92, 0x05, 0x6b, 0x01, 0x88, 0x04, 0x26, - 0x01, 0xba, 0x05, 0x7f, 0x01, 0xdf, 0xe0, 0x04, - 0x68, 0x02, 0x00, 0x00, 0xe1, 0xf2, 0xe2, 0xf2, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xba, 0x05, 0x01, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x0a, 0x01, 0xd2, - 0x09, 0x00, 0x01, 0x00, 0xbc, 0x05, 0x80, 0x01, - 0x01, 0xb8, 0x05, 0x7e, 0x01, 0xdf, 0xd3, 0xf1, - 0x97, 0xec, 0x04, 0xe0, 0xf0, 0x0e, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xbc, 0x05, 0x01, 0x01, 0x01, - 0x02, 0x06, 0x00, 0x3a, 0x02, 0xd2, 0x09, 0x00, - 0x01, 0x00, 0xaa, 0x06, 0x00, 0x00, 0x00, 0x86, - 0x04, 0x25, 0x01, 0xaa, 0x05, 0x77, 0x01, 0xc6, - 0x05, 0x85, 0x01, 0x01, 0xf8, 0x03, 0x1e, 0x01, - 0x88, 0x04, 0x26, 0x01, 0xbe, 0x05, 0x81, 0x01, - 0x01, 0xd3, 0x97, 0xec, 0x03, 0x09, 0x28, 0xdf, - 0xec, 0x0d, 0xdf, 0x04, 0x90, 0x01, 0x00, 0x00, - 0x9e, 0xd3, 0x9e, 0xd7, 0xee, 0x08, 0xe0, 0xd3, - 0xf1, 0xec, 0x03, 0x09, 0x28, 0xe1, 0xd3, 0xf1, - 0xcf, 0xb6, 0x48, 0xe6, 0xc7, 0xb7, 0x48, 0x60, - 0x04, 0x00, 0xe2, 0xec, 0x05, 0xd3, 0xe3, 0x09, - 0x28, 0xc2, 0xe3, 0x5f, 0x05, 0x00, 0xd3, 0xf1, - 0x0e, 0x0a, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xbe, - 0x05, 0x01, 0x01, 0x01, 0x06, 0x06, 0x00, 0x4a, - 0x02, 0xd2, 0x09, 0x00, 0x01, 0x00, 0xd4, 0x09, - 0x00, 0x00, 0x00, 0xf0, 0x03, 0x1a, 0x01, 0x82, - 0x04, 0x23, 0x01, 0xd0, 0x03, 0x01, 0x0c, 0xce, - 0x03, 0x00, 0x0c, 0xc0, 0x05, 0x82, 0x01, 0x01, - 0xc2, 0x05, 0x83, 0x01, 0x01, 0xdf, 0xec, 0x09, - 0x04, 0x6b, 0x02, 0x00, 0x00, 0xd3, 0x9e, 0xd7, - 0x66, 0x02, 0x00, 0x43, 0x6c, 0x02, 0x00, 0x00, - 0x24, 0x00, 0x00, 0xe4, 0x39, 0xc4, 0x00, 0x00, - 0x00, 0x43, 0x18, 0x00, 0x00, 0x00, 0x66, 0x03, - 0x00, 0x42, 0x6d, 0x02, 0x00, 0x00, 0xd3, 0x0b, - 0x0a, 0x4d, 0x6e, 0x02, 0x00, 0x00, 0x0a, 0x4d, - 0x87, 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, 0xcf, - 0x43, 0x81, 0x00, 0x00, 0x00, 0x5f, 0x04, 0x00, - 0x5f, 0x05, 0x00, 0x24, 0x02, 0x00, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xc0, 0x05, 0x01, 0x00, 0x01, - 0x02, 0x06, 0x00, 0x27, 0x01, 0xd4, 0x09, 0x00, - 0x01, 0x00, 0x84, 0x04, 0x24, 0x01, 0xd0, 0x03, - 0x01, 0x0c, 0x82, 0x04, 0x23, 0x01, 0xa8, 0x05, - 0x76, 0x01, 0xd4, 0x03, 0x00, 0x03, 0xc4, 0x05, - 0x84, 0x01, 0x01, 0xd3, 0x42, 0x41, 0x00, 0x00, - 0x00, 0xd7, 0x66, 0x01, 0x00, 0x43, 0x6c, 0x02, - 0x00, 0x00, 0x24, 0x00, 0x00, 0xe1, 0x9f, 0xe3, - 0xe2, 0xd3, 0xf1, 0x0e, 0x5f, 0x04, 0x00, 0xd3, - 0x44, 0x79, 0x01, 0x00, 0x00, 0x5f, 0x05, 0x00, - 0xf0, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc2, 0x05, - 0x01, 0x00, 0x01, 0x04, 0x06, 0x00, 0xa1, 0x01, - 0x01, 0xde, 0x09, 0x00, 0x01, 0x00, 0xe8, 0x03, - 0x16, 0x01, 0xce, 0x03, 0x00, 0x0c, 0xde, 0x03, - 0x11, 0x01, 0xe2, 0x03, 0x13, 0x01, 0xac, 0x02, - 0x09, 0x01, 0xc4, 0x05, 0x84, 0x01, 0x01, 0xdf, - 0xec, 0x15, 0x66, 0x01, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0xe1, 0xe2, 0x42, 0x6f, 0x02, 0x00, - 0x00, 0x48, 0x24, 0x01, 0x00, 0x0e, 0xd3, 0x5f, - 0x04, 0x00, 0xab, 0xec, 0x3b, 0x66, 0x01, 0x00, - 0x43, 0x89, 0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, - 0x00, 0x0e, 0x66, 0x01, 0x00, 0x43, 0x89, 0x01, - 0x00, 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0xd3, 0x42, 0x36, 0x00, 0x00, - 0x00, 0xec, 0x44, 0x66, 0x01, 0x00, 0x43, 0x89, - 0x01, 0x00, 0x00, 0xd3, 0x42, 0x36, 0x00, 0x00, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0xee, 0x30, 0x66, - 0x01, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, - 0x70, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, - 0x66, 0x01, 0x00, 0x43, 0x89, 0x01, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0x0e, 0x66, 0x01, 0x00, - 0x43, 0x89, 0x01, 0x00, 0x00, 0x04, 0x90, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xdf, 0xec, - 0x13, 0x66, 0x01, 0x00, 0x43, 0x89, 0x01, 0x00, - 0x00, 0xe1, 0x42, 0x8a, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0x5f, 0x05, 0x00, 0xf0, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xc4, 0x05, 0x00, 0x00, - 0x00, 0x02, 0x03, 0x00, 0x11, 0x00, 0x88, 0x04, - 0x26, 0x01, 0xce, 0x03, 0x00, 0x0c, 0xb8, 0x05, - 0x7e, 0x01, 0xb6, 0xe3, 0x66, 0x01, 0x00, 0x43, - 0x71, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, - 0xe1, 0xf0, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc6, - 0x05, 0x01, 0x17, 0x01, 0x04, 0x03, 0x0a, 0x84, - 0x04, 0x18, 0xf6, 0x05, 0x00, 0x01, 0x40, 0xe2, - 0x05, 0x00, 0x00, 0x40, 0xe8, 0x05, 0x00, 0x01, - 0x40, 0x8a, 0x06, 0x00, 0x02, 0x40, 0x98, 0x06, - 0x00, 0x03, 0x40, 0x90, 0x06, 0x00, 0x04, 0x40, - 0xe4, 0x09, 0x00, 0x05, 0x40, 0x88, 0x04, 0x00, - 0x06, 0x00, 0xe6, 0x09, 0x00, 0x07, 0x00, 0xe8, - 0x09, 0x00, 0x08, 0x40, 0xf2, 0x06, 0x00, 0x09, - 0x40, 0xea, 0x09, 0x00, 0x0a, 0x40, 0xec, 0x09, - 0x00, 0x0b, 0x40, 0xee, 0x09, 0x00, 0x0c, 0x40, - 0xf0, 0x09, 0x00, 0x0d, 0x00, 0xf2, 0x09, 0x00, - 0x0e, 0x00, 0xf4, 0x09, 0x00, 0x0f, 0x00, 0xf6, - 0x09, 0x00, 0x10, 0x00, 0xf8, 0x09, 0x00, 0x11, - 0x00, 0xfa, 0x09, 0x00, 0x12, 0x40, 0xfc, 0x09, - 0x00, 0x13, 0x40, 0xfe, 0x09, 0x00, 0x14, 0x40, - 0x80, 0x0a, 0x00, 0x15, 0x00, 0x82, 0x0a, 0x00, - 0x16, 0x00, 0xb0, 0x04, 0x3a, 0x01, 0xb6, 0x04, - 0x3d, 0x01, 0xae, 0x04, 0x39, 0x01, 0x0c, 0x43, - 0x02, 0x01, 0xea, 0x09, 0x01, 0x00, 0x01, 0x02, - 0x01, 0x00, 0x05, 0x01, 0xe8, 0x05, 0x00, 0x01, - 0x00, 0xe4, 0x09, 0x05, 0x01, 0xdf, 0xd3, 0x9e, - 0xe3, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xec, 0x09, - 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x0d, 0x01, - 0xe8, 0x05, 0x00, 0x01, 0x00, 0xe4, 0x09, 0x05, - 0x01, 0xdf, 0x43, 0x8b, 0x01, 0x00, 0x00, 0xdf, - 0xeb, 0xb7, 0x9f, 0x25, 0x01, 0x00, 0x0c, 0x43, - 0x02, 0x01, 0xee, 0x09, 0x01, 0x00, 0x01, 0x05, - 0x02, 0x00, 0x14, 0x01, 0xe8, 0x05, 0x00, 0x01, - 0x00, 0xec, 0x09, 0x0b, 0x01, 0xe4, 0x09, 0x05, - 0x01, 0xdf, 0xf0, 0xd7, 0xe0, 0x43, 0x8b, 0x01, - 0x00, 0x00, 0xb6, 0xe0, 0xeb, 0xb7, 0x9f, 0x24, - 0x02, 0x00, 0xe4, 0xd3, 0x28, 0x0c, 0x43, 0x02, - 0x01, 0xf0, 0x09, 0x00, 0x00, 0x00, 0x03, 0x06, - 0x00, 0x49, 0x00, 0x90, 0x06, 0x04, 0x01, 0xea, - 0x09, 0x0a, 0x01, 0xe2, 0x05, 0x00, 0x01, 0x98, - 0x06, 0x03, 0x01, 0xf6, 0x05, 0x00, 0x03, 0xee, - 0x09, 0x0c, 0x01, 0x04, 0x82, 0x02, 0x00, 0x00, - 0xe3, 0xe0, 0x04, 0xb6, 0x01, 0x00, 0x00, 0xf1, - 0x0e, 0xe1, 0x90, 0xe5, 0xe1, 0xe2, 0xb7, 0x9f, - 0xa7, 0xec, 0x31, 0x5f, 0x04, 0x00, 0xe1, 0x48, - 0x04, 0x7f, 0x00, 0x00, 0x00, 0xad, 0xec, 0x1f, - 0x5f, 0x04, 0x00, 0xe1, 0xb7, 0x9e, 0x48, 0x04, - 0xb6, 0x01, 0x00, 0x00, 0xad, 0xec, 0x10, 0xe1, - 0xb8, 0x9e, 0xe5, 0x5f, 0x05, 0x00, 0x04, 0xb6, - 0x01, 0x00, 0x00, 0xf1, 0x0e, 0x29, 0xe1, 0x90, - 0xe5, 0xee, 0xca, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xf2, 0x09, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, - 0x1f, 0x00, 0x90, 0x06, 0x04, 0x01, 0xe2, 0x05, - 0x00, 0x01, 0x98, 0x06, 0x03, 0x01, 0xf6, 0x05, - 0x00, 0x03, 0x04, 0x82, 0x02, 0x00, 0x00, 0xe3, - 0xe0, 0x90, 0xe4, 0xe0, 0xe1, 0xa7, 0xec, 0x11, - 0xe2, 0xe0, 0x48, 0x04, 0x90, 0x01, 0x00, 0x00, - 0xad, 0xed, 0x06, 0xe0, 0x90, 0xe4, 0xee, 0xec, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf4, 0x09, 0x01, - 0x00, 0x01, 0x03, 0x07, 0x00, 0x4c, 0x01, 0x86, - 0x0a, 0x00, 0x01, 0x00, 0x90, 0x06, 0x04, 0x01, - 0xea, 0x09, 0x0a, 0x01, 0xe2, 0x05, 0x00, 0x01, - 0x98, 0x06, 0x03, 0x01, 0xe8, 0x05, 0x01, 0x01, - 0xf6, 0x05, 0x00, 0x03, 0xee, 0x09, 0x0c, 0x01, - 0x04, 0x49, 0x00, 0x00, 0x00, 0xe3, 0xe0, 0xd3, - 0xf1, 0x0e, 0xe1, 0xe2, 0xa7, 0xec, 0x3d, 0x5f, - 0x05, 0x00, 0xe1, 0x92, 0xe5, 0x48, 0x61, 0x04, - 0x00, 0x04, 0x90, 0x01, 0x00, 0x00, 0xad, 0xec, - 0x09, 0x04, 0x6f, 0x02, 0x00, 0x00, 0xe3, 0xee, - 0xe2, 0x5f, 0x04, 0x00, 0x04, 0xae, 0x01, 0x00, - 0x00, 0xad, 0xec, 0x0b, 0xe1, 0xe2, 0xaa, 0xed, - 0x13, 0xe1, 0x90, 0xe5, 0xee, 0xcd, 0x5f, 0x04, - 0x00, 0xd3, 0xad, 0xec, 0xc6, 0x5f, 0x06, 0x00, - 0xf0, 0x0e, 0x29, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xf6, 0x09, 0x00, 0x00, 0x00, 0x03, 0x09, 0x00, - 0xc4, 0x01, 0x00, 0x90, 0x06, 0x04, 0x01, 0xea, - 0x09, 0x0a, 0x01, 0xe2, 0x05, 0x00, 0x01, 0x98, - 0x06, 0x03, 0x01, 0xe8, 0x05, 0x01, 0x01, 0xf6, - 0x05, 0x00, 0x03, 0xec, 0x09, 0x0b, 0x01, 0xee, - 0x09, 0x0c, 0x01, 0xb0, 0x04, 0x00, 0x00, 0x04, - 0x2d, 0x02, 0x00, 0x00, 0xe3, 0xe0, 0x04, 0xb6, - 0x01, 0x00, 0x00, 0xf1, 0x0e, 0xe1, 0xe2, 0xa7, - 0x6a, 0xb1, 0x00, 0x00, 0x00, 0x5f, 0x05, 0x00, - 0xe1, 0x92, 0xe5, 0x48, 0x61, 0x04, 0x00, 0x04, - 0x90, 0x01, 0x00, 0x00, 0xad, 0xec, 0x09, 0x04, - 0x6f, 0x02, 0x00, 0x00, 0xe3, 0xee, 0xdf, 0x5f, - 0x04, 0x00, 0x04, 0xae, 0x01, 0x00, 0x00, 0xad, - 0xec, 0x0b, 0xe1, 0xe2, 0xa7, 0xec, 0xcf, 0xe1, - 0x90, 0xe5, 0xee, 0xca, 0x5f, 0x06, 0x00, 0xf0, - 0x04, 0xd8, 0x01, 0x00, 0x00, 0xad, 0xec, 0x13, - 0x5f, 0x04, 0x00, 0x04, 0xb5, 0x01, 0x00, 0x00, - 0xad, 0xec, 0xb3, 0x5f, 0x07, 0x00, 0xf0, 0x0e, - 0xee, 0xac, 0x5f, 0x04, 0x00, 0x04, 0xd8, 0x01, - 0x00, 0x00, 0xad, 0xec, 0x2e, 0xe0, 0x04, 0xd8, - 0x01, 0x00, 0x00, 0xf1, 0x0e, 0x5f, 0x05, 0x00, - 0xe1, 0x48, 0x04, 0xd8, 0x01, 0x00, 0x00, 0xad, - 0x11, 0xed, 0x0d, 0x0e, 0x5f, 0x05, 0x00, 0xe1, - 0x48, 0x04, 0xb5, 0x01, 0x00, 0x00, 0xad, 0x6a, - 0x7d, 0xff, 0xff, 0xff, 0xe1, 0x90, 0xe5, 0xef, - 0x75, 0xff, 0x5f, 0x04, 0x00, 0x04, 0xb6, 0x01, - 0x00, 0x00, 0xad, 0x6a, 0x69, 0xff, 0xff, 0xff, - 0x5f, 0x07, 0x00, 0xf0, 0x0e, 0xe1, 0xe2, 0xa7, - 0xec, 0x11, 0x5f, 0x08, 0x00, 0x5f, 0x05, 0x00, - 0xe1, 0x48, 0xf1, 0xec, 0x06, 0xe1, 0x90, 0xe5, - 0xee, 0xec, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf8, - 0x09, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x41, - 0x00, 0x90, 0x06, 0x04, 0x01, 0xe2, 0x05, 0x00, - 0x01, 0x98, 0x06, 0x03, 0x01, 0xb0, 0x04, 0x00, - 0x00, 0xf6, 0x05, 0x00, 0x03, 0x04, 0x47, 0x00, - 0x00, 0x00, 0xe3, 0xe0, 0xe1, 0xa7, 0xec, 0x36, - 0xe2, 0x5f, 0x04, 0x00, 0xe0, 0x48, 0xf1, 0x11, - 0xed, 0x25, 0x0e, 0x5f, 0x04, 0x00, 0xe0, 0x48, - 0x04, 0xaf, 0x01, 0x00, 0x00, 0xad, 0xec, 0x1e, - 0xe0, 0xe1, 0xb7, 0x9f, 0xad, 0x11, 0xed, 0x0f, - 0x0e, 0x5f, 0x04, 0x00, 0xe0, 0xb7, 0x9e, 0x48, - 0x04, 0xaf, 0x01, 0x00, 0x00, 0xae, 0xec, 0x06, - 0xe0, 0x90, 0xe4, 0xee, 0xc7, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0x80, 0x0a, 0x00, 0x03, 0x00, 0x04, - 0x0a, 0x00, 0x95, 0x02, 0x03, 0xce, 0x06, 0x00, - 0x00, 0x00, 0xe8, 0x08, 0x00, 0x01, 0x00, 0x88, - 0x0a, 0x00, 0x02, 0x00, 0xe8, 0x09, 0x08, 0x01, - 0xe2, 0x05, 0x00, 0x01, 0x98, 0x06, 0x03, 0x01, - 0xb0, 0x04, 0x00, 0x00, 0xf6, 0x05, 0x00, 0x03, - 0x8a, 0x06, 0x02, 0x01, 0xfa, 0x09, 0x12, 0x01, - 0x90, 0x06, 0x04, 0x01, 0xfc, 0x09, 0x13, 0x01, - 0xfe, 0x09, 0x14, 0x01, 0xb7, 0xe3, 0xe0, 0xe1, - 0xa7, 0xec, 0x0f, 0xe2, 0x5f, 0x04, 0x00, 0xe0, - 0x48, 0xf1, 0xec, 0x06, 0xe0, 0x90, 0xe4, 0xee, - 0xee, 0x5f, 0x04, 0x00, 0x43, 0x8b, 0x01, 0x00, - 0x00, 0x5f, 0x05, 0x00, 0xe0, 0x24, 0x02, 0x00, - 0xcb, 0x04, 0x85, 0x02, 0x00, 0x00, 0xc7, 0x9e, - 0x04, 0x85, 0x02, 0x00, 0x00, 0x9e, 0xcc, 0x5f, - 0x06, 0x00, 0x43, 0xb1, 0x01, 0x00, 0x00, 0xc8, - 0x24, 0x01, 0x00, 0xb6, 0xaa, 0xec, 0x7c, 0x04, - 0x33, 0x02, 0x00, 0x00, 0x60, 0x07, 0x00, 0xc7, - 0x04, 0x03, 0x00, 0x00, 0x00, 0xaf, 0x11, 0xed, - 0x09, 0x0e, 0xc7, 0x04, 0x02, 0x00, 0x00, 0x00, - 0xaf, 0xec, 0x0b, 0x04, 0x48, 0x00, 0x00, 0x00, - 0x60, 0x07, 0x00, 0xee, 0x43, 0xc7, 0x04, 0x03, - 0x00, 0x00, 0x00, 0xaf, 0x11, 0xed, 0x09, 0x0e, - 0xc7, 0x04, 0x02, 0x00, 0x00, 0x00, 0xaf, 0xec, - 0x0b, 0x04, 0x48, 0x00, 0x00, 0x00, 0x60, 0x07, - 0x00, 0xee, 0x25, 0xc7, 0x04, 0x01, 0x00, 0x00, - 0x00, 0xaf, 0xec, 0x0b, 0x04, 0x01, 0x00, 0x00, - 0x00, 0x60, 0x07, 0x00, 0xee, 0x12, 0xc7, 0x04, - 0x46, 0x00, 0x00, 0x00, 0xaf, 0xec, 0x09, 0x04, - 0x46, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x5f, - 0x08, 0x00, 0x43, 0xb1, 0x01, 0x00, 0x00, 0xc8, - 0x24, 0x01, 0x00, 0xb6, 0xaa, 0xec, 0x03, 0xb6, - 0xe3, 0x29, 0xe0, 0xcd, 0xc9, 0xe1, 0xa7, 0xec, - 0x12, 0x5f, 0x04, 0x00, 0xc9, 0x48, 0x04, 0xd3, - 0x01, 0x00, 0x00, 0xad, 0xec, 0x05, 0x94, 0x02, - 0xee, 0xeb, 0xc9, 0xe1, 0xa7, 0xec, 0x17, 0x5f, - 0x04, 0x00, 0xc9, 0x48, 0x04, 0xca, 0x01, 0x00, - 0x00, 0xad, 0xec, 0x0a, 0x04, 0x1b, 0x00, 0x00, - 0x00, 0x60, 0x07, 0x00, 0x29, 0x5f, 0x09, 0x00, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0xc8, 0x24, 0x01, - 0x00, 0xb6, 0xaa, 0xec, 0x0a, 0x04, 0x04, 0x02, - 0x00, 0x00, 0x60, 0x07, 0x00, 0x29, 0x04, 0x86, - 0x02, 0x00, 0x00, 0x60, 0x07, 0x00, 0xb6, 0xe3, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0x82, 0x0a, 0x02, - 0x00, 0x02, 0x03, 0x02, 0x00, 0x2b, 0x02, 0xf6, - 0x01, 0x00, 0x01, 0x00, 0x8e, 0x0a, 0x00, 0x01, - 0x00, 0xf2, 0x06, 0x09, 0x01, 0x90, 0x06, 0x04, - 0x01, 0xdf, 0xeb, 0xd3, 0xa7, 0xec, 0x12, 0xdf, - 0x43, 0x9e, 0x01, 0x00, 0x00, 0x04, 0x16, 0x00, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xee, 0xea, - 0xdf, 0xeb, 0xd4, 0xa7, 0xec, 0x0e, 0xdf, 0x43, - 0x9e, 0x01, 0x00, 0x00, 0xe0, 0x24, 0x01, 0x00, - 0x0e, 0xee, 0xee, 0x29, 0xc1, 0x00, 0xc4, 0x0a, - 0xc1, 0x01, 0xc4, 0x0b, 0xc1, 0x02, 0xc4, 0x0c, - 0xc1, 0x03, 0xc4, 0x0d, 0xc1, 0x04, 0xc4, 0x0e, - 0xc1, 0x05, 0xc4, 0x0f, 0xc1, 0x06, 0xc4, 0x10, - 0xc1, 0x07, 0xc4, 0x11, 0xc1, 0x08, 0xc4, 0x15, - 0xc1, 0x09, 0xc4, 0x16, 0xd3, 0xeb, 0xce, 0xc2, - 0xc4, 0x05, 0xb6, 0xc4, 0x06, 0xb7, 0xc4, 0x08, - 0x26, 0x00, 0x00, 0xc4, 0x09, 0x04, 0x85, 0x02, - 0x00, 0x00, 0x04, 0x88, 0x02, 0x00, 0x00, 0x9e, - 0x04, 0x89, 0x02, 0x00, 0x00, 0x9e, 0x04, 0x8a, - 0x02, 0x00, 0x00, 0x9e, 0x04, 0x8b, 0x02, 0x00, - 0x00, 0x9e, 0x04, 0x8c, 0x02, 0x00, 0x00, 0x9e, - 0x04, 0x8d, 0x02, 0x00, 0x00, 0x9e, 0x04, 0x8e, - 0x02, 0x00, 0x00, 0x9e, 0x04, 0x8f, 0x02, 0x00, - 0x00, 0x9e, 0x04, 0x90, 0x02, 0x00, 0x00, 0x9e, - 0xc4, 0x12, 0x04, 0x91, 0x02, 0x00, 0x00, 0xc4, - 0x13, 0x04, 0x92, 0x02, 0x00, 0x00, 0xc4, 0x14, - 0xb6, 0xcb, 0xc7, 0xca, 0xa7, 0x6a, 0x6a, 0x01, - 0x00, 0x00, 0x07, 0xc4, 0x04, 0xc7, 0xcd, 0xd3, - 0xc7, 0x92, 0xcb, 0x48, 0xd0, 0x11, 0x04, 0xd3, - 0x01, 0x00, 0x00, 0xaf, 0xed, 0x1c, 0x11, 0x04, - 0x93, 0x02, 0x00, 0x00, 0xaf, 0xed, 0x13, 0x11, - 0x04, 0x94, 0x02, 0x00, 0x00, 0xaf, 0xed, 0x0a, - 0x11, 0x04, 0x90, 0x01, 0x00, 0x00, 0xaf, 0xec, - 0x04, 0x0e, 0xee, 0xc7, 0x11, 0x04, 0x95, 0x02, - 0x00, 0x00, 0xaf, 0xed, 0x0a, 0x11, 0x04, 0xde, - 0x01, 0x00, 0x00, 0xaf, 0xec, 0x18, 0xc7, 0xca, - 0xa7, 0xec, 0x0d, 0xd3, 0xc7, 0x48, 0xc8, 0xad, - 0xec, 0x06, 0x94, 0x00, 0x0e, 0xee, 0xa4, 0xb7, - 0xc4, 0x08, 0x0e, 0xee, 0x9e, 0x11, 0x04, 0xb6, - 0x01, 0x00, 0x00, 0xaf, 0xec, 0x44, 0xc7, 0xca, - 0xa7, 0xec, 0x13, 0xd3, 0xc7, 0x48, 0x04, 0x7f, - 0x00, 0x00, 0x00, 0xad, 0xec, 0x08, 0xc3, 0x0d, - 0xf0, 0x0e, 0xef, 0xdc, 0x00, 0xc7, 0xca, 0xa7, - 0xec, 0x13, 0xd3, 0xc7, 0x48, 0x04, 0xb6, 0x01, - 0x00, 0x00, 0xad, 0xec, 0x08, 0xc3, 0x0e, 0xf0, - 0x0e, 0xef, 0xc5, 0x00, 0xc3, 0x08, 0xec, 0x0b, - 0xc3, 0x10, 0xf0, 0x0e, 0xb6, 0xc4, 0x08, 0xef, - 0xb7, 0x00, 0xb7, 0xc4, 0x08, 0x0e, 0xef, 0x53, - 0xff, 0x11, 0x04, 0xb2, 0x01, 0x00, 0x00, 0xaf, - 0xed, 0x13, 0x11, 0x04, 0xb3, 0x01, 0x00, 0x00, - 0xaf, 0xed, 0x0a, 0x11, 0x04, 0xb4, 0x01, 0x00, - 0x00, 0xaf, 0xec, 0x0c, 0xc3, 0x0f, 0xc8, 0xf1, - 0x0e, 0xb6, 0xc4, 0x08, 0xef, 0x8a, 0x00, 0x11, - 0x04, 0xca, 0x01, 0x00, 0x00, 0xaf, 0xed, 0x13, - 0x11, 0x04, 0xd8, 0x01, 0x00, 0x00, 0xaf, 0xed, - 0x0a, 0x11, 0x04, 0x1c, 0x02, 0x00, 0x00, 0xaf, - 0xec, 0x0f, 0xb7, 0xc4, 0x08, 0x94, 0x06, 0xc3, - 0x0a, 0xc8, 0xf1, 0x0e, 0x0e, 0xef, 0x04, 0xff, - 0x11, 0x04, 0xcb, 0x01, 0x00, 0x00, 0xaf, 0xed, - 0x13, 0x11, 0x04, 0xb5, 0x01, 0x00, 0x00, 0xaf, - 0xed, 0x0a, 0x11, 0x04, 0x1d, 0x02, 0x00, 0x00, - 0xaf, 0xec, 0x25, 0xb6, 0xc4, 0x08, 0xc3, 0x06, - 0xb6, 0xa9, 0xec, 0x13, 0xe0, 0xc3, 0x0b, 0xf0, - 0xc8, 0xf2, 0xec, 0x0b, 0x93, 0x06, 0xc3, 0x0c, - 0xf0, 0x0e, 0x0e, 0xef, 0xce, 0xfe, 0x04, 0x6f, - 0x02, 0x00, 0x00, 0xc4, 0x04, 0xee, 0x21, 0xe1, - 0xc8, 0xf1, 0xec, 0x0a, 0xc3, 0x11, 0xf0, 0x0e, - 0xb6, 0xc4, 0x08, 0xee, 0x13, 0xdf, 0xc8, 0xf1, - 0xec, 0x07, 0xc3, 0x15, 0xf0, 0x0e, 0xee, 0x08, - 0xb7, 0xc4, 0x08, 0x0e, 0xef, 0xa5, 0xfe, 0x0e, - 0xc3, 0x04, 0x6a, 0x9f, 0xfe, 0xff, 0xff, 0xc3, - 0x16, 0xc9, 0xc7, 0xf2, 0x0e, 0xef, 0x94, 0xfe, - 0xc3, 0x16, 0xca, 0xca, 0xf2, 0x0e, 0xc3, 0x05, - 0xc3, 0x06, 0xc3, 0x09, 0x26, 0x03, 0x00, 0x28, - 0x0c, 0x43, 0x02, 0x01, 0xc8, 0x05, 0x01, 0x00, - 0x01, 0x03, 0x01, 0x00, 0x36, 0x01, 0xce, 0x06, - 0x00, 0x01, 0x00, 0xce, 0x03, 0x00, 0x0c, 0x66, - 0x00, 0x00, 0x43, 0x96, 0x02, 0x00, 0x00, 0x04, - 0x97, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x11, - 0xed, 0x1b, 0x0e, 0x66, 0x00, 0x00, 0x43, 0x96, - 0x02, 0x00, 0x00, 0x04, 0x98, 0x02, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x11, 0xed, 0x07, 0x0e, 0x04, - 0xaf, 0x01, 0x00, 0x00, 0x04, 0xb6, 0x01, 0x00, - 0x00, 0x9e, 0xd3, 0x9e, 0x28, 0x0c, 0x43, 0x02, - 0x01, 0xca, 0x05, 0x00, 0x03, 0x00, 0x05, 0x03, - 0x00, 0x67, 0x03, 0xce, 0x06, 0x00, 0x00, 0x00, - 0xb2, 0x0a, 0x00, 0x01, 0x00, 0xc2, 0x09, 0x05, - 0x00, 0x03, 0xf2, 0x03, 0x1b, 0x01, 0xce, 0x03, - 0x00, 0x0c, 0xc8, 0x05, 0x86, 0x01, 0x01, 0xdf, - 0x43, 0xaa, 0x01, 0x00, 0x00, 0xbf, 0x18, 0xfc, - 0x24, 0x01, 0x00, 0x43, 0x5c, 0x00, 0x00, 0x00, - 0x04, 0x90, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x43, 0x46, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, - 0xcf, 0xec, 0x43, 0x6d, 0x38, 0x00, 0x00, 0x00, - 0x66, 0x01, 0x00, 0x43, 0x9a, 0x02, 0x00, 0x00, - 0xe1, 0x04, 0x9b, 0x02, 0x00, 0x00, 0xf1, 0x04, - 0x34, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xd0, - 0x43, 0x89, 0x01, 0x00, 0x00, 0xc7, 0x04, 0x90, - 0x01, 0x00, 0x00, 0x9e, 0x24, 0x01, 0x00, 0x0e, - 0xc8, 0x43, 0x9c, 0x02, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x0e, 0x0e, 0x29, 0xcd, 0x6d, 0x06, 0x00, - 0x00, 0x00, 0x0e, 0x29, 0x30, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xcc, 0x05, 0x00, 0x01, 0x00, 0x04, - 0x04, 0x00, 0x2f, 0x01, 0xee, 0x05, 0x00, 0x00, - 0x00, 0xce, 0x03, 0x00, 0x0c, 0xc8, 0x05, 0x86, - 0x01, 0x01, 0xf2, 0x03, 0x1b, 0x01, 0xf4, 0x03, - 0x1c, 0x01, 0x66, 0x00, 0x00, 0x43, 0x9d, 0x02, - 0x00, 0x00, 0xe0, 0x04, 0x9b, 0x02, 0x00, 0x00, - 0xf1, 0x24, 0x01, 0x00, 0xcf, 0xec, 0x1a, 0xc7, - 0x43, 0x46, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x43, 0x5e, 0x00, 0x00, 0x00, 0x04, 0x90, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0xe9, 0xeb, 0xe6, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0xce, 0x05, 0x00, - 0x02, 0x00, 0x04, 0x04, 0x02, 0x51, 0x02, 0x92, - 0x07, 0x00, 0x00, 0x00, 0xce, 0x06, 0x00, 0x01, - 0x00, 0xce, 0x03, 0x00, 0x0c, 0xe2, 0x03, 0x13, - 0x01, 0xe0, 0x03, 0x12, 0x01, 0xe8, 0x03, 0x16, - 0x01, 0x07, 0x16, 0x28, 0x5c, 0x64, 0x2b, 0x29, - 0x3b, 0x28, 0x5c, 0x64, 0x2b, 0x29, 0x07, 0xa8, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x00, - 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, - 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x0c, 0x01, - 0x1d, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, - 0x00, 0x16, 0x01, 0x00, 0x30, 0x00, 0x39, 0x00, - 0x0b, 0x0d, 0x01, 0x01, 0x3b, 0x0c, 0x02, 0x1d, - 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, - 0x16, 0x01, 0x00, 0x30, 0x00, 0x39, 0x00, 0x0b, - 0x0d, 0x02, 0x0d, 0x00, 0x0b, 0x66, 0x00, 0x00, - 0x43, 0x96, 0x02, 0x00, 0x00, 0x04, 0x9e, 0x02, - 0x00, 0x00, 0x24, 0x01, 0x00, 0xd0, 0xec, 0x21, - 0xc8, 0x43, 0xb7, 0x01, 0x00, 0x00, 0xc0, 0x00, - 0xc0, 0x01, 0x34, 0x24, 0x01, 0x00, 0xcf, 0xec, - 0x10, 0xc7, 0xb8, 0x48, 0x8e, 0xb6, 0xb0, 0xec, - 0x08, 0xe1, 0x42, 0x5c, 0x02, 0x00, 0x00, 0xe4, - 0x66, 0x00, 0x00, 0x43, 0x96, 0x02, 0x00, 0x00, - 0x04, 0x9f, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, - 0xd0, 0xec, 0x0b, 0xc8, 0xb6, 0x48, 0x8e, 0xb6, - 0xb0, 0xec, 0x03, 0x09, 0xe6, 0x29, 0xc1, 0x00, - 0xc4, 0x34, 0xc1, 0x01, 0xc4, 0x35, 0xc1, 0x02, - 0xc4, 0x36, 0xc1, 0x03, 0xc4, 0x37, 0xc1, 0x04, - 0xc4, 0x38, 0xc1, 0x05, 0xc4, 0x39, 0xc1, 0x06, - 0xc4, 0x3a, 0xc1, 0x07, 0xc4, 0x3b, 0xc1, 0x08, - 0xc4, 0x3c, 0xc1, 0x09, 0xc4, 0x3d, 0xc1, 0x0a, - 0xc4, 0x3e, 0xc1, 0x0b, 0xc4, 0x3f, 0xc1, 0x0c, - 0xc4, 0x40, 0xc1, 0x0d, 0xc4, 0x41, 0xc1, 0x0e, - 0xc4, 0x42, 0xc1, 0x0f, 0xc4, 0x43, 0xc1, 0x10, - 0xc4, 0x44, 0xc1, 0x11, 0xc4, 0x45, 0xc1, 0x12, - 0xc4, 0x46, 0xc1, 0x13, 0xc4, 0x47, 0xc1, 0x14, - 0xc4, 0x48, 0xc1, 0x15, 0xc4, 0x49, 0xc1, 0x16, - 0xc4, 0x4a, 0xc1, 0x17, 0xc4, 0x4b, 0xc1, 0x18, - 0xc4, 0x4c, 0xc1, 0x19, 0xc4, 0x4d, 0xc1, 0x1a, - 0xc4, 0x4e, 0xc1, 0x1b, 0xc4, 0x4f, 0xc1, 0x1c, - 0xc4, 0x50, 0xc1, 0x1d, 0xc4, 0x51, 0xc1, 0x1e, - 0xc4, 0x52, 0xc1, 0x1f, 0xc4, 0x53, 0xc1, 0x20, - 0xc4, 0x54, 0xc1, 0x21, 0xc4, 0x55, 0xc1, 0x22, - 0xc4, 0x56, 0xc1, 0x23, 0xc4, 0x57, 0xc1, 0x24, - 0xc4, 0x58, 0xc1, 0x25, 0xc4, 0x59, 0xc1, 0x26, - 0xc4, 0x5a, 0xc1, 0x27, 0xc4, 0x5b, 0xc1, 0x28, - 0xc4, 0x5c, 0xc1, 0x29, 0xc4, 0x5d, 0xc1, 0x2a, - 0xc4, 0x5e, 0xc1, 0x2b, 0xc4, 0x5f, 0xc1, 0x2c, - 0xc4, 0x60, 0xc1, 0x2d, 0xc4, 0x61, 0xc1, 0x2e, - 0xc4, 0x62, 0xc1, 0x2f, 0xc4, 0x63, 0xc1, 0x30, - 0xc4, 0x64, 0xc1, 0x31, 0xc4, 0x65, 0xc1, 0x32, - 0xc4, 0x66, 0xc1, 0x33, 0xc4, 0x67, 0xc1, 0x34, - 0xc4, 0x68, 0xc1, 0x35, 0xc4, 0x69, 0xc1, 0x36, - 0xc4, 0x6b, 0xc1, 0x37, 0xc4, 0x6f, 0xc1, 0x38, - 0xc4, 0x70, 0xc1, 0x39, 0xc4, 0x71, 0xc1, 0x3a, - 0xc4, 0x72, 0xc1, 0x3b, 0xc4, 0x73, 0xc1, 0x3c, - 0xc4, 0x74, 0xc1, 0x3e, 0xc4, 0x76, 0xc1, 0x3f, - 0xc4, 0x77, 0xc1, 0x40, 0xc4, 0x78, 0xc1, 0x41, - 0xc4, 0x79, 0xc1, 0x42, 0xc4, 0x7a, 0xc1, 0x43, - 0xc4, 0x7b, 0xc1, 0x4f, 0xc4, 0x7d, 0xc1, 0x50, - 0xc4, 0x7e, 0xc1, 0x51, 0xc4, 0x7f, 0xc1, 0x52, - 0xc4, 0x80, 0xc1, 0x53, 0xc4, 0x81, 0xc1, 0x54, - 0xc4, 0x82, 0xc1, 0x55, 0xc4, 0x83, 0xc1, 0x56, - 0xc4, 0x84, 0xc1, 0x57, 0xc4, 0x85, 0xc1, 0x58, - 0xc4, 0x86, 0xc1, 0x59, 0xc4, 0x87, 0xc1, 0x5a, - 0xc4, 0x88, 0xc1, 0x5b, 0xc4, 0x89, 0xd3, 0x66, - 0x02, 0x00, 0x44, 0xe9, 0x00, 0x00, 0x00, 0xd3, - 0x66, 0x01, 0x00, 0x44, 0xe8, 0x00, 0x00, 0x00, - 0xd3, 0x66, 0x00, 0x00, 0x44, 0xe7, 0x00, 0x00, - 0x00, 0xd3, 0x42, 0x94, 0x00, 0x00, 0x00, 0xcb, - 0xd3, 0x42, 0x98, 0x00, 0x00, 0x00, 0xcc, 0xd3, - 0x42, 0x97, 0x00, 0x00, 0x00, 0xcd, 0xd3, 0x42, - 0x99, 0x00, 0x00, 0x00, 0xce, 0xd3, 0x42, 0xb2, - 0x00, 0x00, 0x00, 0xc4, 0x04, 0xd3, 0x42, 0xa7, - 0x00, 0x00, 0x00, 0xc4, 0x05, 0xd3, 0x42, 0x95, - 0x00, 0x00, 0x00, 0xc4, 0x06, 0xd3, 0x42, 0x9e, - 0x00, 0x00, 0x00, 0xc4, 0x07, 0xd3, 0x42, 0xa2, - 0x00, 0x00, 0x00, 0xc4, 0x08, 0xd3, 0x42, 0x96, - 0x00, 0x00, 0x00, 0xc4, 0x09, 0xd3, 0x42, 0x9a, - 0x00, 0x00, 0x00, 0xc4, 0x0a, 0xd3, 0x42, 0x9c, - 0x00, 0x00, 0x00, 0xc4, 0x0b, 0xd3, 0x42, 0x9d, - 0x00, 0x00, 0x00, 0xc4, 0x0c, 0xd3, 0x42, 0xeb, - 0x00, 0x00, 0x00, 0xc4, 0x0d, 0xd3, 0x42, 0xec, - 0x00, 0x00, 0x00, 0xc4, 0x0e, 0xd3, 0x42, 0xed, - 0x00, 0x00, 0x00, 0xc4, 0x0f, 0xd3, 0x42, 0xee, - 0x00, 0x00, 0x00, 0xc4, 0x10, 0x0b, 0x04, 0xa0, - 0x02, 0x00, 0x00, 0x4d, 0x8a, 0x01, 0x00, 0x00, - 0x04, 0xa1, 0x02, 0x00, 0x00, 0x4d, 0xa2, 0x02, - 0x00, 0x00, 0x04, 0xa3, 0x02, 0x00, 0x00, 0x4d, - 0xa4, 0x02, 0x00, 0x00, 0x04, 0xa5, 0x02, 0x00, - 0x00, 0x4d, 0xa6, 0x02, 0x00, 0x00, 0x04, 0xa7, - 0x02, 0x00, 0x00, 0x4d, 0xa8, 0x02, 0x00, 0x00, - 0x04, 0xa9, 0x02, 0x00, 0x00, 0x4d, 0xaa, 0x02, - 0x00, 0x00, 0x04, 0xab, 0x02, 0x00, 0x00, 0x4d, - 0xac, 0x02, 0x00, 0x00, 0x04, 0xad, 0x02, 0x00, - 0x00, 0x4d, 0xae, 0x02, 0x00, 0x00, 0x04, 0xaf, - 0x02, 0x00, 0x00, 0x4d, 0xb0, 0x02, 0x00, 0x00, - 0x04, 0xb1, 0x02, 0x00, 0x00, 0x4d, 0xb2, 0x02, - 0x00, 0x00, 0x04, 0xb1, 0x02, 0x00, 0x00, 0x4d, - 0xb3, 0x02, 0x00, 0x00, 0x04, 0xb4, 0x02, 0x00, - 0x00, 0x4d, 0xb5, 0x02, 0x00, 0x00, 0x04, 0xb6, - 0x02, 0x00, 0x00, 0x4d, 0xb7, 0x02, 0x00, 0x00, - 0x04, 0xb8, 0x02, 0x00, 0x00, 0x4d, 0xb9, 0x02, - 0x00, 0x00, 0x04, 0xba, 0x02, 0x00, 0x00, 0x4d, - 0xbb, 0x02, 0x00, 0x00, 0x04, 0xbc, 0x02, 0x00, - 0x00, 0x4d, 0xbd, 0x02, 0x00, 0x00, 0x04, 0xbe, - 0x02, 0x00, 0x00, 0x4d, 0xbf, 0x02, 0x00, 0x00, - 0x04, 0xc0, 0x02, 0x00, 0x00, 0x4d, 0xc1, 0x02, - 0x00, 0x00, 0xc4, 0x11, 0x0b, 0x0b, 0x04, 0xae, - 0x02, 0x00, 0x00, 0x4d, 0x2e, 0x02, 0x00, 0x00, - 0x04, 0xc1, 0x02, 0x00, 0x00, 0x4d, 0x48, 0x00, - 0x00, 0x00, 0x04, 0xb0, 0x02, 0x00, 0x00, 0x4d, - 0x82, 0x02, 0x00, 0x00, 0x04, 0xac, 0x02, 0x00, - 0x00, 0x4d, 0x31, 0x02, 0x00, 0x00, 0x04, 0xb7, - 0x02, 0x00, 0x00, 0x4d, 0x16, 0x00, 0x00, 0x00, - 0x04, 0xb5, 0x02, 0x00, 0x00, 0x4d, 0x6f, 0x02, - 0x00, 0x00, 0x04, 0xb9, 0x02, 0x00, 0x00, 0x4d, - 0x1b, 0x00, 0x00, 0x00, 0x04, 0xb7, 0x02, 0x00, - 0x00, 0x4d, 0x86, 0x02, 0x00, 0x00, 0x04, 0xc1, - 0x02, 0x00, 0x00, 0x4d, 0x33, 0x02, 0x00, 0x00, - 0x04, 0xc1, 0x02, 0x00, 0x00, 0x4d, 0x01, 0x00, - 0x00, 0x00, 0x04, 0xa6, 0x02, 0x00, 0x00, 0x4d, - 0x47, 0x00, 0x00, 0x00, 0x04, 0xb0, 0x02, 0x00, - 0x00, 0x4d, 0x30, 0x02, 0x00, 0x00, 0x04, 0xb0, - 0x02, 0x00, 0x00, 0x4d, 0x2b, 0x02, 0x00, 0x00, - 0x04, 0xae, 0x02, 0x00, 0x00, 0x4d, 0x2d, 0x02, - 0x00, 0x00, 0x04, 0xbf, 0x02, 0x00, 0x00, 0x4d, - 0x49, 0x00, 0x00, 0x00, 0x04, 0xc1, 0x02, 0x00, - 0x00, 0x4d, 0x4b, 0x00, 0x00, 0x00, 0x04, 0xbd, - 0x02, 0x00, 0x00, 0x4d, 0x04, 0x02, 0x00, 0x00, - 0x04, 0xc1, 0x02, 0x00, 0x00, 0x4d, 0x46, 0x00, - 0x00, 0x00, 0x4d, 0x59, 0x02, 0x00, 0x00, 0x0b, - 0x04, 0xae, 0x02, 0x00, 0x00, 0x4d, 0x2e, 0x02, - 0x00, 0x00, 0x04, 0xbd, 0x02, 0x00, 0x00, 0x4d, - 0x48, 0x00, 0x00, 0x00, 0x04, 0xb3, 0x02, 0x00, - 0x00, 0x4d, 0x82, 0x02, 0x00, 0x00, 0x04, 0xac, - 0x02, 0x00, 0x00, 0x4d, 0x31, 0x02, 0x00, 0x00, - 0x04, 0xa2, 0x02, 0x00, 0x00, 0x4d, 0x16, 0x00, - 0x00, 0x00, 0x04, 0xa4, 0x02, 0x00, 0x00, 0x4d, - 0x6f, 0x02, 0x00, 0x00, 0x04, 0xb9, 0x02, 0x00, - 0x00, 0x4d, 0x1b, 0x00, 0x00, 0x00, 0x04, 0xa2, - 0x02, 0x00, 0x00, 0x4d, 0x86, 0x02, 0x00, 0x00, - 0x04, 0xbd, 0x02, 0x00, 0x00, 0x4d, 0x33, 0x02, - 0x00, 0x00, 0x04, 0xbd, 0x02, 0x00, 0x00, 0x4d, - 0x01, 0x00, 0x00, 0x00, 0x04, 0xa6, 0x02, 0x00, - 0x00, 0x4d, 0x47, 0x00, 0x00, 0x00, 0x04, 0xa2, - 0x02, 0x00, 0x00, 0x4d, 0x30, 0x02, 0x00, 0x00, - 0x04, 0xa2, 0x02, 0x00, 0x00, 0x4d, 0x2b, 0x02, - 0x00, 0x00, 0x04, 0xae, 0x02, 0x00, 0x00, 0x4d, - 0x2d, 0x02, 0x00, 0x00, 0x04, 0xbf, 0x02, 0x00, - 0x00, 0x4d, 0x49, 0x00, 0x00, 0x00, 0x04, 0xb3, - 0x02, 0x00, 0x00, 0x4d, 0x4b, 0x00, 0x00, 0x00, - 0x04, 0xbd, 0x02, 0x00, 0x00, 0x4d, 0x04, 0x02, - 0x00, 0x00, 0x04, 0xbd, 0x02, 0x00, 0x00, 0x4d, - 0x46, 0x00, 0x00, 0x00, 0x4d, 0x5c, 0x02, 0x00, - 0x00, 0xc5, 0x12, 0x42, 0x59, 0x02, 0x00, 0x00, - 0xc4, 0x13, 0x0a, 0xc4, 0x14, 0x09, 0xc4, 0x15, - 0x0a, 0xc4, 0x16, 0x09, 0xc4, 0x17, 0xb8, 0xc4, - 0x18, 0x09, 0xc4, 0x19, 0x09, 0xc4, 0x1a, 0x26, - 0x00, 0x00, 0xc4, 0x1b, 0xc2, 0xc4, 0x1d, 0xc2, - 0xc4, 0x1e, 0xc2, 0xc4, 0x1f, 0xb6, 0xc4, 0x20, - 0x04, 0xc2, 0x02, 0x00, 0x00, 0xc4, 0x21, 0x04, - 0xc3, 0x02, 0x00, 0x00, 0xc4, 0x22, 0xb6, 0xc4, - 0x24, 0xc2, 0xc4, 0x25, 0xb6, 0xc4, 0x26, 0xc2, - 0xc4, 0x27, 0xb6, 0xc4, 0x28, 0xc2, 0xc4, 0x29, - 0xb6, 0xc4, 0x2a, 0x09, 0xc4, 0x2d, 0xb6, 0xc4, - 0x2e, 0xb6, 0xc4, 0x2f, 0xb6, 0xc4, 0x33, 0x0b, - 0xc3, 0x46, 0x4d, 0xc4, 0x02, 0x00, 0x00, 0xc3, - 0x49, 0x4d, 0xc5, 0x02, 0x00, 0x00, 0xc3, 0x64, - 0x4d, 0xc6, 0x02, 0x00, 0x00, 0xc3, 0x58, 0x4d, - 0xc7, 0x02, 0x00, 0x00, 0xc3, 0x47, 0x4d, 0xc8, - 0x02, 0x00, 0x00, 0xc3, 0x48, 0x4d, 0xc9, 0x02, - 0x00, 0x00, 0xc3, 0x44, 0x4d, 0xca, 0x02, 0x00, - 0x00, 0xc3, 0x59, 0x4d, 0xcb, 0x02, 0x00, 0x00, - 0xc3, 0x69, 0x4d, 0x93, 0x02, 0x00, 0x00, 0xc3, - 0x4f, 0x4d, 0x90, 0x01, 0x00, 0x00, 0xc3, 0x5f, - 0x4d, 0xcc, 0x02, 0x00, 0x00, 0xc3, 0x4e, 0x4d, - 0xcd, 0x02, 0x00, 0x00, 0xc3, 0x4f, 0x4d, 0x94, - 0x02, 0x00, 0x00, 0xc3, 0x52, 0x4d, 0xce, 0x02, - 0x00, 0x00, 0xc3, 0x51, 0x4d, 0xcf, 0x02, 0x00, - 0x00, 0xc3, 0x43, 0x4d, 0xd0, 0x02, 0x00, 0x00, - 0xc3, 0x45, 0x4d, 0xd1, 0x02, 0x00, 0x00, 0xc3, - 0x45, 0x4d, 0xd2, 0x02, 0x00, 0x00, 0xc3, 0x5a, - 0x4d, 0xd3, 0x02, 0x00, 0x00, 0xc3, 0x62, 0x4d, - 0xd4, 0x02, 0x00, 0x00, 0xc3, 0x65, 0x4d, 0xd5, - 0x02, 0x00, 0x00, 0xc3, 0x63, 0x4d, 0xd6, 0x02, - 0x00, 0x00, 0xc3, 0x51, 0x4d, 0xd7, 0x02, 0x00, - 0x00, 0xc3, 0x52, 0x4d, 0xd8, 0x02, 0x00, 0x00, - 0xc3, 0x48, 0x4d, 0xd9, 0x02, 0x00, 0x00, 0xc3, - 0x49, 0x4d, 0xda, 0x02, 0x00, 0x00, 0xc3, 0x4c, - 0x4d, 0xdb, 0x02, 0x00, 0x00, 0xc3, 0x4d, 0x4d, - 0xdc, 0x02, 0x00, 0x00, 0xc3, 0x4c, 0x4d, 0xdd, - 0x02, 0x00, 0x00, 0xc3, 0x4d, 0x4d, 0xde, 0x02, - 0x00, 0x00, 0xc3, 0x46, 0x4d, 0xdf, 0x02, 0x00, - 0x00, 0xc3, 0x57, 0x4d, 0xe0, 0x02, 0x00, 0x00, - 0xc3, 0x47, 0x4d, 0xe1, 0x02, 0x00, 0x00, 0xc3, - 0x54, 0x4d, 0xe2, 0x02, 0x00, 0x00, 0xc3, 0x55, - 0x4d, 0xe3, 0x02, 0x00, 0x00, 0xc3, 0x51, 0x4d, - 0xe4, 0x02, 0x00, 0x00, 0xc3, 0x52, 0x4d, 0xe5, - 0x02, 0x00, 0x00, 0xc3, 0x48, 0x4d, 0xe6, 0x02, - 0x00, 0x00, 0xc3, 0x49, 0x4d, 0xe7, 0x02, 0x00, - 0x00, 0xc3, 0x47, 0x4d, 0xe8, 0x02, 0x00, 0x00, - 0xc3, 0x46, 0x4d, 0xe9, 0x02, 0x00, 0x00, 0xc3, - 0x62, 0x4d, 0xea, 0x02, 0x00, 0x00, 0xc3, 0x4d, - 0x4d, 0xeb, 0x02, 0x00, 0x00, 0xc3, 0x61, 0x4d, - 0xec, 0x02, 0x00, 0x00, 0xc3, 0x4c, 0x4d, 0xed, - 0x02, 0x00, 0x00, 0xc3, 0x60, 0x4d, 0xee, 0x02, - 0x00, 0x00, 0xc3, 0x5d, 0x4d, 0xef, 0x02, 0x00, - 0x00, 0xc3, 0x5b, 0x4d, 0xf0, 0x02, 0x00, 0x00, - 0xc3, 0x5c, 0x4d, 0xf1, 0x02, 0x00, 0x00, 0xc3, - 0x59, 0x4d, 0xf2, 0x02, 0x00, 0x00, 0xc4, 0x6a, - 0x0b, 0xc5, 0x75, 0xc1, 0x3d, 0x44, 0x42, 0x02, - 0x00, 0x00, 0xc7, 0x43, 0x61, 0x00, 0x00, 0x00, - 0x0b, 0xc3, 0x78, 0x4d, 0x56, 0x01, 0x00, 0x00, - 0xc3, 0x79, 0x4d, 0x57, 0x01, 0x00, 0x00, 0xc1, - 0x44, 0x4e, 0xf3, 0x02, 0x00, 0x00, 0x4d, 0xf3, - 0x02, 0x00, 0x00, 0xc1, 0x45, 0x4e, 0xf4, 0x02, - 0x00, 0x00, 0x4d, 0xf4, 0x02, 0x00, 0x00, 0xc1, - 0x46, 0x4e, 0xf5, 0x02, 0x00, 0x00, 0x4d, 0xf5, - 0x02, 0x00, 0x00, 0xc1, 0x47, 0x4e, 0xf6, 0x02, - 0x00, 0x00, 0x4d, 0xf6, 0x02, 0x00, 0x00, 0xc1, - 0x48, 0x4e, 0x41, 0x02, 0x00, 0x00, 0x4d, 0x41, - 0x02, 0x00, 0x00, 0xc1, 0x49, 0x4e, 0xf7, 0x02, - 0x00, 0x00, 0x4d, 0xf7, 0x02, 0x00, 0x00, 0xc1, - 0x4a, 0x4e, 0x2a, 0x02, 0x00, 0x00, 0x4d, 0x2a, - 0x02, 0x00, 0x00, 0xc1, 0x4b, 0x4e, 0x59, 0x02, - 0x00, 0x00, 0x4d, 0x59, 0x02, 0x00, 0x00, 0xc1, - 0x4c, 0x4e, 0x5c, 0x02, 0x00, 0x00, 0x4d, 0x5c, - 0x02, 0x00, 0x00, 0xc1, 0x4d, 0x4e, 0x9c, 0x01, - 0x00, 0x00, 0x4d, 0x9c, 0x01, 0x00, 0x00, 0xc1, - 0x4e, 0x4e, 0xf8, 0x02, 0x00, 0x00, 0x4d, 0xf8, - 0x02, 0x00, 0x00, 0x07, 0x24, 0x02, 0x00, 0xc4, - 0x7c, 0xc3, 0x89, 0xf0, 0x0e, 0xc3, 0x88, 0xf0, - 0x0e, 0xc3, 0x34, 0xf0, 0x0e, 0xc3, 0x7d, 0xf0, - 0x29, 0x08, 0xec, 0x02, 0x29, 0xc1, 0x00, 0x39, - 0x8d, 0x00, 0x00, 0x00, 0xf1, 0x0e, 0x06, 0x2f, -}; - diff --git a/quickjs-ng/gen/standalone.c b/quickjs-ng/gen/standalone.c deleted file mode 100644 index 53aacca..0000000 --- a/quickjs-ng/gen/standalone.c +++ /dev/null @@ -1,323 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include - -const uint32_t qjsc_standalone_size = 2511; - -const uint8_t qjsc_standalone[2511] = { - 0x15, 0x4e, 0x01, 0x1a, 0x73, 0x74, 0x61, 0x6e, - 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x6a, - 0x73, 0x01, 0x0e, 0x71, 0x6a, 0x73, 0x3a, 0x73, - 0x74, 0x64, 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, - 0x6f, 0x73, 0x01, 0x12, 0x71, 0x6a, 0x73, 0x3a, - 0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01, 0x22, 0x63, - 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x53, 0x74, - 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, - 0x01, 0x1a, 0x72, 0x75, 0x6e, 0x53, 0x74, 0x61, - 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x01, - 0x06, 0x73, 0x74, 0x64, 0x01, 0x04, 0x6f, 0x73, - 0x01, 0x0a, 0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01, - 0x28, 0x4a, 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, - 0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54, - 0x45, 0x43, 0x4f, 0x44, 0x45, 0x01, 0x2a, 0x4a, - 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, - 0x42, 0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52, - 0x45, 0x4e, 0x43, 0x45, 0x01, 0x2a, 0x4a, 0x53, - 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, - 0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x43, - 0x4f, 0x44, 0x45, 0x01, 0x2c, 0x4a, 0x53, 0x5f, - 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42, - 0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, - 0x4e, 0x43, 0x45, 0x01, 0x32, 0x4a, 0x53, 0x5f, - 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42, - 0x4a, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x01, 0x0e, - 0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x01, - 0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x41, - 0x73, 0x63, 0x69, 0x69, 0x01, 0x16, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x41, 0x73, 0x63, 0x69, - 0x69, 0x01, 0x06, 0x74, 0x78, 0x74, 0x01, 0x02, - 0x63, 0x01, 0x14, 0x63, 0x68, 0x61, 0x72, 0x43, - 0x6f, 0x64, 0x65, 0x41, 0x74, 0x01, 0x06, 0x6d, - 0x61, 0x70, 0x01, 0x06, 0x62, 0x75, 0x66, 0x01, - 0x18, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x01, 0x0c, 0x69, - 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x0e, 0x6f, - 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x12, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x45, 0x78, - 0x65, 0x01, 0x04, 0x6a, 0x73, 0x01, 0x08, 0x63, - 0x6f, 0x64, 0x65, 0x01, 0x10, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x01, 0x16, 0x65, - 0x78, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x01, 0x06, 0x65, 0x78, 0x65, 0x01, - 0x0e, 0x65, 0x78, 0x65, 0x53, 0x69, 0x7a, 0x65, - 0x01, 0x12, 0x6e, 0x65, 0x77, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x01, 0x0c, 0x6e, 0x65, 0x77, - 0x45, 0x78, 0x65, 0x01, 0x04, 0x64, 0x77, 0x01, - 0x0a, 0x6e, 0x65, 0x77, 0x46, 0x64, 0x01, 0x10, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, - 0x01, 0x1e, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e, - 0x20, 0x01, 0x14, 0x65, 0x76, 0x61, 0x6c, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x01, 0x18, 0x63, - 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6f, - 0x6e, 0x6c, 0x79, 0x01, 0x1c, 0x63, 0x6f, 0x6d, - 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, - 0x75, 0x6c, 0x65, 0x01, 0x0a, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x01, 0x0e, 0x65, 0x78, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x01, 0x0a, 0x61, 0x72, 0x67, - 0x76, 0x30, 0x01, 0x0c, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x01, 0x36, 0x66, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70, - 0x65, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x20, 0x01, - 0x0c, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x01, - 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, - 0x72, 0x01, 0x08, 0x53, 0x69, 0x7a, 0x65, 0x01, - 0x0a, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x01, 0x12, - 0x4d, 0x61, 0x67, 0x69, 0x63, 0x53, 0x69, 0x7a, - 0x65, 0x01, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x69, 0x7a, 0x65, 0x01, 0x12, 0x73, 0x65, 0x74, - 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x01, 0x08, - 0x6f, 0x70, 0x65, 0x6e, 0x01, 0x10, 0x4f, 0x5f, - 0x57, 0x52, 0x4f, 0x4e, 0x4c, 0x59, 0x01, 0x0e, - 0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x01, - 0x0e, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, - 0x01, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x20, 0x01, 0x14, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x01, - 0x0a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x01, 0x3c, - 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x01, 0x08, - 0x66, 0x69, 0x6c, 0x65, 0x01, 0x02, 0x72, 0x01, - 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, - 0x01, 0x0a, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x01, - 0x0c, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x01, - 0x04, 0x72, 0x62, 0x01, 0x08, 0x73, 0x65, 0x65, - 0x6b, 0x01, 0x10, 0x53, 0x45, 0x45, 0x4b, 0x5f, - 0x45, 0x4e, 0x44, 0x01, 0x18, 0x73, 0x65, 0x65, - 0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, - 0x20, 0x01, 0x08, 0x72, 0x65, 0x61, 0x64, 0x01, - 0x40, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x2c, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63, - 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x01, 0x12, 0x67, 0x65, 0x74, 0x55, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x01, 0x10, 0x53, 0x45, - 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x01, 0x0a, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x01, 0x14, 0x72, - 0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x01, 0x16, 0x65, 0x76, 0x61, 0x6c, 0x5f, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x01, 0x10, - 0x71, 0x75, 0x69, 0x63, 0x6b, 0x6a, 0x73, 0x32, - 0x0d, 0xc6, 0x03, 0x03, 0xc8, 0x03, 0xca, 0x03, - 0xcc, 0x03, 0x02, 0x00, 0x0b, 0xce, 0x03, 0x00, - 0x0c, 0xd0, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x01, - 0x00, 0x01, 0xfe, 0x01, 0x01, 0x02, 0xfe, 0x01, - 0x02, 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa2, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x0d, 0x04, 0x58, 0x00, - 0xd2, 0x03, 0x00, 0x0d, 0xd4, 0x03, 0x01, 0x0d, - 0xd6, 0x03, 0x02, 0x0d, 0xd8, 0x03, 0x00, 0x0d, - 0xda, 0x03, 0x01, 0x0d, 0xdc, 0x03, 0x02, 0x0d, - 0xde, 0x03, 0x03, 0x0d, 0xe0, 0x03, 0x04, 0x0d, - 0xe2, 0x03, 0x05, 0x0d, 0xe4, 0x03, 0x06, 0x01, - 0xe6, 0x03, 0x07, 0x01, 0xce, 0x03, 0x08, 0x01, - 0xd0, 0x03, 0x09, 0x01, 0x0c, 0x43, 0x02, 0x01, - 0xe4, 0x03, 0x01, 0x00, 0x01, 0x05, 0x00, 0x01, - 0x1e, 0x01, 0xe8, 0x03, 0x00, 0x01, 0x00, 0x0c, - 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, - 0x00, 0x00, 0x0a, 0x01, 0xea, 0x03, 0x00, 0x01, - 0x00, 0xd3, 0x43, 0xf6, 0x00, 0x00, 0x00, 0xb6, - 0x25, 0x01, 0x00, 0x39, 0xa7, 0x00, 0x00, 0x00, - 0x11, 0xd3, 0x43, 0x5e, 0x00, 0x00, 0x00, 0xc2, - 0x24, 0x01, 0x00, 0x43, 0xf7, 0x00, 0x00, 0x00, - 0xc1, 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xe6, 0x03, 0x01, - 0x00, 0x01, 0x03, 0x00, 0x01, 0x21, 0x01, 0xf0, - 0x03, 0x00, 0x01, 0x00, 0x0c, 0x42, 0x02, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x0e, - 0x01, 0xea, 0x03, 0x00, 0x01, 0x00, 0x39, 0x98, - 0x00, 0x00, 0x00, 0x43, 0xf9, 0x00, 0x00, 0x00, - 0xd3, 0x25, 0x01, 0x00, 0x39, 0x95, 0x00, 0x00, - 0x00, 0x43, 0x7b, 0x00, 0x00, 0x00, 0xd3, 0x24, - 0x01, 0x00, 0x43, 0xf7, 0x00, 0x00, 0x00, 0xc1, - 0x00, 0x24, 0x01, 0x00, 0x43, 0x5c, 0x00, 0x00, - 0x00, 0xc2, 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02, - 0x01, 0xce, 0x03, 0x03, 0x0a, 0x03, 0x07, 0x08, - 0x00, 0x96, 0x04, 0x0d, 0xf4, 0x03, 0x00, 0x01, - 0x00, 0xf6, 0x03, 0x00, 0x01, 0x00, 0xf8, 0x03, - 0x00, 0x01, 0x00, 0xfa, 0x03, 0x01, 0x00, 0x30, - 0xfc, 0x03, 0x01, 0x01, 0x30, 0xfe, 0x03, 0x01, - 0x02, 0x30, 0x80, 0x04, 0x01, 0x03, 0x30, 0x82, - 0x04, 0x01, 0x04, 0x30, 0x84, 0x04, 0x01, 0x05, - 0x30, 0x86, 0x04, 0x01, 0x06, 0x30, 0x88, 0x04, - 0x01, 0x07, 0x30, 0x8a, 0x04, 0x01, 0x08, 0x30, - 0x8c, 0x04, 0x01, 0x09, 0x30, 0xd2, 0x03, 0x00, - 0x0c, 0xd6, 0x03, 0x02, 0x0c, 0xdc, 0x03, 0x05, - 0x0c, 0xde, 0x03, 0x06, 0x0c, 0xe0, 0x03, 0x07, - 0x0c, 0xd4, 0x03, 0x01, 0x0c, 0xe2, 0x03, 0x08, - 0x0c, 0xe4, 0x03, 0x09, 0x00, 0x62, 0x09, 0x00, - 0x62, 0x08, 0x00, 0x62, 0x07, 0x00, 0x62, 0x06, - 0x00, 0x62, 0x05, 0x00, 0x62, 0x04, 0x00, 0x62, - 0x03, 0x00, 0x62, 0x02, 0x00, 0x62, 0x01, 0x00, - 0x62, 0x00, 0x00, 0x66, 0x00, 0x00, 0x43, 0x07, - 0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0xcb, - 0x63, 0x00, 0x00, 0x97, 0xec, 0x19, 0x39, 0x96, - 0x00, 0x00, 0x00, 0x11, 0x04, 0x08, 0x01, 0x00, - 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xd3, 0x24, - 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x66, 0x00, - 0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x0b, 0x0a, 0x4d, 0x0a, 0x01, 0x00, 0x00, - 0x0a, 0x4d, 0x0b, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xcc, 0x39, 0xa7, 0x00, 0x00, 0x00, 0x11, - 0x66, 0x01, 0x00, 0x43, 0x0c, 0x01, 0x00, 0x00, - 0x63, 0x01, 0x00, 0x66, 0x02, 0x00, 0x66, 0x03, - 0x00, 0xa5, 0x66, 0x04, 0x00, 0xa5, 0x24, 0x02, - 0x00, 0x21, 0x01, 0x00, 0xcd, 0xd5, 0x11, 0xb1, - 0xec, 0x1c, 0x0e, 0x66, 0x05, 0x00, 0x43, 0x0d, - 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x11, 0xb1, - 0xec, 0x0c, 0x0e, 0x39, 0x8d, 0x00, 0x00, 0x00, - 0x42, 0x0e, 0x01, 0x00, 0x00, 0xce, 0x66, 0x00, - 0x00, 0x43, 0x07, 0x01, 0x00, 0x00, 0x63, 0x03, - 0x00, 0x0b, 0x0a, 0x4d, 0x0f, 0x01, 0x00, 0x00, - 0x24, 0x02, 0x00, 0xc4, 0x04, 0x63, 0x04, 0x00, - 0x97, 0xec, 0x1b, 0x39, 0x96, 0x00, 0x00, 0x00, - 0x11, 0x04, 0x10, 0x01, 0x00, 0x00, 0x43, 0x5d, - 0x00, 0x00, 0x00, 0x63, 0x03, 0x00, 0x24, 0x01, - 0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x04, 0x00, - 0xeb, 0xc4, 0x05, 0x63, 0x04, 0x00, 0x42, 0x11, - 0x01, 0x00, 0x00, 0x43, 0x12, 0x01, 0x00, 0x00, - 0x63, 0x05, 0x00, 0x63, 0x02, 0x00, 0xeb, 0x9e, - 0x66, 0x06, 0x00, 0x42, 0x13, 0x01, 0x00, 0x00, - 0x9e, 0x24, 0x01, 0x00, 0xc4, 0x06, 0x39, 0xa7, - 0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x21, - 0x01, 0x00, 0xc4, 0x07, 0x63, 0x07, 0x00, 0x43, - 0x43, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x63, - 0x05, 0x00, 0x24, 0x02, 0x00, 0x0e, 0x63, 0x07, - 0x00, 0x43, 0x43, 0x00, 0x00, 0x00, 0x5f, 0x07, - 0x00, 0x66, 0x06, 0x00, 0x42, 0x14, 0x01, 0x00, - 0x00, 0xf1, 0x63, 0x05, 0x00, 0x63, 0x02, 0x00, - 0xeb, 0x9e, 0x24, 0x02, 0x00, 0x0e, 0x39, 0xb1, - 0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x63, - 0x05, 0x00, 0x63, 0x02, 0x00, 0xeb, 0x9e, 0x66, - 0x06, 0x00, 0x42, 0x15, 0x01, 0x00, 0x00, 0x9e, - 0x66, 0x06, 0x00, 0x42, 0x16, 0x01, 0x00, 0x00, - 0x21, 0x03, 0x00, 0xc4, 0x08, 0x63, 0x08, 0x00, - 0x43, 0x17, 0x01, 0x00, 0x00, 0xb6, 0x63, 0x05, - 0x00, 0x0a, 0x24, 0x03, 0x00, 0x0e, 0x66, 0x05, - 0x00, 0x43, 0x18, 0x01, 0x00, 0x00, 0xd4, 0x66, - 0x05, 0x00, 0x42, 0x19, 0x01, 0x00, 0x00, 0x66, - 0x05, 0x00, 0x42, 0x1a, 0x01, 0x00, 0x00, 0xa5, - 0x66, 0x05, 0x00, 0x42, 0x1b, 0x01, 0x00, 0x00, - 0xa5, 0xbf, 0xed, 0x01, 0x24, 0x03, 0x00, 0xc4, - 0x09, 0x63, 0x09, 0x00, 0xb6, 0xa7, 0xec, 0x19, - 0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04, 0x1c, - 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, - 0xd4, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, - 0x66, 0x05, 0x00, 0x43, 0x0c, 0x01, 0x00, 0x00, - 0x63, 0x09, 0x00, 0x63, 0x06, 0x00, 0xb6, 0x63, - 0x06, 0x00, 0x42, 0x1d, 0x01, 0x00, 0x00, 0x24, - 0x04, 0x00, 0xb6, 0xa7, 0xec, 0x1f, 0x66, 0x05, - 0x00, 0x43, 0x1e, 0x01, 0x00, 0x00, 0x63, 0x09, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0x96, 0x00, - 0x00, 0x00, 0x11, 0x04, 0x1f, 0x01, 0x00, 0x00, - 0x21, 0x01, 0x00, 0x30, 0x66, 0x05, 0x00, 0x43, - 0x1e, 0x01, 0x00, 0x00, 0x63, 0x09, 0x00, 0x24, - 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xd0, - 0x03, 0x00, 0x09, 0x00, 0x07, 0x07, 0x00, 0xb4, - 0x04, 0x09, 0xc0, 0x04, 0x01, 0x00, 0x30, 0x82, - 0x04, 0x01, 0x01, 0x30, 0xc2, 0x04, 0x01, 0x02, - 0x20, 0xc4, 0x04, 0x01, 0x03, 0x30, 0xc6, 0x04, - 0x01, 0x04, 0x30, 0x8a, 0x04, 0x01, 0x05, 0x30, - 0xc8, 0x04, 0x01, 0x06, 0x30, 0xfe, 0x03, 0x01, - 0x07, 0x30, 0xfc, 0x03, 0x01, 0x08, 0x30, 0xd4, - 0x03, 0x01, 0x0c, 0xd2, 0x03, 0x00, 0x0c, 0xe2, - 0x03, 0x08, 0x0c, 0xe6, 0x03, 0x0a, 0x00, 0xd6, - 0x03, 0x02, 0x0c, 0xd8, 0x03, 0x03, 0x0c, 0xda, - 0x03, 0x04, 0x0c, 0x62, 0x08, 0x00, 0x62, 0x07, - 0x00, 0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62, - 0x04, 0x00, 0x62, 0x03, 0x00, 0x62, 0x02, 0x00, - 0x62, 0x01, 0x00, 0x62, 0x00, 0x00, 0x66, 0x00, - 0x00, 0x43, 0x0d, 0x01, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x11, 0xb1, 0xec, 0x0c, 0x0e, 0x39, 0x8d, - 0x00, 0x00, 0x00, 0x42, 0x0e, 0x01, 0x00, 0x00, - 0xcb, 0x66, 0x01, 0x00, 0x43, 0x18, 0x01, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x04, 0x25, 0x01, 0x00, - 0x00, 0x24, 0x02, 0x00, 0xcc, 0x63, 0x01, 0x00, - 0x97, 0xec, 0x1b, 0x39, 0x96, 0x00, 0x00, 0x00, - 0x11, 0x04, 0x10, 0x01, 0x00, 0x00, 0x43, 0x5d, - 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x24, 0x01, - 0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00, - 0x43, 0x26, 0x01, 0x00, 0x00, 0x66, 0x02, 0x00, - 0x42, 0x13, 0x01, 0x00, 0x00, 0x8d, 0x66, 0x01, - 0x00, 0x42, 0x27, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xcd, 0x63, 0x02, 0x00, 0xb6, 0xa7, 0xec, - 0x1c, 0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04, - 0x28, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0x63, 0x02, 0x00, 0x8d, 0x24, 0x01, 0x00, - 0x21, 0x01, 0x00, 0x30, 0x39, 0xa7, 0x00, 0x00, - 0x00, 0x11, 0x66, 0x02, 0x00, 0x42, 0x13, 0x01, - 0x00, 0x00, 0x21, 0x01, 0x00, 0xce, 0x63, 0x01, - 0x00, 0x43, 0x29, 0x01, 0x00, 0x00, 0x63, 0x03, - 0x00, 0x42, 0x11, 0x01, 0x00, 0x00, 0xb6, 0x66, - 0x02, 0x00, 0x42, 0x13, 0x01, 0x00, 0x00, 0x24, - 0x03, 0x00, 0x0e, 0x39, 0xa7, 0x00, 0x00, 0x00, - 0x11, 0x63, 0x03, 0x00, 0x42, 0x11, 0x01, 0x00, - 0x00, 0xb6, 0x66, 0x02, 0x00, 0x42, 0x15, 0x01, - 0x00, 0x00, 0x21, 0x03, 0x00, 0xc4, 0x04, 0xe2, - 0x63, 0x04, 0x00, 0xf1, 0x66, 0x02, 0x00, 0x42, - 0x14, 0x01, 0x00, 0x00, 0xb0, 0xec, 0x1c, 0x63, - 0x01, 0x00, 0x43, 0x1e, 0x01, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x0e, 0x39, 0x96, 0x00, 0x00, 0x00, - 0x11, 0x04, 0x2a, 0x01, 0x00, 0x00, 0x21, 0x01, - 0x00, 0x30, 0x39, 0xb1, 0x00, 0x00, 0x00, 0x11, - 0x63, 0x03, 0x00, 0x42, 0x11, 0x01, 0x00, 0x00, - 0x66, 0x02, 0x00, 0x42, 0x15, 0x01, 0x00, 0x00, - 0x66, 0x02, 0x00, 0x42, 0x16, 0x01, 0x00, 0x00, - 0x21, 0x03, 0x00, 0xc4, 0x05, 0x63, 0x05, 0x00, - 0x43, 0x2b, 0x01, 0x00, 0x00, 0xb6, 0x0a, 0x24, - 0x02, 0x00, 0xc4, 0x06, 0x39, 0xa7, 0x00, 0x00, - 0x00, 0x11, 0x63, 0x06, 0x00, 0x66, 0x02, 0x00, - 0x42, 0x13, 0x01, 0x00, 0x00, 0x9f, 0x21, 0x01, - 0x00, 0xc4, 0x07, 0x63, 0x01, 0x00, 0x43, 0x26, - 0x01, 0x00, 0x00, 0x63, 0x06, 0x00, 0x66, 0x01, - 0x00, 0x42, 0x2c, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0x11, 0x64, 0x02, 0x00, 0x0e, 0x63, 0x02, - 0x00, 0xb6, 0xa7, 0xec, 0x28, 0x63, 0x01, 0x00, - 0x43, 0x1e, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x0e, 0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04, - 0x28, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, - 0x00, 0x63, 0x02, 0x00, 0x8d, 0x24, 0x01, 0x00, - 0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00, 0x43, - 0x29, 0x01, 0x00, 0x00, 0x63, 0x07, 0x00, 0x42, - 0x11, 0x01, 0x00, 0x00, 0xb6, 0x63, 0x07, 0x00, - 0xeb, 0x24, 0x03, 0x00, 0x0e, 0x63, 0x01, 0x00, - 0x43, 0x2d, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, - 0xec, 0x1c, 0x63, 0x01, 0x00, 0x43, 0x1e, 0x01, - 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0x39, 0x96, - 0x00, 0x00, 0x00, 0x11, 0x04, 0x2e, 0x01, 0x00, - 0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00, - 0x43, 0x1e, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x0e, 0x66, 0x04, 0x00, 0x43, 0x29, 0x01, 0x00, - 0x00, 0x63, 0x07, 0x00, 0x42, 0x11, 0x01, 0x00, - 0x00, 0xb6, 0x63, 0x07, 0x00, 0xeb, 0x66, 0x05, - 0x00, 0x66, 0x06, 0x00, 0xa5, 0x24, 0x04, 0x00, - 0xc4, 0x08, 0x66, 0x01, 0x00, 0x43, 0x09, 0x01, - 0x00, 0x00, 0x63, 0x08, 0x00, 0x0b, 0x0a, 0x4d, - 0x2f, 0x01, 0x00, 0x00, 0x25, 0x02, 0x00, 0x08, - 0xec, 0x16, 0xc1, 0x00, 0x60, 0x09, 0x00, 0xc1, - 0x01, 0x60, 0x0a, 0x00, 0xc1, 0x02, 0x60, 0x0b, - 0x00, 0xc1, 0x03, 0x60, 0x0c, 0x00, 0x29, 0xb7, - 0xb6, 0xa0, 0xe6, 0xb7, 0xb9, 0xa0, 0x60, 0x04, - 0x00, 0xb7, 0xb6, 0xa0, 0x60, 0x05, 0x00, 0xb7, - 0xb9, 0xa0, 0x60, 0x06, 0x00, 0xb7, 0xba, 0xa0, - 0x60, 0x07, 0x00, 0x0b, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x4d, 0x14, 0x01, 0x00, 0x00, 0xbe, 0x08, - 0x4d, 0x15, 0x01, 0x00, 0x00, 0xba, 0x4d, 0x16, - 0x01, 0x00, 0x00, 0xbe, 0x0c, 0x4d, 0x13, 0x01, - 0x00, 0x00, 0x60, 0x08, 0x00, 0x06, 0x2f, -}; - diff --git a/quickjs-ng/gen/test_fib.c b/quickjs-ng/gen/test_fib.c deleted file mode 100644 index 8ac34a2..0000000 --- a/quickjs-ng/gen/test_fib.c +++ /dev/null @@ -1,80 +0,0 @@ -/* File generated automatically by the QuickJS-ng compiler. */ - -#include "quickjs-libc.h" - -const uint32_t qjsc_test_fib_size = 294; - -const uint8_t qjsc_test_fib[294] = { - 0x15, 0x0e, 0x01, 0x28, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, - 0x74, 0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, - 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, 0x6f, 0x73, - 0x01, 0x04, 0x6f, 0x73, 0x01, 0x0a, 0x69, 0x73, - 0x57, 0x69, 0x6e, 0x01, 0x06, 0x66, 0x69, 0x62, - 0x01, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x01, 0x0a, 0x77, 0x69, 0x6e, 0x33, - 0x32, 0x01, 0x0c, 0x2e, 0x2f, 0x66, 0x69, 0x62, - 0x2e, 0x01, 0x06, 0x64, 0x6c, 0x6c, 0x01, 0x04, - 0x73, 0x6f, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73, - 0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67, - 0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, - 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66, - 0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d, - 0xc6, 0x03, 0x01, 0xc8, 0x03, 0x00, 0x00, 0x01, - 0x00, 0xfe, 0x01, 0x00, 0x01, 0x0c, 0x20, 0x0a, - 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, - 0x00, 0x73, 0x00, 0xca, 0x03, 0x00, 0x0d, 0xcc, - 0x03, 0x00, 0x0d, 0xce, 0x03, 0x01, 0x0d, 0x08, - 0xec, 0x02, 0x29, 0x66, 0x00, 0x00, 0x42, 0xe8, - 0x00, 0x00, 0x00, 0x04, 0xe9, 0x00, 0x00, 0x00, - 0xaf, 0xe4, 0x06, 0x11, 0xf4, 0xed, 0x0b, 0x71, - 0x43, 0xe7, 0x00, 0x00, 0x00, 0xe5, 0x0e, 0xee, - 0x24, 0x0e, 0x04, 0xea, 0x00, 0x00, 0x00, 0x43, - 0x5d, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0xec, - 0x08, 0x04, 0xeb, 0x00, 0x00, 0x00, 0xee, 0x06, - 0x04, 0xec, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x36, 0x8c, 0xee, 0xd4, 0x39, 0xed, 0x00, 0x00, - 0x00, 0x43, 0xee, 0x00, 0x00, 0x00, 0x04, 0xef, - 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, - 0xed, 0x00, 0x00, 0x00, 0x43, 0xee, 0x00, 0x00, - 0x00, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x66, 0x02, - 0x00, 0xbe, 0x0a, 0xf1, 0x24, 0x02, 0x00, 0x0e, - 0x06, 0x2f, 0xc6, 0x03, 0x01, 0x01, 0x0e, 0x41, - 0x3c, 0x00, 0x39, 0x06, 0x3b, 0x34, 0x10, 0x30, - 0x0f, 0x34, 0x10, 0x2a, 0x20, 0x00, -}; - -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx = JS_NewContext(rt); - if (!ctx) - return NULL; - { - extern JSModuleDef *js_init_module_os(JSContext *ctx, const char *name); - js_init_module_os(ctx, "qjs:os"); - } - return ctx; -} - -int main(int argc, char **argv) -{ - int r; - JSRuntime *rt; - JSContext *ctx; - r = 0; - rt = JS_NewRuntime(); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - ctx = JS_NewCustomContext(rt); - js_std_add_helpers(ctx, argc, argv); - js_std_eval_binary(ctx, qjsc_test_fib, qjsc_test_fib_size, 0); - r = js_std_loop(ctx); - if (r) { - js_std_dump_error(ctx); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return r; -} diff --git a/quickjs-ng/meson.build b/quickjs-ng/meson.build deleted file mode 100644 index 5332677..0000000 --- a/quickjs-ng/meson.build +++ /dev/null @@ -1,521 +0,0 @@ -project( - 'quickjs-ng', - 'c', - version: '0.8.0', - default_options: [ - 'c_std=gnu11,c11', - 'warning_level=3', - 'default_library=static', - ], - license: 'MIT', - license_files: 'LICENSE', - meson_version: '>=1.3.0', -) - -host_system = host_machine.system() -cc = meson.get_compiler('c') - -qjs_gcc_warning_args = [ - '-Wno-unsafe-buffer-usage', - '-Wno-sign-conversion', - '-Wno-nonportable-system-include-path', - '-Wno-implicit-int-conversion', - '-Wno-shorten-64-to-32', - '-Wno-reserved-macro-identifier', - '-Wno-reserved-identifier', - '-Wdeprecated-declarations', - - '-Wno-implicit-fallthrough', - '-Wno-sign-compare', - '-Wno-missing-field-initializers', - '-Wno-unused-parameter', - '-Wno-unused-but-set-variable', - '-Wno-array-bounds', - '-Wno-format-truncation', -] -qjs_gcc_args = [ - '-funsigned-char', -] - -if host_system == 'darwin' - # https://github.com/quickjs-ng/quickjs/issues/453 - qjs_gcc_warning_args += '-Wno-maybe-uninitialized' -endif - -# https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings -qjs_msvc_warning_args = [ - '/wd4018', # -Wno-sign-conversion - '/wd4061', # -Wno-implicit-fallthrough - '/wd4100', # -Wno-unused-parameter - '/wd4200', # -Wno-zero-length-array - '/wd4242', # -Wno-shorten-64-to-32 - '/wd4244', # -Wno-shorten-64-to-32 - '/wd4245', # -Wno-sign-compare - '/wd4267', # -Wno-shorten-64-to-32 - '/wd4388', # -Wno-sign-compare - '/wd4389', # -Wno-sign-compare - '/wd4710', # Function not inlined - '/wd4711', # Function was inlined - '/wd4820', # Padding added after construct - '/wd4996', # -Wdeprecated-declarations - '/wd5045', # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified -] -qjs_msvc_args = [ - '/experimental:c11atomics', - '/J', # -funsigned-char -] - -if cc.get_argument_syntax() == 'msvc' - add_project_arguments( - cc.get_supported_arguments(qjs_msvc_warning_args), - cc.get_id().contains('clang') ? cc.get_supported_arguments(qjs_gcc_warning_args) : [], - qjs_msvc_args, - language: 'c', - ) -else - add_project_arguments( - cc.get_supported_arguments(qjs_gcc_warning_args), - qjs_gcc_args, - language: 'c', - ) -endif - -if host_system == 'windows' - # Set a 8MB default stack size on Windows. - # It defaults to 1MB on MSVC, which is the same as our current JS stack size, - # so it will overflow and crash otherwise. - # On MinGW it defaults to 2MB. - stack_size = 8 * 1024 * 1024 - if cc.get_argument_syntax() == 'msvc' - add_project_link_arguments(f'/STACK:@stack_size@', language: 'c') - else - add_project_link_arguments(f'-Wl,--stack,@stack_size@', language: 'c') - endif -endif - -if meson.is_cross_build() - native_cc = meson.get_compiler('c', native: true) - - if native_cc.get_argument_syntax() == 'msvc' - # https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings - add_project_arguments( - native_cc.get_supported_arguments(qjs_msvc_warning_args), - native_cc.get_id().contains('clang') ? native_cc.get_supported_arguments(qjs_gcc_warning_args) : [], - qjs_msvc_args, - - language: 'c', - native: true, - ) - else - add_project_arguments( - native_cc.get_supported_arguments(qjs_gcc_warning_args), - qjs_gcc_args, - - language: 'c', - native: true, - ) - endif -endif -if get_option('debug') - add_project_arguments( - cc.get_supported_arguments('-fno-omit-frame-pointer'), - language: 'c', - ) -endif -if get_option('disable_parser') - add_project_arguments( - ['-DQJS_DISABLE_PARSER'], - language: 'c', - ) -endif - -qjs_sys_deps = [] - -m_dep = cc.find_library('m', required: false) -qjs_sys_deps += m_dep -qjs_sys_deps += dependency('threads', required: false) -qjs_sys_deps += dependency('dl', required: false) - -qjs_srcs = files( - 'cutils.c', - 'dtoa.c', - 'libregexp.c', - 'libunicode.c', - 'quickjs.c', -) -qjs_hdrs = files( - 'quickjs.h', -) - -qjs_libc = get_option('libc') -qjs_libc_srcs = files('quickjs-libc.c') -qjs_libc_hdrs = files('quickjs-libc.h') - -if qjs_libc - qjs_hdrs += qjs_libc_hdrs -endif - -qjs_c_args = ['-D_GNU_SOURCE'] - -if host_system == 'windows' - qjs_c_args += ['-DWIN32_LEAN_AND_MEAN', '-D_WIN32_WINNT=0x0602'] -endif - -qjs_libc_lib = static_library( - 'quickjs-libc', - qjs_libc_srcs, - - dependencies: qjs_sys_deps, - c_args: qjs_c_args, - gnu_symbol_visibility: 'hidden', -) - -qjs_lib = library( - 'qjs', - qjs_srcs, - - # export public headers - generator( - find_program('cp', 'xcopy'), - output: ['@PLAINNAME@'], - arguments: ['@INPUT@', '@OUTPUT@'], - ).process(qjs_hdrs), - - dependencies: qjs_sys_deps, - link_whole: qjs_libc ? qjs_libc_lib : [], - c_args: qjs_c_args, - gnu_symbol_visibility: 'hidden', - - install: true, - version: meson.project_version(), -) - -qjs_dep = declare_dependency( - link_with: qjs_lib, - dependencies: qjs_sys_deps, - include_directories: qjs_lib.private_dir_include(), -) - -if host_system == 'emscripten' - qjs_wasm_export_name = 'getQuickJs' - executable( - 'qjs_wasm', - qjs_srcs, - link_args: cc.get_supported_link_arguments( - # in emscripten 3.x, this will be set to 16k which is too small for quickjs. - '-sSTACK_SIZE=@0@'.format(2 * 1024 * 1024), # let it be 2m = 2 * 1024 * 1024, otherwise, stack overflow may be occured at bootstrap - '-sNO_INVOKE_RUN', - '-sNO_EXIT_RUNTIME', - '-sMODULARIZE', # do not mess the global - '-sEXPORT_ES6', # export js file to morden es module - '-sEXPORT_NAME=@0@'.format(qjs_wasm_export_name), # give a name - '-sTEXTDECODER=1', # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail - '-sNO_DEFAULT_TO_CXX', # this project is pure c project, no need for c plus plus handle - '-sEXPORTED_RUNTIME_METHODS=ccall,cwrap', - ), - dependencies: m_dep, - c_args: qjs_c_args, - ) -endif - -install_headers(qjs_hdrs, subdir: 'quickjs-ng') - -if not meson.is_subproject() - docdir = get_option('docdir') - datadir = get_option('datadir') - - if docdir == '' - docdir = datadir / 'doc' / meson.project_name() - endif - install_data( - 'LICENSE', - install_dir: docdir, - - install_tag: 'doc', - ) - install_subdir( - 'examples', - install_dir: docdir, - - strip_directory: false, - install_tag: 'doc', - ) -endif - -meson.override_dependency('quickjs-ng', qjs_dep) - -import('pkgconfig').generate( - qjs_lib, - subdirs: 'quickjs-ng', - name: 'quickjs-ng', - description: 'QuickJS, the Next Generation: a mighty JavaScript engine', - url: 'https://github.com/quickjs-ng/quickjs', - version: meson.project_version(), -) - -# QuickJS bytecode compiler -qjsc_srcs = files( - 'qjsc.c', -) -qjsc_exe = executable( - 'qjsc', - qjsc_srcs, - - c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: qjs_dep, - - install: true, -) - -mimalloc_dep = [] -mimalloc_sys_dep = dependency('mimalloc', required: get_option('cli_mimalloc')) -if mimalloc_sys_dep.found() - mimalloc_dep = declare_dependency( - dependencies: mimalloc_sys_dep, - compile_args: '-DQJS_USE_MIMALLOC', - ) -endif - -# QuickJS CLI -qjs_exe_srcs = files( - 'gen/repl.c', - 'gen/standalone.c', - 'qjs.c', -) -qjs_exe = executable( - 'qjs', - qjs_exe_srcs, - - c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: [qjs_dep, mimalloc_dep], - - install: true, -) - -if meson.is_cross_build() - mimalloc_native_dep = [] - mimalloc_sys_native_dep = dependency('mimalloc', required: get_option('cli_mimalloc'), native: true) - if mimalloc_sys_dep.found() - mimalloc_native_dep = declare_dependency( - dependencies: mimalloc_sys_native_dep, - compile_args: '-DQJS_USE_MIMALLOC', - ) - endif - - qjs_sys_native_deps = [ - native_cc.find_library('m', required: false), - dependency('threads', required: false, native: true), - dependency('dl', required: false, native: true), - ] - qjs_native_lib = static_library( - 'qjs_native', - qjs_srcs, - qjs_libc_srcs, - - dependencies: qjs_sys_native_deps, - c_args: qjs_c_args, - gnu_symbol_visibility: 'hidden', - - build_by_default: false, - native: true, - install: false, - ) - - meson.override_find_program( - 'qjsc', - executable( - 'qjsc_native', - qjsc_srcs, - - c_args: qjs_c_args, - link_with: qjs_native_lib, - dependencies: qjs_sys_native_deps, - - build_by_default: false, - native: true, - install: false, - ), - ) - meson.override_find_program( - 'qjs', - executable( - 'qjs_native', - qjs_exe_srcs, - - c_args: qjs_c_args, - link_with: qjs_native_lib, - dependencies: [qjs_sys_native_deps, mimalloc_native_dep], - - build_by_default: false, - native: true, - install: false, - ), - ) -else - meson.override_find_program('qjsc', qjsc_exe) - meson.override_find_program('qjs', qjs_exe) -endif - -tests = get_option('tests').disable_auto_if(meson.is_subproject()) -examples = get_option('examples').disable_auto_if(meson.is_subproject()) - -if tests.allowed() - if host_system != 'emscripten' - # Test262 runner - run262_exe = executable( - 'run-test262', - 'run-test262.c', - qjs_libc_srcs, - - c_args: qjs_c_args, - dependencies: qjs_dep, - ) - - test( - 'test', - run262_exe, - args: ['-c', files('tests.conf')], - workdir: meson.current_source_dir(), - ) - - foreach bench : [ - 'empty_loop', - - 'date_now', - - 'prop_read', - 'prop_write', - 'prop_create', - 'prop_delete', - - 'array_read', - 'array_write', - 'array_prop_create', - 'array_length_decr', - 'array_hole_length_decr', - 'array_push', - 'array_pop', - - 'typed_array_read', - 'typed_array_write', - - 'global_read', - 'global_write', - 'global_write_strict', - - 'local_destruct', - 'global_destruct', - 'global_destruct_strict', - - 'func_call', - 'closure_var', - - 'int_arith', - 'float_arith', - - 'set_collection_add', - - 'array_for', - 'array_for_in', - 'array_for_of', - - 'math_min', - - 'regexp_ascii', - 'regexp_utf16', - - 'string_build1', - 'string_build2', - - 'sort_bench', - - 'int_to_string', - 'int_toString', - - 'float_to_string', - 'float_toString', - 'float_toFixed', - 'float_toPrecision', - 'float_toExponential', - - 'string_to_int', - 'string_to_float', - - 'bigint64_arith', - 'bigint256_arith', - ] - benchmark( - bench, - qjs_exe, - args: [files('tests/microbench.js'), bench], - ) - endforeach - endif - - # API test - test( - 'api', - executable( - 'api-test', - 'api-test.c', - - c_args: qjs_c_args, - dependencies: qjs_dep, - ), - ) -endif - -# Unicode generator -executable( - 'unicode_gen', - 'cutils.c', - 'libunicode.c', - 'unicode_gen.c', - - c_args: qjs_c_args, - build_by_default: false, -) - -executable( - 'function_source', - 'gen/function_source.c', - qjs_libc_srcs, - - c_args: qjs_c_args, - dependencies: qjs_dep, -) - -if examples.allowed() - executable( - 'hello', - 'gen/hello.c', - qjs_libc_srcs, - - c_args: qjs_c_args, - dependencies: qjs_dep, - ) - - executable( - 'hello_module', - 'gen/hello_module.c', - qjs_libc_srcs, - - c_args: qjs_c_args, - dependencies: qjs_dep, - ) - - subdir('examples') - - executable( - 'test_fib', - 'examples/fib.c', - 'gen/test_fib.c', - qjs_libc_srcs, - - c_args: qjs_c_args, - dependencies: qjs_dep, - export_dynamic: true, - ) -endif diff --git a/quickjs-ng/meson_options.txt b/quickjs-ng/meson_options.txt deleted file mode 100644 index eec8afd..0000000 --- a/quickjs-ng/meson_options.txt +++ /dev/null @@ -1,6 +0,0 @@ -option('tests', type: 'feature', description: 'build tests') -option('examples', type: 'feature', description: 'build examples') -option('libc', type: 'boolean', value: false, description: 'build qjs standard library modules as part of the library') -option('cli_mimalloc', type: 'feature', value: 'disabled', description: 'build qjs cli with mimalloc') -option('docdir', type: 'string', description: 'documentation directory') -option('disable_parser', type: 'boolean', value: false, description: 'Disable JS source code parser') diff --git a/quickjs-ng/qjs.c b/quickjs-ng/qjs.c deleted file mode 100644 index 4aed683..0000000 --- a/quickjs-ng/qjs.c +++ /dev/null @@ -1,748 +0,0 @@ -/* - * QuickJS stand alone interpreter - * - * Copyright (c) 2017-2021 Fabrice Bellard - * Copyright (c) 2017-2021 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cutils.h" -#include "quickjs.h" -#include "quickjs-libc.h" - -#ifdef QJS_USE_MIMALLOC -#include -#endif - -extern const uint8_t qjsc_repl[]; -extern const uint32_t qjsc_repl_size; -extern const uint8_t qjsc_standalone[]; -extern const uint32_t qjsc_standalone_size; - -// Must match standalone.js -#define TRAILER_SIZE 12 -static const char trailer_magic[] = "quickjs2"; -static const int trailer_magic_size = sizeof(trailer_magic) - 1; -static const int trailer_size = TRAILER_SIZE; - -static int qjs__argc; -static char **qjs__argv; - - -static bool is_standalone(const char *exe) -{ - FILE *exe_f = fopen(exe, "rb"); - if (!exe_f) - return false; - if (fseek(exe_f, -trailer_size, SEEK_END) < 0) - goto fail; - uint8_t buf[TRAILER_SIZE]; - if (fread(buf, 1, trailer_size, exe_f) != trailer_size) - goto fail; - fclose(exe_f); - return !memcmp(buf, trailer_magic, trailer_magic_size); -fail: - fclose(exe_f); - return false; -} - -static JSValue load_standalone_module(JSContext *ctx) -{ - JSModuleDef *m; - JSValue obj, val; - obj = JS_ReadObject(ctx, qjsc_standalone, qjsc_standalone_size, JS_READ_OBJ_BYTECODE); - if (JS_IsException(obj)) - goto exception; - assert(JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE); - if (JS_ResolveModule(ctx, obj) < 0) { - JS_FreeValue(ctx, obj); - goto exception; - } - if (js_module_set_import_meta(ctx, obj, false, true) < 0) { - JS_FreeValue(ctx, obj); - goto exception; - } - val = JS_EvalFunction(ctx, JS_DupValue(ctx, obj)); - val = js_std_await(ctx, val); - - if (JS_IsException(val)) { - JS_FreeValue(ctx, obj); - exception: - js_std_dump_error(ctx); - exit(1); - } - JS_FreeValue(ctx, val); - - m = JS_VALUE_GET_PTR(obj); - JS_FreeValue(ctx, obj); - return JS_GetModuleNamespace(ctx, m); -} - -static int eval_buf(JSContext *ctx, const void *buf, int buf_len, - const char *filename, int eval_flags) -{ - bool use_realpath; - JSValue val; - int ret; - - if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) { - /* for the modules, we compile then run to be able to set - import.meta */ - val = JS_Eval(ctx, buf, buf_len, filename, - eval_flags | JS_EVAL_FLAG_COMPILE_ONLY); - if (!JS_IsException(val)) { - // ex. "" pr "/dev/stdin" - use_realpath = - !(*filename == '<' || !strncmp(filename, "/dev/", 5)); - if (js_module_set_import_meta(ctx, val, use_realpath, true) < 0) { - js_std_dump_error(ctx); - ret = -1; - goto end; - } - val = JS_EvalFunction(ctx, val); - } - val = js_std_await(ctx, val); - } else { - val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); - } - if (JS_IsException(val)) { - js_std_dump_error(ctx); - ret = -1; - } else { - ret = 0; - } -end: - JS_FreeValue(ctx, val); - return ret; -} - -static int eval_file(JSContext *ctx, const char *filename, int module) -{ - uint8_t *buf; - int ret, eval_flags; - size_t buf_len; - - buf = js_load_file(ctx, &buf_len, filename); - if (!buf) { - perror(filename); - exit(1); - } - - if (module < 0) { - module = (js__has_suffix(filename, ".mjs") || - JS_DetectModule((const char *)buf, buf_len)); - } - if (module) - eval_flags = JS_EVAL_TYPE_MODULE; - else - eval_flags = JS_EVAL_TYPE_GLOBAL; - ret = eval_buf(ctx, buf, buf_len, filename, eval_flags); - js_free(ctx, buf); - return ret; -} - -static int64_t parse_limit(const char *arg) { - char *p; - unsigned long unit = 1024; /* default to traditional KB */ - double d = strtod(arg, &p); - - if (p == arg) { - fprintf(stderr, "Invalid limit: %s\n", arg); - return -1; - } - - if (*p) { - switch (*p++) { - case 'b': case 'B': unit = 1UL << 0; break; - case 'k': case 'K': unit = 1UL << 10; break; /* IEC kibibytes */ - case 'm': case 'M': unit = 1UL << 20; break; /* IEC mebibytes */ - case 'g': case 'G': unit = 1UL << 30; break; /* IEC gigibytes */ - default: - fprintf(stderr, "Invalid limit: %s, unrecognized suffix, only k,m,g are allowed\n", arg); - return -1; - } - if (*p) { - fprintf(stderr, "Invalid limit: %s, only one suffix allowed\n", arg); - return -1; - } - } - - return (int64_t)(d * unit); -} - -static JSValue js_gc(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JS_RunGC(JS_GetRuntime(ctx)); - return JS_UNDEFINED; -} - -static JSValue js_navigator_get_userAgent(JSContext *ctx, JSValueConst this_val) -{ - char version[32]; - snprintf(version, sizeof(version), "quickjs-ng/%s", JS_GetVersion()); - return JS_NewString(ctx, version); -} - -static const JSCFunctionListEntry navigator_proto_funcs[] = { - JS_CGETSET_DEF2("userAgent", js_navigator_get_userAgent, NULL, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Navigator", JS_PROP_CONFIGURABLE), -}; - -static const JSCFunctionListEntry global_obj[] = { - JS_CFUNC_DEF("gc", 0, js_gc), -}; - -/* also used to initialize the worker context */ -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx; - ctx = JS_NewContext(rt); - if (!ctx) - return NULL; - /* system modules */ - js_init_module_std(ctx, "qjs:std"); - js_init_module_os(ctx, "qjs:os"); - js_init_module_bjson(ctx, "qjs:bjson"); - - JSValue global = JS_GetGlobalObject(ctx); - JS_SetPropertyFunctionList(ctx, global, global_obj, countof(global_obj)); - JSValue args = JS_NewArray(ctx); - int i; - for(i = 0; i < qjs__argc; i++) { - JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, qjs__argv[i])); - } - JS_SetPropertyStr(ctx, global, "execArgv", args); - JS_SetPropertyStr(ctx, global, "argv0", JS_NewString(ctx, qjs__argv[0])); - JSValue navigator_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, navigator_proto, navigator_proto_funcs, countof(navigator_proto_funcs)); - JSValue navigator = JS_NewObjectProto(ctx, navigator_proto); - JS_DefinePropertyValueStr(ctx, global, "navigator", navigator, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE); - JS_FreeValue(ctx, global); - JS_FreeValue(ctx, navigator_proto); - - return ctx; -} - -struct trace_malloc_data { - uint8_t *base; -}; - -static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, - struct trace_malloc_data *dp) -{ - return ptr - dp->base; -} - -static void JS_PRINTF_FORMAT_ATTR(2, 3) js_trace_malloc_printf(void *opaque, JS_PRINTF_FORMAT const char *fmt, ...) -{ - va_list ap; - int c; - - va_start(ap, fmt); - while ((c = *fmt++) != '\0') { - if (c == '%') { - /* only handle %p and %zd */ - if (*fmt == 'p') { - uint8_t *ptr = va_arg(ap, void *); - if (ptr == NULL) { - printf("NULL"); - } else { - printf("H%+06lld.%zd", - js_trace_malloc_ptr_offset(ptr, opaque), - js__malloc_usable_size(ptr)); - } - fmt++; - continue; - } - if (fmt[0] == 'z' && fmt[1] == 'd') { - size_t sz = va_arg(ap, size_t); - printf("%zd", sz); - fmt += 2; - continue; - } - } - putc(c, stdout); - } - va_end(ap); -} - -static void js_trace_malloc_init(struct trace_malloc_data *s) -{ - free(s->base = malloc(8)); -} - -static void *js_trace_calloc(void *opaque, size_t count, size_t size) -{ - void *ptr; - ptr = calloc(count, size); - js_trace_malloc_printf(opaque, "C %zd %zd -> %p\n", count, size, ptr); - return ptr; -} - -static void *js_trace_malloc(void *opaque, size_t size) -{ - void *ptr; - ptr = malloc(size); - js_trace_malloc_printf(opaque, "A %zd -> %p\n", size, ptr); - return ptr; -} - -static void js_trace_free(void *opaque, void *ptr) -{ - if (!ptr) - return; - js_trace_malloc_printf(opaque, "F %p\n", ptr); - free(ptr); -} - -static void *js_trace_realloc(void *opaque, void *ptr, size_t size) -{ - js_trace_malloc_printf(opaque, "R %zd %p", size, ptr); - ptr = realloc(ptr, size); - js_trace_malloc_printf(opaque, " -> %p\n", ptr); - return ptr; -} - -static const JSMallocFunctions trace_mf = { - js_trace_calloc, - js_trace_malloc, - js_trace_free, - js_trace_realloc, - js__malloc_usable_size -}; - -#ifdef QJS_USE_MIMALLOC -static void *js_mi_calloc(void *opaque, size_t count, size_t size) -{ - return mi_calloc(count, size); -} - -static void *js_mi_malloc(void *opaque, size_t size) -{ - return mi_malloc(size); -} - -static void js_mi_free(void *opaque, void *ptr) -{ - if (!ptr) - return; - mi_free(ptr); -} - -static void *js_mi_realloc(void *opaque, void *ptr, size_t size) -{ - return mi_realloc(ptr, size); -} - -static const JSMallocFunctions mi_mf = { - js_mi_calloc, - js_mi_malloc, - js_mi_free, - js_mi_realloc, - mi_malloc_usable_size -}; -#endif - -#define PROG_NAME "qjs" - -void help(void) -{ - printf("QuickJS-ng version %s\n" - "usage: " PROG_NAME " [options] [file [args]]\n" - "-h --help list options\n" - "-e --eval EXPR evaluate EXPR\n" - "-i --interactive go to interactive mode\n" - "-C --script load as JS classic script (default=autodetect)\n" - "-m --module load as ES module (default=autodetect)\n" - "-I --include file include an additional file\n" - " --std make 'std', 'os' and 'bjson' available to script\n" - "-T --trace trace memory allocation\n" - "-d --dump dump the memory usage stats\n" - "-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n" - "-c --compile FILE compile the given JS file as a standalone executable\n" - "-o --out FILE output file for standalone executables\n" - " --exe select the executable to use as the base, defaults to the current one\n" - " --memory-limit n limit the memory usage to 'n' Kbytes\n" - " --stack-size n limit the stack size to 'n' Kbytes\n" - "-q --quit just instantiate the interpreter and quit\n", JS_GetVersion()); - exit(1); -} - -int main(int argc, char **argv) -{ - JSRuntime *rt; - JSContext *ctx; - JSValue ret = JS_UNDEFINED; - struct trace_malloc_data trace_data = { NULL }; - int r = 0; - int optind = 1; - char exebuf[JS__PATH_MAX]; - size_t exebuf_size = sizeof(exebuf); - char *compile_file = NULL; - char *exe = NULL; - char *expr = NULL; - char *dump_flags_str = NULL; - char *out = NULL; - int standalone = 0; - int interactive = 0; - int dump_memory = 0; - int dump_flags = 0; - int trace_memory = 0; - int empty_run = 0; - int module = -1; - int load_std = 0; - char *include_list[32]; - int i, include_count = 0; - int64_t memory_limit = -1; - int64_t stack_size = -1; - - /* save for later */ - qjs__argc = argc; - qjs__argv = argv; - - /* check if this is a standalone executable */ - - if (!js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) { - standalone = 1; - goto start; - } - - dump_flags_str = getenv("QJS_DUMP_FLAGS"); - dump_flags = dump_flags_str ? strtol(dump_flags_str, NULL, 16) : 0; - - /* cannot use getopt because we want to pass the command line to - the script */ - while (optind < argc && *argv[optind] == '-') { - char *arg = argv[optind] + 1; - const char *longopt = ""; - char *optarg = NULL; - /* a single - is not an option, it also stops argument scanning */ - if (!*arg) - break; - optind++; - if (*arg == '-') { - longopt = arg + 1; - optarg = strchr(longopt, '='); - if (optarg) - *optarg++ = '\0'; - arg += strlen(arg); - /* -- stops argument scanning */ - if (!*longopt) - break; - } - for (; *arg || *longopt; longopt = "") { - char opt = *arg; - if (opt) { - arg++; - if (!optarg && *arg) - optarg = arg; - } - if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { - help(); - continue; - } - if (opt == 'e' || !strcmp(longopt, "eval")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "qjs: missing expression for -e\n"); - exit(1); - } - optarg = argv[optind++]; - } - expr = optarg; - break; - } - if (opt == 'I' || !strcmp(longopt, "include")) { - if (optind >= argc) { - fprintf(stderr, "expecting filename"); - exit(1); - } - if (include_count >= countof(include_list)) { - fprintf(stderr, "too many included files"); - exit(1); - } - include_list[include_count++] = argv[optind++]; - continue; - } - if (opt == 'i' || !strcmp(longopt, "interactive")) { - interactive++; - continue; - } - if (opt == 'm' || !strcmp(longopt, "module")) { - module = 1; - continue; - } - if (opt == 'C' || !strcmp(longopt, "script")) { - module = 0; - continue; - } - if (opt == 'd' || !strcmp(longopt, "dump")) { - dump_memory++; - continue; - } - if (opt == 'D' || !strcmp(longopt, "dump-flags")) { - dump_flags = optarg ? strtol(optarg, NULL, 16) : 0; - break; - } - if (opt == 'T' || !strcmp(longopt, "trace")) { - trace_memory++; - continue; - } - if (!strcmp(longopt, "std")) { - load_std = 1; - continue; - } - if (opt == 'q' || !strcmp(longopt, "quit")) { - empty_run++; - continue; - } - if (!strcmp(longopt, "memory-limit")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "expecting memory limit"); - exit(1); - } - optarg = argv[optind++]; - } - memory_limit = parse_limit(optarg); - break; - } - if (!strcmp(longopt, "stack-size")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "expecting stack size"); - exit(1); - } - optarg = argv[optind++]; - } - stack_size = parse_limit(optarg); - break; - } - if (opt == 'c' || !strcmp(longopt, "compile")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "qjs: missing file for -c\n"); - exit(1); - } - optarg = argv[optind++]; - } - compile_file = optarg; - break; - } - if (opt == 'o' || !strcmp(longopt, "out")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "qjs: missing file for -o\n"); - exit(1); - } - optarg = argv[optind++]; - } - out = optarg; - break; - } - if (!strcmp(longopt, "exe")) { - if (!optarg) { - if (optind >= argc) { - fprintf(stderr, "qjs: missing file for --exe\n"); - exit(1); - } - optarg = argv[optind++]; - } - exe = optarg; - break; - } - if (opt) { - fprintf(stderr, "qjs: unknown option '-%c'\n", opt); - } else { - fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); - } - help(); - } - } - - if (compile_file && !out) - help(); - -start: - - if (trace_memory) { - js_trace_malloc_init(&trace_data); - rt = JS_NewRuntime2(&trace_mf, &trace_data); - } else { -#ifdef QJS_USE_MIMALLOC - rt = JS_NewRuntime2(&mi_mf, NULL); -#else - rt = JS_NewRuntime(); -#endif - } - if (!rt) { - fprintf(stderr, "qjs: cannot allocate JS runtime\n"); - exit(2); - } - if (memory_limit >= 0) - JS_SetMemoryLimit(rt, (size_t)memory_limit); - if (stack_size >= 0) - JS_SetMaxStackSize(rt, (size_t)stack_size); - if (dump_flags != 0) - JS_SetDumpFlags(rt, dump_flags); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - ctx = JS_NewCustomContext(rt); - if (!ctx) { - fprintf(stderr, "qjs: cannot allocate JS context\n"); - exit(2); - } - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - - /* exit on unhandled promise rejections */ - JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); - - if (!empty_run) { - js_std_add_helpers(ctx, argc - optind, argv + optind); - - /* make 'std' and 'os' visible to non module code */ - if (load_std) { - const char *str = - "import * as bjson from 'qjs:bjson';\n" - "import * as std from 'qjs:std';\n" - "import * as os from 'qjs:os';\n" - "globalThis.bjson = bjson;\n" - "globalThis.std = std;\n" - "globalThis.os = os;\n"; - eval_buf(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE); - } - - for(i = 0; i < include_count; i++) { - if (eval_file(ctx, include_list[i], 0)) - goto fail; - } - - if (standalone) { - JSValue ns = load_standalone_module(ctx); - if (JS_IsException(ns)) - goto fail; - JSValue func = JS_GetPropertyStr(ctx, ns, "runStandalone"); - JS_FreeValue(ctx, ns); - if (JS_IsException(func)) - goto fail; - ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL); - JS_FreeValue(ctx, func); - } else if (compile_file) { - JSValue ns = load_standalone_module(ctx); - if (JS_IsException(ns)) - goto fail; - JSValue func = JS_GetPropertyStr(ctx, ns, "compileStandalone"); - JS_FreeValue(ctx, ns); - if (JS_IsException(func)) - goto fail; - JSValue args[3]; - args[0] = JS_NewString(ctx, compile_file); - args[1] = JS_NewString(ctx, out); - args[2] = exe != NULL ? JS_NewString(ctx, exe) : JS_UNDEFINED; - ret = JS_Call(ctx, func, JS_UNDEFINED, 3, (JSValueConst *)args); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, args[0]); - JS_FreeValue(ctx, args[1]); - JS_FreeValue(ctx, args[2]); - } else if (expr) { - int flags = module ? JS_EVAL_TYPE_MODULE : 0; - if (eval_buf(ctx, expr, strlen(expr), "", flags)) - goto fail; - } else if (optind >= argc) { - /* interactive mode */ - interactive = 1; - } else { - const char *filename; - filename = argv[optind]; - if (eval_file(ctx, filename, module)) - goto fail; - } - if (interactive) { - JS_SetHostPromiseRejectionTracker(rt, NULL, NULL); - js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0); - } - if (standalone || compile_file) { - if (JS_IsException(ret)) { - r = 1; - } else { - JS_FreeValue(ctx, ret); - r = js_std_loop(ctx); - } - } else { - r = js_std_loop(ctx); - } - if (r) { - js_std_dump_error(ctx); - goto fail; - } - } - - if (dump_memory) { - JSMemoryUsage stats; - JS_ComputeMemoryUsage(rt, &stats); - JS_DumpMemoryUsage(stdout, &stats, rt); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - - if (empty_run && dump_memory) { - clock_t t[5]; - double best[5] = {0}; - int i, j; - for (i = 0; i < 100; i++) { - t[0] = clock(); - rt = JS_NewRuntime(); - t[1] = clock(); - ctx = JS_NewContext(rt); - t[2] = clock(); - JS_FreeContext(ctx); - t[3] = clock(); - JS_FreeRuntime(rt); - t[4] = clock(); - for (j = 4; j > 0; j--) { - double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC; - if (i == 0 || best[j] > ms) - best[j] = ms; - } - } - printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n", - best[1] + best[2] + best[3] + best[4], - best[1], best[2], best[3], best[4]); - } - return 0; - fail: - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return 1; -} diff --git a/quickjs-ng/qjsc.c b/quickjs-ng/qjsc.c deleted file mode 100644 index 395bcb3..0000000 --- a/quickjs-ng/qjsc.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * QuickJS command line compiler - * - * Copyright (c) 2018-2024 Fabrice Bellard - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include - -#include "cutils.h" -#include "quickjs-libc.h" - -typedef enum { - OUTPUT_C, - OUTPUT_C_MAIN, - OUTPUT_RAW, -} OutputTypeEnum; - -typedef struct { - char *name; - char *short_name; - int flags; -} namelist_entry_t; - -typedef struct namelist_t { - namelist_entry_t *array; - int count; - int size; -} namelist_t; - -static namelist_t cname_list; -static namelist_t cmodule_list; -static namelist_t init_module_list; -static OutputTypeEnum output_type; -static FILE *outfile; -static const char *c_ident_prefix = "qjsc_"; -static int strip; - -void namelist_add(namelist_t *lp, const char *name, const char *short_name, - int flags) -{ - namelist_entry_t *e; - if (lp->count == lp->size) { - size_t newsize = lp->size + (lp->size >> 1) + 4; - namelist_entry_t *a = - realloc(lp->array, sizeof(lp->array[0]) * newsize); - /* XXX: check for realloc failure */ - lp->array = a; - lp->size = newsize; - } - e = &lp->array[lp->count++]; - e->name = strdup(name); - if (short_name) - e->short_name = strdup(short_name); - else - e->short_name = NULL; - e->flags = flags; -} - -void namelist_free(namelist_t *lp) -{ - while (lp->count > 0) { - namelist_entry_t *e = &lp->array[--lp->count]; - free(e->name); - free(e->short_name); - } - free(lp->array); - lp->array = NULL; - lp->size = 0; -} - -namelist_entry_t *namelist_find(namelist_t *lp, const char *name) -{ - int i; - for(i = 0; i < lp->count; i++) { - namelist_entry_t *e = &lp->array[i]; - if (!strcmp(e->name, name)) - return e; - } - return NULL; -} - -static void get_c_name(char *buf, size_t buf_size, const char *file) -{ - const char *p, *r; - size_t len, i; - int c; - char *q; - - p = strrchr(file, '/'); - if (!p) - p = file; - else - p++; - r = strrchr(p, '.'); - if (!r) - len = strlen(p); - else - len = r - p; - js__pstrcpy(buf, buf_size, c_ident_prefix); - q = buf + strlen(buf); - for(i = 0; i < len; i++) { - c = p[i]; - if (!((c >= '0' && c <= '9') || - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z'))) { - c = '_'; - } - if ((q - buf) < buf_size - 1) - *q++ = c; - } - *q = '\0'; -} - -static void dump_hex(FILE *f, const uint8_t *buf, size_t len) -{ - size_t i, col; - col = 0; - for(i = 0; i < len; i++) { - fprintf(f, " 0x%02x,", buf[i]); - if (++col == 8) { - fprintf(f, "\n"); - col = 0; - } - } - if (col != 0) - fprintf(f, "\n"); -} - -static void output_object_code(JSContext *ctx, - FILE *fo, JSValue obj, const char *c_name, - bool load_only) -{ - uint8_t *out_buf; - size_t out_buf_len; - int flags = JS_WRITE_OBJ_BYTECODE; - - if (strip) { - flags |= JS_WRITE_OBJ_STRIP_SOURCE; - if (strip > 1) - flags |= JS_WRITE_OBJ_STRIP_DEBUG; - } - - out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); - if (!out_buf) { - js_std_dump_error(ctx); - exit(1); - } - - namelist_add(&cname_list, c_name, NULL, load_only); - - if (output_type == OUTPUT_RAW) { - fwrite(out_buf, 1, out_buf_len, fo); - } else { - fprintf(fo, "const uint32_t %s_size = %u;\n\n", - c_name, (unsigned int)out_buf_len); - fprintf(fo, "const uint8_t %s[%u] = {\n", - c_name, (unsigned int)out_buf_len); - dump_hex(fo, out_buf, out_buf_len); - fprintf(fo, "};\n\n"); - } - - js_free(ctx, out_buf); -} - -static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) -{ - /* should never be called when compiling JS code */ - abort(); - return -1; // pacify compiler -} - -static void find_unique_cname(char *cname, size_t cname_size) -{ - char cname1[1024]; - int suffix_num; - size_t len, max_len; - assert(cname_size >= 32); - /* find a C name not matching an existing module C name by - adding a numeric suffix */ - len = strlen(cname); - max_len = cname_size - 16; - if (len > max_len) - cname[max_len] = '\0'; - suffix_num = 1; - for(;;) { - snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num); - if (!namelist_find(&cname_list, cname1)) - break; - suffix_num++; - } - js__pstrcpy(cname, cname_size, cname1); -} - -JSModuleDef *jsc_module_loader(JSContext *ctx, - const char *module_name, void *opaque) -{ - JSModuleDef *m; - namelist_entry_t *e; - - /* check if it is a declared C or system module */ - e = namelist_find(&cmodule_list, module_name); - if (e) { - /* add in the static init module list */ - namelist_add(&init_module_list, e->name, e->short_name, 0); - /* create a dummy module */ - m = JS_NewCModule(ctx, module_name, js_module_dummy_init); - } else if (js__has_suffix(module_name, ".so")) { - JS_ThrowReferenceError(ctx, "%s: dynamically linking to shared libraries not supported", - module_name); - return NULL; - } else { - size_t buf_len; - uint8_t *buf; - JSValue func_val; - char cname[1000]; - - buf = js_load_file(ctx, &buf_len, module_name); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", - module_name); - return NULL; - } - - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - get_c_name(cname, sizeof(cname), module_name); - if (namelist_find(&cname_list, cname)) { - find_unique_cname(cname, sizeof(cname)); - } - output_object_code(ctx, outfile, func_val, cname, true); - - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); - } - return m; -} - -static void compile_file(JSContext *ctx, FILE *fo, - const char *filename, - const char *script_name, - const char *c_name1, - int module) -{ - uint8_t *buf; - char c_name[1024]; - int eval_flags; - JSValue obj; - size_t buf_len; - - buf = js_load_file(ctx, &buf_len, filename); - if (!buf) { - fprintf(stderr, "Could not load '%s'\n", filename); - exit(1); - } - eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; - if (module < 0) { - module = (js__has_suffix(filename, ".mjs") || - JS_DetectModule((const char *)buf, buf_len)); - } - if (module) - eval_flags |= JS_EVAL_TYPE_MODULE; - else - eval_flags |= JS_EVAL_TYPE_GLOBAL; - obj = JS_Eval(ctx, (const char *)buf, buf_len, script_name ? script_name : filename, eval_flags); - if (JS_IsException(obj)) { - js_std_dump_error(ctx); - exit(1); - } - js_free(ctx, buf); - if (c_name1) { - js__pstrcpy(c_name, sizeof(c_name), c_name1); - } else { - get_c_name(c_name, sizeof(c_name), filename); - } - output_object_code(ctx, fo, obj, c_name, false); - JS_FreeValue(ctx, obj); -} - -static const char main_c_template1[] = - "int main(int argc, char **argv)\n" - "{\n" - " int r;\n" - " JSRuntime *rt;\n" - " JSContext *ctx;\n" - " r = 0;\n" - " rt = JS_NewRuntime();\n" - " js_std_set_worker_new_context_func(JS_NewCustomContext);\n" - " js_std_init_handlers(rt);\n" - ; - -static const char main_c_template2[] = - " r = js_std_loop(ctx);\n" - " if (r) {\n" - " js_std_dump_error(ctx);\n" - " }\n" - " js_std_free_handlers(rt);\n" - " JS_FreeContext(ctx);\n" - " JS_FreeRuntime(rt);\n" - " return r;\n" - "}\n"; - -#define PROG_NAME "qjsc" - -void help(void) -{ - printf("QuickJS-ng Compiler version %s\n" - "usage: " PROG_NAME " [options] [files]\n" - "\n" - "options are:\n" - "-b output raw bytecode instead of C code\n" - "-e output main() and bytecode in a C file\n" - "-o output set the output filename\n" - "-n script_name set the script name (as used in stack traces)\n" - "-N cname set the C name of the generated data\n" - "-C compile as JS classic script (default=autodetect)\n" - "-m compile as ES module (default=autodetect)\n" - "-D module_name compile a dynamically loaded module or worker\n" - "-M module_name[,cname] add initialization code for an external C module\n" - "-p prefix set the prefix of the generated C names\n" - "-P do not add default system modules\n" - "-s strip the source code, specify twice to also strip debug info\n" - "-S n set the maximum stack size to 'n' bytes (default=%d)\n", - JS_GetVersion(), - JS_DEFAULT_STACK_SIZE); - exit(1); -} - -// TODO(bnoordhuis) share with qjs.c maybe -static int64_t parse_limit(const char *arg) { - char *p; - unsigned long unit = 1; // bytes for backcompat; qjs defaults to kilobytes - double d = strtod(arg, &p); - - if (p == arg) { - fprintf(stderr, "qjsc: invalid limit: %s\n", arg); - return -1; - } - - if (*p) { - switch (*p++) { - case 'b': case 'B': unit = 1UL << 0; break; - case 'k': case 'K': unit = 1UL << 10; break; /* IEC kibibytes */ - case 'm': case 'M': unit = 1UL << 20; break; /* IEC mebibytes */ - case 'g': case 'G': unit = 1UL << 30; break; /* IEC gigibytes */ - default: - fprintf(stderr, "qjsc: invalid limit: %s, unrecognized suffix, only k,m,g are allowed\n", arg); - return -1; - } - if (*p) { - fprintf(stderr, "qjsc: invalid limit: %s, only one suffix allowed\n", arg); - return -1; - } - } - - return (int64_t)(d * unit); -} - -static void check_hasarg(int optind, int argc, int opt) -{ - if (optind >= argc) { - fprintf(stderr, "qjsc: missing file for -%c\n", opt); - exit(1); - } -} - -int main(int argc, char **argv) -{ - int optind = 1; - int i; - const char *out_filename, *cname, *script_name; - char cfilename[1024]; - FILE *fo; - JSRuntime *rt; - JSContext *ctx; - int module; - size_t stack_size; - namelist_t dynamic_module_list; - bool load_system_modules = true; - - out_filename = NULL; - script_name = NULL; - output_type = OUTPUT_C; - cname = NULL; - module = -1; - strip = 0; - stack_size = 0; - memset(&dynamic_module_list, 0, sizeof(dynamic_module_list)); - - - while (optind < argc && *argv[optind] == '-') { - char *arg = argv[optind] + 1; - const char *longopt = ""; - char *optarg = NULL; - /* a single - is not an option, it also stops argument scanning */ - if (!*arg) - break; - optind++; - if (*arg == '-') { - longopt = arg + 1; - optarg = strchr(longopt, '='); - if (optarg) - *optarg++ = '\0'; - arg += strlen(arg); - /* -- stops argument scanning */ - if (!*longopt) - break; - } - for (; *arg || *longopt; longopt = "") { - char opt = *arg; - if (opt) { - arg++; - if (!optarg && *arg) - optarg = arg; - } - if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { - help(); - continue; - } - if (opt == 'b') { - output_type = OUTPUT_RAW; - continue; - } - if (opt == 'o') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - out_filename = optarg; - continue; - } - if (opt == 'e') { - output_type = OUTPUT_C_MAIN; - continue; - } - if (opt == 'n') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - script_name = optarg; - continue; - } - if (opt == 'N') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - cname = optarg; - continue; - } - if (opt == 'C') { - module = 0; - continue; - } - if (opt == 'm') { - module = 1; - continue; - } - if (opt == 'M') { - char *p; - char path[1024]; - char cname[1024]; - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - js__pstrcpy(path, sizeof(path), optarg); - p = strchr(path, ','); - if (p) { - *p = '\0'; - js__pstrcpy(cname, sizeof(cname), p + 1); - } else { - get_c_name(cname, sizeof(cname), path); - } - namelist_add(&cmodule_list, path, cname, 0); - continue; - } - if (opt == 'D') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - namelist_add(&dynamic_module_list, optarg, NULL, 0); - continue; - } - if (opt == 'P') { - load_system_modules = false; - continue; - } - if (opt == 's') { - strip++; - continue; - } - if (opt == 'p') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - c_ident_prefix = optarg; - continue; - } - if (opt == 'S') { - if (!optarg) { - check_hasarg(optind, argc, opt); - optarg = argv[optind++]; - } - stack_size = parse_limit(optarg); - continue; - } - help(); - } - } - - if (load_system_modules) { - /* add system modules */ - namelist_add(&cmodule_list, "qjs:std", "std", 0); - namelist_add(&cmodule_list, "qjs:os", "os", 0); - namelist_add(&cmodule_list, "qjs:bjson", "bjson", 0); - namelist_add(&cmodule_list, "std", "std", 0); - namelist_add(&cmodule_list, "os", "os", 0); - namelist_add(&cmodule_list, "bjson", "bjson", 0); - } - - if (optind >= argc) - help(); - - if (!out_filename) - out_filename = "out.c"; - - js__pstrcpy(cfilename, sizeof(cfilename), out_filename); - - if (output_type == OUTPUT_RAW) - fo = fopen(cfilename, "wb"); - else - fo = fopen(cfilename, "w"); - - if (!fo) { - perror(cfilename); - exit(1); - } - outfile = fo; - - rt = JS_NewRuntime(); - ctx = JS_NewContext(rt); - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); - - if (output_type != OUTPUT_RAW) { - fprintf(fo, "/* File generated automatically by the QuickJS-ng compiler. */\n" - "\n" - ); - } - - if (output_type == OUTPUT_C_MAIN) { - fprintf(fo, "#include \"quickjs-libc.h\"\n" - "\n" - ); - } else if (output_type == OUTPUT_C) { - fprintf(fo, "#include \n" - "\n" - ); - } - - for(i = optind; i < argc; i++) { - const char *filename = argv[i]; - compile_file(ctx, fo, filename, script_name, cname, module); - cname = NULL; - } - - for(i = 0; i < dynamic_module_list.count; i++) { - if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) { - fprintf(stderr, "Could not load dynamic module '%s'\n", - dynamic_module_list.array[i].name); - exit(1); - } - } - - if (output_type == OUTPUT_C_MAIN) { - fprintf(fo, - "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n" - "{\n" - " JSContext *ctx = JS_NewContext(rt);\n" - " if (!ctx)\n" - " return NULL;\n"); - /* add the precompiled modules (XXX: could modify the module - loader instead) */ - for(i = 0; i < init_module_list.count; i++) { - namelist_entry_t *e = &init_module_list.array[i]; - /* initialize the static C modules */ - - fprintf(fo, - " {\n" - " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" - " js_init_module_%s(ctx, \"%s\");\n" - " }\n", - e->short_name, e->short_name, e->name); - } - for(i = 0; i < cname_list.count; i++) { - namelist_entry_t *e = &cname_list.array[i]; - if (e->flags) { - fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n", - e->name, e->name); - } - } - fprintf(fo, - " return ctx;\n" - "}\n\n"); - - fputs(main_c_template1, fo); - - if (stack_size != 0) { - fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n", - (unsigned int)stack_size); - } - - /* add the module loader */ - fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); - - fprintf(fo, - " ctx = JS_NewCustomContext(rt);\n" - " js_std_add_helpers(ctx, argc, argv);\n"); - - for(i = 0; i < cname_list.count; i++) { - namelist_entry_t *e = &cname_list.array[i]; - if (!e->flags) { - fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n", - e->name, e->name); - } - } - fputs(main_c_template2, fo); - } - - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - - fclose(fo); - - namelist_free(&cname_list); - namelist_free(&cmodule_list); - namelist_free(&init_module_list); - return 0; -} diff --git a/quickjs-ng/quickjs-c-atomics.h b/quickjs-ng/quickjs-c-atomics.h deleted file mode 100644 index 8fc6b72..0000000 --- a/quickjs-ng/quickjs-c-atomics.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * QuickJS C atomics definitions - * - * Copyright (c) 2023 Marcin Kolny - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__) - // Use GCC builtins for version < 4.9 -# if((__GNUC__ << 16) + __GNUC_MINOR__ < ((4) << 16) + 9) -# define GCC_BUILTIN_ATOMICS -# endif -#endif - -#ifdef GCC_BUILTIN_ATOMICS -#define atomic_fetch_add(obj, arg) \ - __atomic_fetch_add(obj, arg, __ATOMIC_SEQ_CST) -#define atomic_compare_exchange_strong(obj, expected, desired) \ - __atomic_compare_exchange_n(obj, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) -#define atomic_exchange(obj, desired) \ - __atomic_exchange_n (obj, desired, __ATOMIC_SEQ_CST) -#define atomic_load(obj) \ - __atomic_load_n(obj, __ATOMIC_SEQ_CST) -#define atomic_store(obj, desired) \ - __atomic_store_n(obj, desired, __ATOMIC_SEQ_CST) -#define atomic_fetch_or(obj, arg) \ - __atomic_fetch_or(obj, arg, __ATOMIC_SEQ_CST) -#define atomic_fetch_xor(obj, arg) \ - __atomic_fetch_xor(obj, arg, __ATOMIC_SEQ_CST) -#define atomic_fetch_and(obj, arg) \ - __atomic_fetch_and(obj, arg, __ATOMIC_SEQ_CST) -#define atomic_fetch_sub(obj, arg) \ - __atomic_fetch_sub(obj, arg, __ATOMIC_SEQ_CST) -#define _Atomic -#else -#include -#endif diff --git a/quickjs-ng/quickjs-libc.h b/quickjs-ng/quickjs-libc.h deleted file mode 100644 index 6af5a63..0000000 --- a/quickjs-ng/quickjs-libc.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * QuickJS C library - * - * Copyright (c) 2017-2018 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef QUICKJS_LIBC_H -#define QUICKJS_LIBC_H - -#include -#include -#include - -#include "quickjs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__GNUC__) || defined(__clang__) -#define JS_EXTERN __attribute__((visibility("default"))) -#else -#define JS_EXTERN /* nothing */ -#endif - -JS_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx, - const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx, - const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx, - const char *module_name); -JS_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv); -JS_EXTERN int js_std_loop(JSContext *ctx); -JS_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj); -JS_EXTERN void js_std_init_handlers(JSRuntime *rt); -JS_EXTERN void js_std_free_handlers(JSRuntime *rt); -JS_EXTERN void js_std_dump_error(JSContext *ctx); -JS_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, - const char *filename); -JS_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, - bool use_realpath, bool is_main); -JS_EXTERN JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque); -JS_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, - size_t buf_len, int flags); -JS_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx, - JSValueConst promise, - JSValueConst reason, - bool is_handled, - void *opaque); -JS_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); - -#undef JS_EXTERN - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* QUICKJS_LIBC_H */ diff --git a/quickjs-ng/quickjs.h b/quickjs-ng/quickjs.h deleted file mode 100644 index ddae1e5..0000000 --- a/quickjs-ng/quickjs.h +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * QuickJS Javascript Engine - * - * Copyright (c) 2017-2024 Fabrice Bellard - * Copyright (c) 2017-2024 Charlie Gordon - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef QUICKJS_H -#define QUICKJS_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define QUICKJS_NG 1 - -#if defined(__GNUC__) || defined(__clang__) -#define js_force_inline inline __attribute__((always_inline)) -#define JS_EXTERN __attribute__((visibility("default"))) -#else -#define js_force_inline inline -#define JS_EXTERN /* nothing */ -#endif - -/* Borrowed from Folly */ -#ifndef JS_PRINTF_FORMAT -#ifdef _MSC_VER -#include -#define JS_PRINTF_FORMAT _Printf_format_string_ -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) -#else -#define JS_PRINTF_FORMAT -#if !defined(__clang__) && defined(__GNUC__) -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ - __attribute__((format(gnu_printf, format_param, dots_param))) -#else -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ - __attribute__((format(printf, format_param, dots_param))) -#endif -#endif -#endif - -typedef struct JSRuntime JSRuntime; -typedef struct JSContext JSContext; -typedef struct JSObject JSObject; -typedef struct JSClass JSClass; -typedef uint32_t JSClassID; -typedef uint32_t JSAtom; - -/* Unless documented otherwise, C string pointers (`char *` or `const char *`) - are assumed to verify these constraints: - - unless a length is passed separately, the string has a null terminator - - string contents is either pure ASCII or is UTF-8 encoded. - */ - -/* Overridable purely for testing purposes; don't touch. */ -#ifndef JS_NAN_BOXING -#if INTPTR_MAX < INT64_MAX -#define JS_NAN_BOXING 1 /* Use NAN boxing for 32bit builds. */ -#endif -#endif - -enum { - /* all tags with a reference count are negative */ - JS_TAG_FIRST = -9, /* first negative tag */ - JS_TAG_BIG_INT = -9, - JS_TAG_SYMBOL = -8, - JS_TAG_STRING = -7, - JS_TAG_MODULE = -3, /* used internally */ - JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ - JS_TAG_OBJECT = -1, - - JS_TAG_INT = 0, - JS_TAG_BOOL = 1, - JS_TAG_NULL = 2, - JS_TAG_UNDEFINED = 3, - JS_TAG_UNINITIALIZED = 4, - JS_TAG_CATCH_OFFSET = 5, - JS_TAG_EXCEPTION = 6, - JS_TAG_SHORT_BIG_INT = 7, - JS_TAG_FLOAT64 = 8, - /* any larger tag is FLOAT64 if JS_NAN_BOXING */ -}; - -#if !defined(JS_CHECK_JSVALUE) -#define JSValueConst JSValue -#endif - -// JS_CHECK_JSVALUE build mode does not produce working code but is here to -// help catch reference counting bugs at compile time, by making it harder -// to mix up JSValue and JSValueConst -// -// rules: -// -// - a function with a JSValue parameter takes ownership; -// caller must *not* call JS_FreeValue -// -// - a function with a JSValueConst parameter does not take ownership; -// caller *must* call JS_FreeValue -// -// - a function returning a JSValue transfers ownership to caller; -// caller *must* call JS_FreeValue -// -// - a function returning a JSValueConst does *not* transfer ownership; -// caller must *not* call JS_FreeValue -#if defined(JS_CHECK_JSVALUE) - -typedef struct JSValue *JSValue; -typedef const struct JSValue *JSValueConst; - -#define JS_MKVAL(tag, val) ((JSValue)((tag) | (intptr_t)(val) << 4)) -#define JS_MKPTR(tag, ptr) ((JSValue)((tag) | (intptr_t)(ptr))) -#define JS_VALUE_GET_NORM_TAG(v) ((int)((intptr_t)(v) & 15)) -#define JS_VALUE_GET_TAG(v) ((int)((intptr_t)(v) & 15)) -#define JS_VALUE_GET_SHORT_BIG_INT(v) JS_VALUE_GET_INT(v) -#define JS_VALUE_GET_PTR(v) ((void *)((intptr_t)(v) & ~15)) -#define JS_VALUE_GET_INT(v) ((int)((intptr_t)(v) >> 4)) -#define JS_VALUE_GET_BOOL(v) ((int)((intptr_t)(v) >> 4)) -#define JS_VALUE_GET_FLOAT64(v) ((double)((intptr_t)(v) >> 4)) -#define JS_TAG_IS_FLOAT64(tag) ((int)(tag) == JS_TAG_FLOAT64) -#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 0) - -static inline JSValue __JS_NewFloat64(double d) -{ - return JS_MKVAL(JS_TAG_FLOAT64, (int)d); -} - -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); -} - -static inline bool JS_VALUE_IS_NAN(JSValue v) -{ - (void)&v; - return false; -} - -#elif defined(JS_NAN_BOXING) && JS_NAN_BOXING - -typedef uint64_t JSValue; - -#define JS_VALUE_GET_TAG(v) (int)((v) >> 32) -#define JS_VALUE_GET_INT(v) (int)(v) -#define JS_VALUE_GET_BOOL(v) (int)(v) -#define JS_VALUE_GET_SHORT_BIG_INT(v) (int)(v) -#define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v) - -#define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val)) -#define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr)) - -#define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */ - -static inline double JS_VALUE_GET_FLOAT64(JSValue v) -{ - union { - JSValue v; - double d; - } u; - u.v = v; - u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32; - return u.d; -} - -#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) - -static inline JSValue __JS_NewFloat64(double d) -{ - union { - double d; - uint64_t u64; - } u; - JSValue v; - u.d = d; - /* normalize NaN */ - if ((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000) - v = JS_NAN; - else - v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); - return v; -} - -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); -} - -#define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) - -/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ -static inline int JS_VALUE_GET_NORM_TAG(JSValue v) -{ - uint32_t tag; - tag = JS_VALUE_GET_TAG(v); - if (JS_TAG_IS_FLOAT64(tag)) - return JS_TAG_FLOAT64; - else - return tag; -} - -static inline bool JS_VALUE_IS_NAN(JSValue v) -{ - uint32_t tag; - tag = JS_VALUE_GET_TAG(v); - return tag == (JS_NAN >> 32); -} - -#else /* !JS_NAN_BOXING */ - -typedef union JSValueUnion { - int32_t int32; - double float64; - void *ptr; - int32_t short_big_int; -} JSValueUnion; - -typedef struct JSValue { - JSValueUnion u; - int64_t tag; -} JSValue; - -#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) -/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ -#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) -#define JS_VALUE_GET_INT(v) ((v).u.int32) -#define JS_VALUE_GET_BOOL(v) ((v).u.int32) -#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) -#define JS_VALUE_GET_SHORT_BIG_INT(v) ((v).u.short_big_int) -#define JS_VALUE_GET_PTR(v) ((v).u.ptr) - -/* msvc doesn't understand designated initializers without /std:c++20 */ -#ifdef __cplusplus -static inline JSValue JS_MKPTR(int64_t tag, void *ptr) -{ - JSValue v; - v.u.ptr = ptr; - v.tag = tag; - return v; -} -static inline JSValue JS_MKVAL(int64_t tag, int32_t int32) -{ - JSValue v; - v.u.int32 = int32; - v.tag = tag; - return v; -} -static inline JSValue JS_MKNAN(void) -{ - JSValue v; - v.u.float64 = NAN; - v.tag = JS_TAG_FLOAT64; - return v; -} -/* provide as macros for consistency and backward compat reasons */ -#define JS_MKPTR(tag, ptr) JS_MKPTR(tag, ptr) -#define JS_MKVAL(tag, val) JS_MKVAL(tag, val) -#define JS_NAN JS_MKNAN() /* alas, not a constant expression */ -#else -#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } -#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } -#define JS_NAN (JSValue){ (JSValueUnion){ .float64 = NAN }, JS_TAG_FLOAT64 } -#endif - -#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) - -static inline JSValue __JS_NewFloat64(double d) -{ - JSValue v; - v.tag = JS_TAG_FLOAT64; - v.u.float64 = d; - return v; -} - -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int64_t d) -{ - (void)&ctx; - JSValue v; - v.tag = JS_TAG_SHORT_BIG_INT; - v.u.short_big_int = d; - return v; -} - -static inline bool JS_VALUE_IS_NAN(JSValue v) -{ - union { - double d; - uint64_t u64; - } u; - if (v.tag != JS_TAG_FLOAT64) - return 0; - u.d = v.u.float64; - return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000; -} - -#endif /* !JS_NAN_BOXING */ - -#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) -#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) - -#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) -#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) - -/* special values */ -#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0) -#define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0) -#define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0) -#define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1) -#define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) -#define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) - -/* flags for object properties */ -#define JS_PROP_CONFIGURABLE (1 << 0) -#define JS_PROP_WRITABLE (1 << 1) -#define JS_PROP_ENUMERABLE (1 << 2) -#define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) -#define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */ -#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ -#define JS_PROP_NORMAL (0 << 4) -#define JS_PROP_GETSET (1 << 4) -#define JS_PROP_VARREF (2 << 4) /* used internally */ -#define JS_PROP_AUTOINIT (3 << 4) /* used internally */ - -/* flags for JS_DefineProperty */ -#define JS_PROP_HAS_SHIFT 8 -#define JS_PROP_HAS_CONFIGURABLE (1 << 8) -#define JS_PROP_HAS_WRITABLE (1 << 9) -#define JS_PROP_HAS_ENUMERABLE (1 << 10) -#define JS_PROP_HAS_GET (1 << 11) -#define JS_PROP_HAS_SET (1 << 12) -#define JS_PROP_HAS_VALUE (1 << 13) - -/* throw an exception if false would be returned - (JS_DefineProperty/JS_SetProperty) */ -#define JS_PROP_THROW (1 << 14) -/* throw an exception if false would be returned in strict mode - (JS_SetProperty) */ -#define JS_PROP_THROW_STRICT (1 << 15) - -#define JS_PROP_NO_ADD (1 << 16) /* internal use */ -#define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */ -#define JS_PROP_DEFINE_PROPERTY (1 << 18) /* internal use */ -#define JS_PROP_REFLECT_DEFINE_PROPERTY (1 << 19) /* internal use */ - -#ifndef JS_DEFAULT_STACK_SIZE -#define JS_DEFAULT_STACK_SIZE (1024 * 1024) -#endif - -/* JS_Eval() flags */ -#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */ -#define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */ -#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */ -#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ -#define JS_EVAL_TYPE_MASK (3 << 0) - -#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ -#define JS_EVAL_FLAG_UNUSED (1 << 4) /* unused */ -/* compile but do not run. The result is an object with a - JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed - with JS_EvalFunction(). */ -#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) -/* don't include the stack frames before this eval in the Error() backtraces */ -#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6) -/* allow top-level await in normal script. JS_Eval() returns a - promise. Only allowed with JS_EVAL_TYPE_GLOBAL */ -#define JS_EVAL_FLAG_ASYNC (1 << 7) - -typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); -typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); -typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValueConst *func_data); - -typedef struct JSMallocFunctions { - void *(*js_calloc)(void *opaque, size_t count, size_t size); - void *(*js_malloc)(void *opaque, size_t size); - void (*js_free)(void *opaque, void *ptr); - void *(*js_realloc)(void *opaque, void *ptr, size_t size); - size_t (*js_malloc_usable_size)(const void *ptr); -} JSMallocFunctions; - -// Debug trace system: the debug output will be produced to the dump stream (currently -// stdout) if dumps are enabled and JS_SetDumpFlags is invoked with the corresponding -// bit set. -#define JS_DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */ -#define JS_DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */ -#define JS_DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */ -#define JS_DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */ -#define JS_DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */ -#define JS_DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */ -#define JS_DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */ -#define JS_DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */ -#define JS_DUMP_FREE 0x200 /* dump every object free */ -#define JS_DUMP_GC 0x400 /* dump the occurrence of the automatic GC */ -#define JS_DUMP_GC_FREE 0x800 /* dump objects freed by the GC */ -#define JS_DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */ -#define JS_DUMP_PROMISE 0x2000 /* dump promise steps */ -#define JS_DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */ -#define JS_DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */ -#define JS_DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */ -#define JS_DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ -#define JS_DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ -#define JS_DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ - -// Finalizers run in LIFO order at the very end of JS_FreeRuntime. -// Intended for cleanup of associated resources; the runtime itself -// is no longer usable. -typedef void JSRuntimeFinalizer(JSRuntime *rt, void *arg); - -typedef struct JSGCObjectHeader JSGCObjectHeader; - -JS_EXTERN JSRuntime *JS_NewRuntime(void); -/* info lifetime must exceed that of rt */ -JS_EXTERN void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); -/* use 0 to disable memory limit */ -JS_EXTERN void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); -JS_EXTERN void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags); -JS_EXTERN uint64_t JS_GetDumpFlags(JSRuntime *rt); -JS_EXTERN size_t JS_GetGCThreshold(JSRuntime *rt); -JS_EXTERN void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); -/* use 0 to disable maximum stack size check */ -JS_EXTERN void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); -/* should be called when changing thread to update the stack top value - used to check stack overflow. */ -JS_EXTERN void JS_UpdateStackTop(JSRuntime *rt); -JS_EXTERN JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); -JS_EXTERN void JS_FreeRuntime(JSRuntime *rt); -JS_EXTERN void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)); -JS_EXTERN void *JS_GetRuntimeOpaque(JSRuntime *rt); -JS_EXTERN void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); -JS_EXTERN int JS_AddRuntimeFinalizer(JSRuntime *rt, - JSRuntimeFinalizer *finalizer, void *arg); -typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp); -JS_EXTERN void JS_MarkValue(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -JS_EXTERN void JS_RunGC(JSRuntime *rt); -JS_EXTERN bool JS_IsLiveObject(JSRuntime *rt, JSValueConst obj); - -JS_EXTERN JSContext *JS_NewContext(JSRuntime *rt); -JS_EXTERN void JS_FreeContext(JSContext *s); -JS_EXTERN JSContext *JS_DupContext(JSContext *ctx); -JS_EXTERN void *JS_GetContextOpaque(JSContext *ctx); -JS_EXTERN void JS_SetContextOpaque(JSContext *ctx, void *opaque); -JS_EXTERN JSRuntime *JS_GetRuntime(JSContext *ctx); -JS_EXTERN void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); -JS_EXTERN JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); -JS_EXTERN JSValue JS_GetFunctionProto(JSContext *ctx); - -/* the following functions are used to select the intrinsic object to - save memory */ -JS_EXTERN JSContext *JS_NewContextRaw(JSRuntime *rt); -JS_EXTERN void JS_AddIntrinsicBaseObjects(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicDate(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicEval(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicRegExp(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicJSON(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicProxy(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicMapSet(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicTypedArrays(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicPromise(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicBigInt(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicWeakRef(JSContext *ctx); -JS_EXTERN void JS_AddPerformance(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicDOMException(JSContext *ctx); - -/* for equality comparisons and sameness */ -JS_EXTERN int JS_IsEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2); -JS_EXTERN bool JS_IsStrictEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2); -JS_EXTERN bool JS_IsSameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2); -/* Similar to same-value equality, but +0 and -0 are considered equal. */ -JS_EXTERN bool JS_IsSameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2); - -/* Only used for running 262 tests. TODO(saghul) add build time flag. */ -JS_EXTERN JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); - -JS_EXTERN void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size); -JS_EXTERN void *js_malloc_rt(JSRuntime *rt, size_t size); -JS_EXTERN void js_free_rt(JSRuntime *rt, void *ptr); -JS_EXTERN void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); -JS_EXTERN size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); -JS_EXTERN void *js_mallocz_rt(JSRuntime *rt, size_t size); - -JS_EXTERN void *js_calloc(JSContext *ctx, size_t count, size_t size); -JS_EXTERN void *js_malloc(JSContext *ctx, size_t size); -JS_EXTERN void js_free(JSContext *ctx, void *ptr); -JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size); -JS_EXTERN size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); -JS_EXTERN void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); -JS_EXTERN void *js_mallocz(JSContext *ctx, size_t size); -JS_EXTERN char *js_strdup(JSContext *ctx, const char *str); -JS_EXTERN char *js_strndup(JSContext *ctx, const char *s, size_t n); - -typedef struct JSMemoryUsage { - int64_t malloc_size, malloc_limit, memory_used_size; - int64_t malloc_count; - int64_t memory_used_count; - int64_t atom_count, atom_size; - int64_t str_count, str_size; - int64_t obj_count, obj_size; - int64_t prop_count, prop_size; - int64_t shape_count, shape_size; - int64_t js_func_count, js_func_size, js_func_code_size; - int64_t js_func_pc2line_count, js_func_pc2line_size; - int64_t c_func_count, array_count; - int64_t fast_array_count, fast_array_elements; - int64_t binary_object_count, binary_object_size; -} JSMemoryUsage; - -JS_EXTERN void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); -JS_EXTERN void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); - -/* atom support */ -#define JS_ATOM_NULL 0 - -JS_EXTERN JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); -JS_EXTERN JSAtom JS_NewAtom(JSContext *ctx, const char *str); -JS_EXTERN JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); -JS_EXTERN JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); -JS_EXTERN void JS_FreeAtom(JSContext *ctx, JSAtom v); -JS_EXTERN void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); -JS_EXTERN JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); -JS_EXTERN JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); -JS_EXTERN const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom); -static inline const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) -{ - return JS_AtomToCStringLen(ctx, NULL, atom); -} -JS_EXTERN JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); - -/* object class support */ - -typedef struct JSPropertyEnum { - bool is_enumerable; - JSAtom atom; -} JSPropertyEnum; - -typedef struct JSPropertyDescriptor { - int flags; - JSValue value; - JSValue getter; - JSValue setter; -} JSPropertyDescriptor; - -typedef struct JSClassExoticMethods { - /* Return -1 if exception (can only happen in case of Proxy object), - false if the property does not exists, true if it exists. If 1 is - returned, the property descriptor 'desc' is filled if != NULL. */ - int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); - /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, - -1 if exception. The 'is_enumerable' field is ignored. - */ - int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, JSValueConst obj); - /* return < 0 if exception, or true/false */ - int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); - /* return < 0 if exception or true/false */ - int (*define_own_property)(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags); - /* The following methods can be emulated with the previous ones, - so they are usually not needed */ - /* return < 0 if exception or true/false */ - int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom); - JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst receiver); - /* return < 0 if exception or true/false */ - int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst value, JSValueConst receiver, int flags); -} JSClassExoticMethods; - -typedef void JSClassFinalizer(JSRuntime *rt, JSValueConst val); -typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -#define JS_CALL_FLAG_CONSTRUCTOR (1 << 0) -typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_val, int argc, - JSValueConst *argv, int flags); - -typedef struct JSClassDef { - const char *class_name; /* pure ASCII only! */ - JSClassFinalizer *finalizer; - JSClassGCMark *gc_mark; - /* if call != NULL, the object is a function. If (flags & - JS_CALL_FLAG_CONSTRUCTOR) != 0, the function is called as a - constructor. In this case, 'this_val' is new.target. A - constructor call only happens if the object constructor bit is - set (see JS_SetConstructorBit()). */ - JSClassCall *call; - /* XXX: suppress this indirection ? It is here only to save memory - because only a few classes need these methods */ - JSClassExoticMethods *exotic; -} JSClassDef; - -#define JS_EVAL_OPTIONS_VERSION 1 - -typedef struct JSEvalOptions { - int version; - int eval_flags; - const char *filename; - int line_num; - // can add new fields in ABI-compatible manner by incrementing JS_EVAL_OPTIONS_VERSION -} JSEvalOptions; - -#define JS_INVALID_CLASS_ID 0 -JS_EXTERN JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id); -/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */ -JS_EXTERN JSClassID JS_GetClassID(JSValueConst v); -JS_EXTERN int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); -JS_EXTERN bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); - -/* value handling */ - -static js_force_inline JSValue JS_NewBool(JSContext *ctx, bool val) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_BOOL, (val != 0)); -} - -static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_INT, val); -} - -static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double val) -{ - (void)&ctx; - return __JS_NewFloat64(val); -} - -static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); -} - -static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) -{ - JSValue v; - if (val >= INT32_MIN && val <= INT32_MAX) { - v = JS_NewInt32(ctx, (int32_t)val); - } else { - v = JS_NewFloat64(ctx, (double)val); - } - return v; -} - -static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) -{ - JSValue v; - if (val <= INT32_MAX) { - v = JS_NewInt32(ctx, (int32_t)val); - } else { - v = JS_NewFloat64(ctx, (double)val); - } - return v; -} - -JS_EXTERN JSValue JS_NewNumber(JSContext *ctx, double d); -JS_EXTERN JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); -JS_EXTERN JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); - -static inline bool JS_IsNumber(JSValueConst v) -{ - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); -} - -static inline bool JS_IsBigInt(JSValueConst v) -{ - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT; -} - -static inline bool JS_IsBool(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; -} - -static inline bool JS_IsNull(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; -} - -static inline bool JS_IsUndefined(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; -} - -static inline bool JS_IsException(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION; -} - -static inline bool JS_IsUninitialized(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED; -} - -static inline bool JS_IsString(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; -} - -static inline bool JS_IsSymbol(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; -} - -static inline bool JS_IsObject(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; -} - -static inline bool JS_IsModule(JSValueConst v) -{ - return JS_VALUE_GET_TAG(v) == JS_TAG_MODULE; -} - -JS_EXTERN JSValue JS_Throw(JSContext *ctx, JSValue obj); -JS_EXTERN JSValue JS_GetException(JSContext *ctx); -JS_EXTERN bool JS_HasException(JSContext *ctx); -JS_EXTERN bool JS_IsError(JSContext *ctx, JSValueConst val); -JS_EXTERN bool JS_IsUncatchableError(JSContext* ctx, JSValueConst val); -JS_EXTERN void JS_SetUncatchableError(JSContext *ctx, JSValueConst val); -JS_EXTERN void JS_ClearUncatchableError(JSContext *ctx, JSValueConst val); -// Shorthand for: -// JSValue exc = JS_GetException(ctx); -// JS_ClearUncatchableError(ctx, exc); -// JS_Throw(ctx, exc); -JS_EXTERN void JS_ResetUncatchableError(JSContext *ctx); -JS_EXTERN JSValue JS_NewError(JSContext *ctx); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_NewTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowDOMException(JSContext *ctx, const char *name, JS_PRINTF_FORMAT const char *fmt, ...); -JS_EXTERN JSValue JS_ThrowOutOfMemory(JSContext *ctx); -JS_EXTERN void JS_FreeValue(JSContext *ctx, JSValue v); -JS_EXTERN void JS_FreeValueRT(JSRuntime *rt, JSValue v); -JS_EXTERN JSValue JS_DupValue(JSContext *ctx, JSValueConst v); -JS_EXTERN JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v); -JS_EXTERN int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ -static inline JSValue JS_ToBoolean(JSContext *ctx, JSValueConst val) -{ - return JS_NewBool(ctx, JS_ToBool(ctx, val)); -} -JS_EXTERN JSValue JS_ToNumber(JSContext *ctx, JSValueConst val); -JS_EXTERN int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); -static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) -{ - return JS_ToInt32(ctx, (int32_t*)pres, val); -} -JS_EXTERN int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val); -JS_EXTERN int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val); -JS_EXTERN int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val); -/* return an exception if 'val' is a Number */ -JS_EXTERN int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); -JS_EXTERN int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValueConst val); -/* same as JS_ToInt64() but allow BigInt */ -JS_EXTERN int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val); - -JS_EXTERN JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); -static inline JSValue JS_NewString(JSContext *ctx, const char *str) { - return JS_NewStringLen(ctx, str, strlen(str)); -} -// makes a copy of the input; does not check if the input is valid UTF-16, -// that is the responsibility of the caller -JS_EXTERN JSValue JS_NewTwoByteString(JSContext *ctx, const uint16_t *buf, - size_t len); -JS_EXTERN JSValue JS_NewAtomString(JSContext *ctx, const char *str); -JS_EXTERN JSValue JS_ToString(JSContext *ctx, JSValueConst val); -JS_EXTERN JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); -JS_EXTERN const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, bool cesu8); -static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1) -{ - return JS_ToCStringLen2(ctx, plen, val1, 0); -} -static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) -{ - return JS_ToCStringLen2(ctx, NULL, val1, 0); -} -JS_EXTERN void JS_FreeCString(JSContext *ctx, const char *ptr); - -JS_EXTERN JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, - JSClassID class_id); -JS_EXTERN JSValue JS_NewObjectClass(JSContext *ctx, JSClassID class_id); -JS_EXTERN JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto); -JS_EXTERN JSValue JS_NewObject(JSContext *ctx); -// takes ownership of the values -JS_EXTERN JSValue JS_NewObjectFrom(JSContext *ctx, int count, - const JSAtom *props, - const JSValue *values); -// takes ownership of the values -JS_EXTERN JSValue JS_NewObjectFromStr(JSContext *ctx, int count, - const char **props, - const JSValue *values); -JS_EXTERN JSValue JS_ToObject(JSContext *ctx, JSValueConst val); -JS_EXTERN JSValue JS_ToObjectString(JSContext *ctx, JSValueConst val); - -JS_EXTERN bool JS_IsFunction(JSContext* ctx, JSValueConst val); -JS_EXTERN bool JS_IsConstructor(JSContext* ctx, JSValueConst val); -JS_EXTERN bool JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, bool val); - -JS_EXTERN bool JS_IsRegExp(JSValueConst val); -JS_EXTERN bool JS_IsMap(JSValueConst val); -JS_EXTERN bool JS_IsSet(JSValueConst val); -JS_EXTERN bool JS_IsWeakRef(JSValueConst val); -JS_EXTERN bool JS_IsWeakSet(JSValueConst val); -JS_EXTERN bool JS_IsWeakMap(JSValueConst val); -JS_EXTERN bool JS_IsDataView(JSValueConst val); - -JS_EXTERN JSValue JS_NewArray(JSContext *ctx); -// takes ownership of the values -JS_EXTERN JSValue JS_NewArrayFrom(JSContext *ctx, int count, - const JSValue *values); -// reader beware: JS_IsArray used to "punch" through proxies and check -// if the target object is an array but it no longer does; use JS_IsProxy -// and JS_GetProxyTarget instead, and remember that the target itself can -// also be a proxy, ad infinitum -JS_EXTERN bool JS_IsArray(JSValueConst val); - -JS_EXTERN bool JS_IsProxy(JSValueConst val); -JS_EXTERN JSValue JS_GetProxyTarget(JSContext *ctx, JSValueConst proxy); -JS_EXTERN JSValue JS_GetProxyHandler(JSContext *ctx, JSValueConst proxy); - -JS_EXTERN JSValue JS_NewDate(JSContext *ctx, double epoch_ms); -JS_EXTERN bool JS_IsDate(JSValueConst v); - -JS_EXTERN JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); -JS_EXTERN JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx); -JS_EXTERN JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst this_obj, - int64_t idx); -JS_EXTERN JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop); - -JS_EXTERN int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val); -JS_EXTERN int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val); -JS_EXTERN int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, - int64_t idx, JSValue val); -JS_EXTERN int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val); -JS_EXTERN int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); -JS_EXTERN int JS_IsExtensible(JSContext *ctx, JSValueConst obj); -JS_EXTERN int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); -JS_EXTERN int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); -JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValue proto_val); -JS_EXTERN JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); -JS_EXTERN int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres); -JS_EXTERN int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len); -JS_EXTERN int JS_SealObject(JSContext *ctx, JSValueConst obj); -JS_EXTERN int JS_FreezeObject(JSContext *ctx, JSValueConst obj); - -#define JS_GPN_STRING_MASK (1 << 0) -#define JS_GPN_SYMBOL_MASK (1 << 1) -#define JS_GPN_PRIVATE_MASK (1 << 2) -/* only include the enumerable properties */ -#define JS_GPN_ENUM_ONLY (1 << 4) -/* set theJSPropertyEnum.is_enumerable field */ -#define JS_GPN_SET_ENUM (1 << 5) - -JS_EXTERN int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, JSValueConst obj, - int flags); -JS_EXTERN int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); -JS_EXTERN void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, - uint32_t len); - -JS_EXTERN JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, int argc, JSValueConst *argv); -JS_EXTERN JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, - int argc, JSValueConst *argv); -JS_EXTERN JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, - int argc, JSValueConst *argv); -JS_EXTERN JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, - JSValueConst new_target, - int argc, JSValueConst *argv); -/* Try to detect if the input is a module. Returns true if parsing the input - * as a module produces no syntax errors. It's a naive approach that is not - * wholly infallible: non-strict classic scripts may _parse_ okay as a module - * but not _execute_ as one (different runtime semantics.) Use with caution. - * |input| can be either ASCII or UTF-8 encoded source code. - * Returns false if QuickJS was built with -DQJS_DISABLE_PARSER. - */ -JS_EXTERN bool JS_DetectModule(const char *input, size_t input_len); -/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ -JS_EXTERN JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, - const char *filename, int eval_flags); -JS_EXTERN JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len, - JSEvalOptions *options); -JS_EXTERN JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, - const char *input, size_t input_len, - const char *filename, int eval_flags); -JS_EXTERN JSValue JS_EvalThis2(JSContext *ctx, JSValueConst this_obj, - const char *input, size_t input_len, - JSEvalOptions *options); -JS_EXTERN JSValue JS_GetGlobalObject(JSContext *ctx); -JS_EXTERN int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); -JS_EXTERN int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags); -JS_EXTERN int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val, int flags); -JS_EXTERN int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val, int flags); -JS_EXTERN int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val, int flags); -JS_EXTERN int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue getter, JSValue setter, - int flags); -/* Only supported for custom classes, returns 0 on success < 0 otherwise. */ -JS_EXTERN int JS_SetOpaque(JSValueConst obj, void *opaque); -JS_EXTERN void *JS_GetOpaque(JSValueConst obj, JSClassID class_id); -JS_EXTERN void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); -JS_EXTERN void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id); - -/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ -JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, - const char *filename); -JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, - JSValueConst replacer, JSValueConst space0); - -typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); -JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared); -JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); -JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); -JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); -JS_EXTERN bool JS_IsArrayBuffer(JSValueConst obj); -JS_EXTERN uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValueConst obj); - -typedef enum JSTypedArrayEnum { - JS_TYPED_ARRAY_UINT8C = 0, - JS_TYPED_ARRAY_INT8, - JS_TYPED_ARRAY_UINT8, - JS_TYPED_ARRAY_INT16, - JS_TYPED_ARRAY_UINT16, - JS_TYPED_ARRAY_INT32, - JS_TYPED_ARRAY_UINT32, - JS_TYPED_ARRAY_BIG_INT64, - JS_TYPED_ARRAY_BIG_UINT64, - JS_TYPED_ARRAY_FLOAT16, - JS_TYPED_ARRAY_FLOAT32, - JS_TYPED_ARRAY_FLOAT64, -} JSTypedArrayEnum; - -JS_EXTERN JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, - JSTypedArrayEnum array_type); -JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, - size_t *pbyte_offset, - size_t *pbyte_length, - size_t *pbytes_per_element); -JS_EXTERN JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared); -/* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */ -JS_EXTERN int JS_GetTypedArrayType(JSValueConst obj); -JS_EXTERN JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len); -typedef struct { - void *(*sab_alloc)(void *opaque, size_t size); - void (*sab_free)(void *opaque, void *ptr); - void (*sab_dup)(void *opaque, void *ptr); - void *sab_opaque; -} JSSharedArrayBufferFunctions; -JS_EXTERN void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf); - -typedef enum JSPromiseStateEnum { - JS_PROMISE_PENDING, - JS_PROMISE_FULFILLED, - JS_PROMISE_REJECTED, -} JSPromiseStateEnum; - -JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); -JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, - JSValueConst promise); -JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise); -JS_EXTERN bool JS_IsPromise(JSValueConst val); - -JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global); - -typedef enum JSPromiseHookType { - JS_PROMISE_HOOK_INIT, // emitted when a new promise is created - JS_PROMISE_HOOK_BEFORE, // runs right before promise.then is invoked - JS_PROMISE_HOOK_AFTER, // runs right after promise.then is invoked - JS_PROMISE_HOOK_RESOLVE, // not emitted for rejected promises -} JSPromiseHookType; - -// parent_promise is only passed in when type == JS_PROMISE_HOOK_INIT and -// is then either a promise object or JS_UNDEFINED if the new promise does -// not have a parent promise; only promises created with promise.then have -// a parent promise -typedef void JSPromiseHook(JSContext *ctx, JSPromiseHookType type, - JSValueConst promise, JSValueConst parent_promise, - void *opaque); -JS_EXTERN void JS_SetPromiseHook(JSRuntime *rt, JSPromiseHook promise_hook, - void *opaque); - -/* is_handled = true means that the rejection is handled */ -typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, - bool is_handled, void *opaque); -JS_EXTERN void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); - -/* return != 0 if the JS code needs to be interrupted */ -typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); -JS_EXTERN void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); -/* if can_block is true, Atomics.wait() can be used */ -JS_EXTERN void JS_SetCanBlock(JSRuntime *rt, bool can_block); -/* set the [IsHTMLDDA] internal slot */ -JS_EXTERN void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj); - -typedef struct JSModuleDef JSModuleDef; - -/* return the module specifier (allocated with js_malloc()) or NULL if - exception */ -typedef char *JSModuleNormalizeFunc(JSContext *ctx, - const char *module_base_name, - const char *module_name, void *opaque); -typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, - const char *module_name, void *opaque); - -/* module_normalize = NULL is allowed and invokes the default module - filename normalizer */ -JS_EXTERN void JS_SetModuleLoaderFunc(JSRuntime *rt, - JSModuleNormalizeFunc *module_normalize, - JSModuleLoaderFunc *module_loader, void *opaque); -/* return the import.meta object of a module */ -JS_EXTERN JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); -JS_EXTERN JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); -JS_EXTERN JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m); - -/* JS Job support */ - -typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); -JS_EXTERN int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, - int argc, JSValueConst *argv); - -JS_EXTERN bool JS_IsJobPending(JSRuntime *rt); -JS_EXTERN int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); - -/* Structure to retrieve (de)serialized SharedArrayBuffer objects. */ -typedef struct JSSABTab { - uint8_t **tab; - size_t len; -} JSSABTab; - -/* Object Writer/Reader (currently only used to handle precompiled code) */ -#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */ -#define JS_WRITE_OBJ_BSWAP (0) /* byte swapped output (obsolete, handled transparently) */ -#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ -#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to encode arbitrary object graph */ -#define JS_WRITE_OBJ_STRIP_SOURCE (1 << 4) /* do not write source code information */ -#define JS_WRITE_OBJ_STRIP_DEBUG (1 << 5) /* do not write debug information */ -JS_EXTERN uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, int flags); -JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, - int flags, JSSABTab *psab_tab); - -#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */ -#define JS_READ_OBJ_ROM_DATA (0) /* avoid duplicating 'buf' data (obsolete, broken by ICs) */ -#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ -#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */ -JS_EXTERN JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); -JS_EXTERN JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags, JSSABTab *psab_tab); -/* instantiate and evaluate a bytecode function. Only used when - reading a script or module with JS_ReadObject() */ -JS_EXTERN JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); -/* load the dependencies of the module 'obj'. Useful when JS_ReadObject() - returns a module. */ -JS_EXTERN int JS_ResolveModule(JSContext *ctx, JSValueConst obj); - -/* only exported for os.Worker() */ -JS_EXTERN JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); -/* only exported for os.Worker() */ -JS_EXTERN JSValue JS_LoadModule(JSContext *ctx, const char *basename, - const char *filename); - -/* C function definition */ -typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ - JS_CFUNC_generic, - JS_CFUNC_generic_magic, - JS_CFUNC_constructor, - JS_CFUNC_constructor_magic, - JS_CFUNC_constructor_or_func, - JS_CFUNC_constructor_or_func_magic, - JS_CFUNC_f_f, - JS_CFUNC_f_f_f, - JS_CFUNC_getter, - JS_CFUNC_setter, - JS_CFUNC_getter_magic, - JS_CFUNC_setter_magic, - JS_CFUNC_iterator_next, -} JSCFunctionEnum; - -typedef union JSCFunctionType { - JSCFunction *generic; - JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); - JSCFunction *constructor; - JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); - JSCFunction *constructor_or_func; - double (*f_f)(double); - double (*f_f_f)(double, double); - JSValue (*getter)(JSContext *ctx, JSValueConst this_val); - JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); - JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); - JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); - JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int *pdone, int magic); -} JSCFunctionType; - -JS_EXTERN JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, - const char *name, - int length, JSCFunctionEnum cproto, int magic); -JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, - const char *name, - int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val); -JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, - int length, int magic, int data_len, - JSValueConst *data); - -static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, - const char *name, int length) -{ - return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0); -} - -static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, - const char *name, int length, - JSCFunctionEnum cproto, int magic) -{ - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft; - ft.generic_magic = func; - return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); -} -JS_EXTERN void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto); - -/* C property definition */ - -typedef struct JSCFunctionListEntry { - const char *name; /* pure ASCII or UTF-8 encoded */ - uint8_t prop_flags; - uint8_t def_type; - int16_t magic; - union { - struct { - uint8_t length; /* XXX: should move outside union */ - uint8_t cproto; /* XXX: should move outside union */ - JSCFunctionType cfunc; - } func; - struct { - JSCFunctionType get; - JSCFunctionType set; - } getset; - struct { - const char *name; - int base; - } alias; - struct { - const struct JSCFunctionListEntry *tab; - int len; - } prop_list; - const char *str; /* pure ASCII or UTF-8 encoded */ - int32_t i32; - int64_t i64; - uint64_t u64; - double f64; - } u; -} JSCFunctionListEntry; - -#define JS_DEF_CFUNC 0 -#define JS_DEF_CGETSET 1 -#define JS_DEF_CGETSET_MAGIC 2 -#define JS_DEF_PROP_STRING 3 -#define JS_DEF_PROP_INT32 4 -#define JS_DEF_PROP_INT64 5 -#define JS_DEF_PROP_DOUBLE 6 -#define JS_DEF_PROP_UNDEFINED 7 -#define JS_DEF_OBJECT 8 -#define JS_DEF_ALIAS 9 - -/* Note: c++ does not like nested designators */ -#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } -#define JS_CFUNC_DEF2(name, length, func1, prop_flags) { name, prop_flags, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } -#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } -#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } -#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } -#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } -#define JS_CGETSET_DEF2(name, fgetter, fsetter, prop_flags) { name, prop_flags, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } -#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } -#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, { .str = cstr } } -#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, { .i32 = val } } -#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, { .i64 = val } } -#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .f64 = val } } -#define JS_PROP_U2D_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .u64 = val } } -#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, { .i32 = 0 } } -#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, { .prop_list = { tab, len } } } -#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, -1 } } } -#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, base } } } - -JS_EXTERN int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, - const JSCFunctionListEntry *tab, - int len); - -/* C module definition */ - -typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); - -JS_EXTERN JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, - JSModuleInitFunc *func); -/* can only be called before the module is instantiated */ -JS_EXTERN int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); -JS_EXTERN int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, - const JSCFunctionListEntry *tab, int len); -/* can only be called after the module is instantiated */ -JS_EXTERN int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, - JSValue val); -JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, - const JSCFunctionListEntry *tab, int len); - -/* Version */ - -#define QJS_VERSION_MAJOR 0 -#define QJS_VERSION_MINOR 10 -#define QJS_VERSION_PATCH 1 -#define QJS_VERSION_SUFFIX "" - -JS_EXTERN const char* JS_GetVersion(void); - -/* Integration point for quickjs-libc.c, not for public use. */ -JS_EXTERN uintptr_t js_std_cmd(int cmd, ...); - -#undef JS_EXTERN -#undef js_force_inline - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* QUICKJS_H */ diff --git a/quickjs-ng/standalone.js b/quickjs-ng/standalone.js deleted file mode 100644 index 59dac95..0000000 --- a/quickjs-ng/standalone.js +++ /dev/null @@ -1,129 +0,0 @@ -import * as std from "qjs:std"; -import * as os from "qjs:os"; -import * as bjson from "qjs:bjson"; - -// See quickjs.h -const JS_READ_OBJ_BYTECODE = 1 << 0; -const JS_READ_OBJ_REFERENCE = 1 << 3; -const JS_WRITE_OBJ_BYTECODE = 1 << 0; -const JS_WRITE_OBJ_REFERENCE = 1 << 3; -const JS_WRITE_OBJ_STRIP_SOURCE = 1 << 4; - -/** - * Trailer for standalone binaries. When some code gets bundled with the qjs - * executable we add a 12 byte trailer. The first 8 bytes are the magic - * string that helps us understand this is a standalone binary, and the - * remaining 4 are the offset (from the beginning of the binary) where the - * bundled data is located. - * - * The offset is stored as a 32bit little-endian number. - */ -const Trailer = { - Magic: 'quickjs2', - MagicSize: 8, - DataSize: 4, - Size: 12 -}; - -function encodeAscii(txt) { - return new Uint8Array(txt.split('').map(c => c.charCodeAt(0))); -} - -function decodeAscii(buf) { - return Array.from(buf).map(c => String.fromCharCode(c)).join('') -} - -export function compileStandalone(inFile, outFile, targetExe) { - // Step 1: compile the source file to bytecode - const js = std.loadFile(inFile); - - if (!js) { - throw new Error(`failed to open ${inFile}`); - } - - const code = std.evalScript(js, { - compile_only: true, - compile_module: true - }); - const bytecode = new Uint8Array(bjson.write(code, JS_WRITE_OBJ_BYTECODE | JS_WRITE_OBJ_REFERENCE | JS_WRITE_OBJ_STRIP_SOURCE)); - - // Step 2: copy the bytecode to the end of the executable and add a marker. - const exeFileName = targetExe ?? os.exePath() ?? globalThis.argv0; - const exe = std.loadFile(exeFileName, { binary: true }); - - if (!exe) { - throw new Error(`failed to open executable: ${exeFileName}`); - } - - const exeSize = exe.length; - const newBuffer = exe.buffer.transfer(exeSize + bytecode.length + Trailer.Size); - const newExe = new Uint8Array(newBuffer); - - newExe.set(bytecode, exeSize); - newExe.set(encodeAscii(Trailer.Magic), exeSize + bytecode.length); - - const dw = new DataView(newBuffer, exeSize + bytecode.length + Trailer.MagicSize, Trailer.DataSize); - - dw.setUint32(0, exeSize, true /* little-endian */); - - // We use os.open() so we can set the permissions mask. - const newFd = os.open(outFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o755); - - if (newFd < 0) { - throw new Error(`failed to create ${outFile}`); - } - if (os.write(newFd, newBuffer, 0, newBuffer.byteLength) < 0) { - os.close(newFd); - throw new Error(`failed to write to output file`); - } - os.close(newFd); -} - -export function runStandalone() { - const file = os.exePath() ?? globalThis.argv0; - const exe = std.open(file, 'rb'); - - if (!exe) { - throw new Error(`failed to open executable: ${file}`); - } - - let r = exe.seek(-Trailer.Size, std.SEEK_END); - if (r < 0) { - throw new Error(`seek error: ${-r}`); - } - - const trailer = new Uint8Array(Trailer.Size); - - exe.read(trailer.buffer, 0, Trailer.Size); - - const magic = new Uint8Array(trailer.buffer, 0, Trailer.MagicSize); - - // Shouldn't happen since qjs.c checks for it. - if (decodeAscii(magic) !== Trailer.Magic) { - exe.close(); - throw new Error('corrupted binary, magic mismatch'); - } - - const dw = new DataView(trailer.buffer, Trailer.MagicSize, Trailer.DataSize); - const offset = dw.getUint32(0, true /* little-endian */); - const bytecode = new Uint8Array(offset - Trailer.Size); - - r = exe.seek(offset, std.SEEK_SET); - if (r < 0) { - exe.close(); - throw new Error(`seek error: ${-r}`); - } - - exe.read(bytecode.buffer, 0, bytecode.length); - if (exe.error()) { - exe.close(); - throw new Error('read error'); - } - exe.close(); - - const code = bjson.read(bytecode.buffer, 0, bytecode.length, JS_READ_OBJ_BYTECODE | JS_READ_OBJ_REFERENCE); - - return std.evalScript(code, { - eval_module: true - }); -} diff --git a/quickjs-ng/test262-fast.conf b/quickjs-ng/test262-fast.conf deleted file mode 100644 index ef36cee..0000000 --- a/quickjs-ng/test262-fast.conf +++ /dev/null @@ -1,132 +0,0 @@ -[exclude] -# list excluded tests and directories here for faster operation - -# lengthy constructed regexp (>500 ms) -test262/test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js -test262/test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js - -# slow notifications (> 600 ms) -test262/test/built-ins/Atomics/notify/notify-in-order-one-time.js -test262/test/built-ins/Atomics/notify/notify-in-order.js -test262/test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js -test262/test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js - -# lengthy constructed regexp (>200 ms) -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js -test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js -test262/test/built-ins/RegExp/character-class-escape-non-whitespace.js - -# 417 lengty tests with huge constructed regexp (>200 ms) -test262/test/built-ins/RegExp/property-escapes/generated/ - -# lengthy constructed URLS (>200 ms) -test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T1.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T2.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.10_T1.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T1.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T2.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T1.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T2.js -test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T3.js -test262/test/built-ins/decodeURI/S15.1.3.1_A2.5_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T2.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js - -# lengthy comment tests -test262/test/language/comments/S7.4_A5.js -test262/test/language/comments/S7.4_A6.js - -# lengthy unicode level tests -test262/test/language/identifiers/start-unicode-5.2.0-class-escaped.js -test262/test/language/identifiers/start-unicode-5.2.0-class.js -test262/test/language/identifiers/start-unicode-8.0.0-class-escaped.js -test262/test/language/identifiers/start-unicode-8.0.0-class.js -test262/test/language/identifiers/start-unicode-9.0.0-class-escaped.js -test262/test/language/identifiers/start-unicode-9.0.0-class.js -test262/test/language/identifiers/start-unicode-10.0.0-class-escaped.js -test262/test/language/identifiers/start-unicode-10.0.0-class.js -test262/test/language/identifiers/start-unicode-13.0.0-class-escaped.js -test262/test/language/identifiers/start-unicode-13.0.0-class.js -test262/test/language/identifiers/start-unicode-15.0.0-class-escaped.js -test262/test/language/identifiers/start-unicode-15.0.0-class.js - -# Atomics tests with 2 second delays -test262/test/built-ins/Atomics/notify/bigint/notify-all-on-loc.js -test262/test/built-ins/Atomics/notify/negative-count.js -test262/test/built-ins/Atomics/notify/notify-all-on-loc.js -test262/test/built-ins/Atomics/notify/notify-all.js -test262/test/built-ins/Atomics/notify/notify-nan.js -test262/test/built-ins/Atomics/notify/notify-one.js -test262/test/built-ins/Atomics/notify/notify-two.js -test262/test/built-ins/Atomics/notify/notify-zero.js - -# Atomics tests with 400 millisecond delays -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js -test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js -test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js - -# Atomics tests with 200 millisecond delays -test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js -test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js -test262/test/built-ins/Atomics/notify/notify-renotify-noop.js -test262/test/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js -test262/test/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js -test262/test/built-ins/Atomics/wait/bigint/nan-for-timeout.js -test262/test/built-ins/Atomics/wait/bigint/negative-timeout-agent.js -test262/test/built-ins/Atomics/wait/bigint/value-not-equal.js -test262/test/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js -test262/test/built-ins/Atomics/wait/false-for-timeout-agent.js -test262/test/built-ins/Atomics/wait/nan-for-timeout.js -test262/test/built-ins/Atomics/wait/negative-timeout-agent.js -test262/test/built-ins/Atomics/wait/null-for-timeout-agent.js -test262/test/built-ins/Atomics/wait/object-for-timeout-agent.js -test262/test/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js -test262/test/built-ins/Atomics/wait/symbol-for-index-throws-agent.js -test262/test/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js -test262/test/built-ins/Atomics/wait/symbol-for-value-throws-agent.js -test262/test/built-ins/Atomics/wait/true-for-timeout-agent.js -test262/test/built-ins/Atomics/wait/undefined-for-timeout.js -test262/test/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js -test262/test/built-ins/Atomics/wait/value-not-equal.js -test262/test/built-ins/Atomics/wait/wait-index-value-not-equal.js -test262/test/built-ins/Atomics/wait/was-woken-before-timeout.js - -# lengthy regexp literal construction (>500 ms) -test262/test/language/literals/regexp/S7.8.5_A1.1_T2.js -test262/test/language/literals/regexp/S7.8.5_A1.4_T2.js -test262/test/language/literals/regexp/S7.8.5_A2.1_T2.js -test262/test/language/literals/regexp/S7.8.5_A2.4_T2.js - -# lengthy built-ins tests (100-200 ms) -test262/test/built-ins/Function/prototype/toString/built-in-function-object.js -test262/test/built-ins/decodeURI/S15.1.3.1_A2.4_T1.js -test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.4_T1.js -test262/test/built-ins/encodeURI/S15.1.3.3_A2.3_T1.js -test262/test/built-ins/encodeURIComponent/S15.1.3.4_A2.3_T1.js -test262/test/language/expressions/dynamic-import/await-import-evaluation.js diff --git a/quickjs-ng/test262.conf b/quickjs-ng/test262.conf deleted file mode 100644 index 6f756f1..0000000 --- a/quickjs-ng/test262.conf +++ /dev/null @@ -1,396 +0,0 @@ -[config] -# general settings for test262 ES6 version - -# handle tests tagged as [noStrict]: yes, no, skip -nostrict=yes - -# handle tests tagged as [strictOnly]: yes, no, skip -strict=yes - -# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all -mode=default - -# handle tests flagged as [async]: yes, no, skip -# for these, load 'harness/doneprintHandle.js' prior to test -# and expect `print('Test262:AsyncTestComplete')` to be called for -# successful termination -async=yes - -# handle tests flagged as [module]: yes, no, skip -module=yes - -# output error messages: yes, no -verbose=yes - -# load harness files from this directory -harnessdir=test262/harness - -# names of harness include files to skip -#harnessexclude= - -# name of the error file for known errors -errorfile=test262_errors.txt - -# exclude tests enumerated in this file (see also [exclude] section) -#excludefile=test262_exclude.txt - -# enumerate tests from this directory -testdir=test262/test - -[features] -# Standard language features and proposed extensions -# list the features that are included -# skipped features are tagged as such to avoid warnings -# Keep this list alpha-sorted (:sort i in vim) - -__getter__ -__proto__ -__setter__ -AggregateError -align-detached-buffer-semantics-with-web-reality -arbitrary-module-namespace-names=skip -array-find-from-last -array-grouping -Array.fromAsync -Array.prototype.at -Array.prototype.flat -Array.prototype.flatMap -Array.prototype.includes -Array.prototype.values -ArrayBuffer -arraybuffer-transfer -arrow-function -async-functions -async-iteration -# atomics are broken in recent versions of tcc -Atomics=!tcc -Atomics.pause=!tcc -Atomics.waitAsync=skip -BigInt -caller -canonical-tz=skip -change-array-by-copy -class -class-fields-private -class-fields-private-in -class-fields-public -class-methods-private -class-static-block -class-static-fields-private -class-static-fields-public -class-static-methods-private -coalesce-expression -computed-property-names -const -cross-realm -DataView -DataView.prototype.getFloat32 -DataView.prototype.getFloat64 -DataView.prototype.getInt16 -DataView.prototype.getInt32 -DataView.prototype.getInt8 -DataView.prototype.getUint16 -DataView.prototype.getUint32 -DataView.prototype.setUint8 -decorators=skip -default-parameters -destructuring-assignment -destructuring-binding -dynamic-import -error-cause -Error.isError -explicit-resource-management=skip -exponentiation -export-star-as-namespace-from-module -FinalizationRegistry -Float16Array -Float32Array -Float64Array -for-in-order -for-of -generators -globalThis -hashbang -host-gc-required=skip -immutable-arraybuffer=skip -import-assertions=skip -import-attributes=skip -import-defer=skip -import.meta -Int16Array -Int32Array -Int8Array -Intl-enumeration=skip -intl-normative-optional=skip -Intl.DateTimeFormat-datetimestyle=skip -Intl.DateTimeFormat-dayPeriod=skip -Intl.DateTimeFormat-extend-timezonename=skip -Intl.DateTimeFormat-formatRange=skip -Intl.DateTimeFormat-fractionalSecondDigits=skip -Intl.DisplayNames-v2=skip -Intl.DisplayNames=skip -Intl.DurationFormat=skip -Intl.ListFormat=skip -Intl.Locale-info=skip -Intl.Locale=skip -Intl.NumberFormat-unified=skip -Intl.NumberFormat-v3=skip -Intl.RelativeTimeFormat=skip -Intl.Segmenter=skip -IsHTMLDDA -iterator-helpers -iterator-sequencing -json-modules=skip -json-parse-with-source=skip -json-superset -legacy-regexp=skip -let -logical-assignment-operators -Map -Math.sumPrecise -new.target -numeric-separator-literal -object-rest -object-spread -Object.fromEntries -Object.hasOwn -Object.is -optional-catch-binding -optional-chaining -Promise -promise-try -promise-with-resolvers -Promise.allSettled -Promise.any -Promise.prototype.finally -Proxy -proxy-missing-checks -Reflect -Reflect.construct -Reflect.set -Reflect.setPrototypeOf -regexp-dotall -regexp-duplicate-named-groups=skip -regexp-lookbehind -regexp-match-indices -regexp-modifiers=skip -regexp-named-groups -regexp-unicode-property-escapes -regexp-v-flag -RegExp.escape -resizable-arraybuffer -rest-parameters -Set -set-methods -ShadowRealm=skip -SharedArrayBuffer -source-phase-imports-module-source=skip -source-phase-imports=skip -string-trimming -String.fromCodePoint -String.prototype.at -String.prototype.endsWith -String.prototype.includes -String.prototype.isWellFormed -String.prototype.matchAll -String.prototype.replaceAll -String.prototype.toWellFormed -String.prototype.trimEnd -String.prototype.trimStart -super -Symbol -Symbol.asyncIterator -Symbol.hasInstance -Symbol.isConcatSpreadable -Symbol.iterator -Symbol.match -Symbol.matchAll -Symbol.prototype.description -Symbol.replace -Symbol.search -Symbol.species -Symbol.split -Symbol.toPrimitive -Symbol.toStringTag -Symbol.unscopables -symbols-as-weakmap-keys -tail-call-optimization=skip -template -Temporal=skip -top-level-await -TypedArray -TypedArray.prototype.at -u180e -Uint16Array -Uint32Array -Uint8Array -uint8array-base64=skip -Uint8ClampedArray -upsert -WeakMap -WeakRef -WeakSet -well-formed-json-stringify - -[exclude] -# list excluded tests and directories here - -# intl not supported -test262/test/intl402/ - -# incompatible with the "caller" feature -test262/test/built-ins/Function/prototype/restricted-property-caller.js -test262/test/built-ins/Function/prototype/restricted-property-arguments.js -test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js - -# slow tests -#test262/test/built-ins/RegExp/CharacterClassEscapes/ -#test262/test/built-ins/RegExp/property-escapes/ - -# in progress regexp-v-flag support, see https://github.com/quickjs-ng/quickjs/issues/228 -test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js -test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/character-union-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-13.1.js -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-14.0.js -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.0.js -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.1.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-string-literal.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-property-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-property-of-strings-escape.js -test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-string-literal.js - -# frequently broken, sometimes contain engine-dependent tests -test262/test/staging/ - -[tests] -# list test files or use config.testdir diff --git a/quickjs-ng/test262_errors.txt b/quickjs-ng/test262_errors.txt deleted file mode 100644 index 69224cc..0000000 --- a/quickjs-ng/test262_errors.txt +++ /dev/null @@ -1,92 +0,0 @@ -test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js:27: SyntaxError: invalid for in/of left hand-side -test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js:27: SyntaxError: invalid for in/of left hand-side -test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js:33: SyntaxError: invalid assignment left-hand side -test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js:27: SyntaxError: invalid increment/decrement operand -test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand -test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side -test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: strict mode: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: TypeError: $DONE() not called -test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: strict mode: TypeError: $DONE() not called -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34: RangeError: out-of-bound access -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34: strict mode: RangeError: out-of-bound access -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-resize-to-zero.js:33: RangeError: out-of-bound access -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-resize-to-zero.js:33: strict mode: RangeError: out-of-bound access -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared.js:35: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared.js:35: strict mode: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion.js:35: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion.js:35: strict mode: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/Atomics/wait/retrieve-length-before-index-coercion.js:38: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/Atomics/wait/retrieve-length-before-index-coercion.js:38: strict mode: Test262Error: Expected a RangeError but got a Test262Error -test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: SyntaxError: unknown unicode script -test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: strict mode: SyntaxError: unknown unicode script -test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag -test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: strict mode: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6) -test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6) -test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag -test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: strict mode: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag -test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents. -test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: strict mode: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents. -test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true -test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true -test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true -test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true -test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true -test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true -test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: strict mode: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: strict mode: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: RangeError: invalid offset (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: strict mode: RangeError: invalid offset (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-in-bounds.js:22: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-in-bounds.js:22: strict mode: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-out-of-bounds.js:22: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.) -test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-out-of-bounds.js:22: strict mode: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true -test262/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:73: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, get source, binding::defaultValue, binding::varTarget] and expected [binding::source, binding::sourceKey, sourceKey, binding::varTarget, get source, binding::defaultValue] should have the same contents. -test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents. -test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: strict mode: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents. -test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:37: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, targetKey, get source, binding::defaultValue, set target] and expected [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, get source, binding::defaultValue, targetKey, set target] should have the same contents. -test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents. -test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: strict mode: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents. -test262/test/language/expressions/assignment/target-member-computed-reference.js:22: Test262Error: Expected a DummyError but got a Test262Error -test262/test/language/expressions/assignment/target-member-computed-reference.js:22: strict mode: Test262Error: Expected a DummyError but got a Test262Error -test262/test/language/expressions/assignment/target-super-computed-reference.js:20: Test262Error: Expected a DummyError but got a Test262Error -test262/test/language/expressions/assignment/target-super-computed-reference.js:20: strict mode: Test262Error: Expected a DummyError but got a Test262Error -test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated. -test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated. -test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true -test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: strict mode: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true -test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called -test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: SyntaxError: invalid property name -test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name -test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: SyntaxError: invalid property name -test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name -test262/test/language/statements/with/get-binding-value-call-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents. -test262/test/language/statements/with/get-binding-value-idref-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents. -test262/test/language/statements/with/get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js:21: Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all -test262/test/language/statements/with/set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js:20: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true -test262/test/language/statements/with/set-mutable-binding-idref-compound-assign-with-proxy-env.js:58: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), get:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, get:p, has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents. -test262/test/language/statements/with/set-mutable-binding-idref-with-proxy-env.js:50: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents. diff --git a/quickjs-ng/tests.conf b/quickjs-ng/tests.conf deleted file mode 100644 index b006e16..0000000 --- a/quickjs-ng/tests.conf +++ /dev/null @@ -1,10 +0,0 @@ -[config] -local=yes -verbose=yes -testdir=tests - -[exclude] -tests/empty.js -tests/fixture_cyclic_import.js -tests/microbench.js -tests/test_worker_module.js diff --git a/quickjs-ng/tests/bug39/1.js b/quickjs-ng/tests/bug39/1.js deleted file mode 100644 index 9084ea2..0000000 --- a/quickjs-ng/tests/bug39/1.js +++ /dev/null @@ -1,6 +0,0 @@ -/*--- -flags: [qjs:track-promise-rejections] ----*/ - -Promise.reject().catch(() => print('oops')) -Promise.resolve().then(() => print('ok')) diff --git a/quickjs-ng/tests/bug39/2.js b/quickjs-ng/tests/bug39/2.js deleted file mode 100644 index a786a77..0000000 --- a/quickjs-ng/tests/bug39/2.js +++ /dev/null @@ -1,6 +0,0 @@ -/*--- -flags: [qjs:track-promise-rejections] ----*/ - -const error = await Promise.resolve().then(() => Promise.reject('reject')).catch(e => e) -print('Got this error:', error) diff --git a/quickjs-ng/tests/bug39/3.js b/quickjs-ng/tests/bug39/3.js deleted file mode 100644 index aa13106..0000000 --- a/quickjs-ng/tests/bug39/3.js +++ /dev/null @@ -1,7 +0,0 @@ -/*--- -flags: [qjs:track-promise-rejections] ----*/ - -const promise = Promise.reject('reject') -const error = await Promise.resolve().then(() => promise).catch(e => e) -print('Got this error:', error) diff --git a/quickjs-ng/tests/bug633/0.js b/quickjs-ng/tests/bug633/0.js deleted file mode 100644 index 155d3a4..0000000 --- a/quickjs-ng/tests/bug633/0.js +++ /dev/null @@ -1,7 +0,0 @@ -/*--- -flags: [qjs:no-detect-module] -negative: - phase: parse - type: SyntaxError ----*/ -const undefined = 42 // SyntaxError at global scope diff --git a/quickjs-ng/tests/bug633/1.js b/quickjs-ng/tests/bug633/1.js deleted file mode 100644 index 1aa83ba..0000000 --- a/quickjs-ng/tests/bug633/1.js +++ /dev/null @@ -1,4 +0,0 @@ -/*--- -flags: [qjs:no-detect-module, module] ----*/ -const undefined = 42 // not a SyntaxError at toplevel module scope diff --git a/quickjs-ng/tests/bug633/2.js b/quickjs-ng/tests/bug633/2.js deleted file mode 100644 index 70a3301..0000000 --- a/quickjs-ng/tests/bug633/2.js +++ /dev/null @@ -1,4 +0,0 @@ -/*--- -flags: [qjs:no-detect-module] ----*/ -{ const undefined = 42 } // not a SyntaxError, not at global scope diff --git a/quickjs-ng/tests/bug633/3.js b/quickjs-ng/tests/bug633/3.js deleted file mode 100644 index 2bfa1ce..0000000 --- a/quickjs-ng/tests/bug633/3.js +++ /dev/null @@ -1,4 +0,0 @@ -/*--- -flags: [qjs:no-detect-module] ----*/ -;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope diff --git a/quickjs-ng/tests/bug645/0.js b/quickjs-ng/tests/bug645/0.js deleted file mode 100644 index 00bdac8..0000000 --- a/quickjs-ng/tests/bug645/0.js +++ /dev/null @@ -1,4 +0,0 @@ -"use strict"; - -const u8 = new Uint8Array(1); -u8[100] = 123; // Should not throw. diff --git a/quickjs-ng/tests/bug645/1.js b/quickjs-ng/tests/bug645/1.js deleted file mode 100644 index 8031be2..0000000 --- a/quickjs-ng/tests/bug645/1.js +++ /dev/null @@ -1,9 +0,0 @@ -import { assert, assertThrows } from "../assert.js"; -const ab = new ArrayBuffer(1); -const u8 = new Uint8Array(ab); -assert(!ab.detached); -// Detach the ArrayBuffer. -ab.transfer(); -assert(ab.detached); -u8[100] = 123; // Doesn't throw. -assertThrows(TypeError, () => Object.defineProperty(u8, "100", { value: 123 })); diff --git a/quickjs-ng/tests/bug645/2.js b/quickjs-ng/tests/bug645/2.js deleted file mode 100644 index 3076efa..0000000 --- a/quickjs-ng/tests/bug645/2.js +++ /dev/null @@ -1,7 +0,0 @@ -import { assert, assertThrows } from "../assert.js"; -const ab = new ArrayBuffer(16, { maxByteLength: 32 }); -const u8 = new Uint8Array(ab, 16); -ab.resize(8); -assert(ab.byteLength, 8); -u8[1] = 123; // Doesn't throw. -assertThrows(TypeError, () => Object.defineProperty(u8, "1", { value: 123 })); diff --git a/quickjs-ng/tests/bug648.js b/quickjs-ng/tests/bug648.js deleted file mode 100644 index cb0a7d3..0000000 --- a/quickjs-ng/tests/bug648.js +++ /dev/null @@ -1,13 +0,0 @@ -/*--- -negative: - phase: runtime - type: Error ----*/ -let finrec = new FinalizationRegistry(v => {}) -let object = {object:"object"} -finrec.register(object, {held:"held"}, {token:"token"}) -object = undefined -// abrupt termination should not leak |held| -// unfortunately only shows up in qjs, not run-test262, -// but still good to have a regression test -throw Error("ok") diff --git a/quickjs-ng/tests/bug652.js b/quickjs-ng/tests/bug652.js deleted file mode 100644 index 27dea3b..0000000 --- a/quickjs-ng/tests/bug652.js +++ /dev/null @@ -1,4 +0,0 @@ -import { assert } from "./assert.js" -const ref = new WeakRef({}) -const val = ref.deref() // should not throw -assert(val, undefined) diff --git a/quickjs-ng/tests/bug741.js b/quickjs-ng/tests/bug741.js deleted file mode 100644 index 3947f71..0000000 --- a/quickjs-ng/tests/bug741.js +++ /dev/null @@ -1,19 +0,0 @@ -import {assert} from "./assert.js" - -while (1) label: break - -var i = 0 -while (i < 3) label: { - if (i > 0) - break - i++ -} -assert(i, 1) - -for (;;) label: break - -for (i = 0; i < 3; i++) label: { - if (i > 0) - break -} -assert(i, 1) diff --git a/quickjs-ng/tests/bug775.js b/quickjs-ng/tests/bug775.js deleted file mode 100644 index 4cb9387..0000000 --- a/quickjs-ng/tests/bug775.js +++ /dev/null @@ -1,7 +0,0 @@ -/*--- -negative: - phase: runtime - type: RangeError ----*/ -function f() { f() } // was problematic under ASan -f() diff --git a/quickjs-ng/tests/bug776.js b/quickjs-ng/tests/bug776.js deleted file mode 100644 index 4b092c2..0000000 --- a/quickjs-ng/tests/bug776.js +++ /dev/null @@ -1,7 +0,0 @@ -/*--- -negative: - phase: runtime - type: RangeError ----*/ -function f() { f.apply(null) } // was problematic under ASan -f() diff --git a/quickjs-ng/tests/bug832.js b/quickjs-ng/tests/bug832.js deleted file mode 100644 index 7d7b845..0000000 --- a/quickjs-ng/tests/bug832.js +++ /dev/null @@ -1,2 +0,0 @@ -const m = await import("./empty.js") -print(m) // should not throw diff --git a/quickjs-ng/tests/bug858.js b/quickjs-ng/tests/bug858.js deleted file mode 100644 index 2b0ef2c..0000000 --- a/quickjs-ng/tests/bug858.js +++ /dev/null @@ -1,26 +0,0 @@ -import {assert} from "./assert.js"; - -Error.stackTraceLimit = Infinity; -assert(Error.stackTraceLimit === Infinity); -assert(new Error("error").stack.includes("bug858.js")); // stack should not be empty - -Error.stackTraceLimit = -Infinity; -assert(Error.stackTraceLimit === -Infinity); -assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty - -Error.stackTraceLimit = NaN; -assert(Number.isNaN(Error.stackTraceLimit)); -assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty - -Error.stackTraceLimit = -0; -assert(Object.is(Error.stackTraceLimit, -0)); -assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty - -const obj = { valueOf() { throw "evil" } }; -Error.stackTraceLimit = obj; -assert(Error.stackTraceLimit === obj); -try { - throw new Error("fail") -} catch (e) { - assert(e.message.includes("fail")); -} diff --git a/quickjs-ng/tests/bug904.js b/quickjs-ng/tests/bug904.js deleted file mode 100644 index baecafe..0000000 --- a/quickjs-ng/tests/bug904.js +++ /dev/null @@ -1,6 +0,0 @@ -import {assert, assertThrows} from "./assert.js" -let calls = 0 -Error.prepareStackTrace = function() { calls++ } -function f() { f() } -assertThrows(RangeError, f) -assert(calls, 0) diff --git a/quickjs-ng/tests/bug988.js b/quickjs-ng/tests/bug988.js deleted file mode 100644 index 5f1027c..0000000 --- a/quickjs-ng/tests/bug988.js +++ /dev/null @@ -1,7 +0,0 @@ -import {assert} from "./assert.js" -const expected = [97,98,99] -const ab = new ArrayBuffer(0, {maxByteLength:3}) -const dv = new DataView(ab) -ab.resize(3) -for (const [i,v] of Object.entries(expected)) dv.setUint8(i, v) -for (const [i,v] of Object.entries(expected)) assert(v, dv.getUint8(i)) diff --git a/quickjs-ng/tests/bug999.js b/quickjs-ng/tests/bug999.js deleted file mode 100644 index 28a3a6f..0000000 --- a/quickjs-ng/tests/bug999.js +++ /dev/null @@ -1,3 +0,0 @@ -function* f(r){ return r } // must return r -[...f({})] - diff --git a/quickjs-ng/tests/destructured-export.js b/quickjs-ng/tests/destructured-export.js deleted file mode 100644 index a038c6f..0000000 --- a/quickjs-ng/tests/destructured-export.js +++ /dev/null @@ -1,8 +0,0 @@ -import { assert, assertArrayEquals } from "./assert.js"; -import * as mod from "./destructured-export.js"; - -export const { a, b, c } = { a: 1, b: 2, c: 3 }; -export const d = 4; - -assert(typeof mod === 'object'); -assertArrayEquals(Object.keys(mod), ["a", "b", "c", "d"]); diff --git a/quickjs-ng/tests/detect_module/0.js b/quickjs-ng/tests/detect_module/0.js deleted file mode 100644 index 18a9109..0000000 --- a/quickjs-ng/tests/detect_module/0.js +++ /dev/null @@ -1 +0,0 @@ -await undefined diff --git a/quickjs-ng/tests/detect_module/1.js b/quickjs-ng/tests/detect_module/1.js deleted file mode 100644 index 0212282..0000000 --- a/quickjs-ng/tests/detect_module/1.js +++ /dev/null @@ -1,2 +0,0 @@ -const p = Promise.resolve(42) -await p diff --git a/quickjs-ng/tests/detect_module/2.js b/quickjs-ng/tests/detect_module/2.js deleted file mode 100644 index 0b1d1f7..0000000 --- a/quickjs-ng/tests/detect_module/2.js +++ /dev/null @@ -1 +0,0 @@ -await = 42 // parsed as classic script diff --git a/quickjs-ng/tests/detect_module/3.js b/quickjs-ng/tests/detect_module/3.js deleted file mode 100644 index 5b175e9..0000000 --- a/quickjs-ng/tests/detect_module/3.js +++ /dev/null @@ -1,8 +0,0 @@ -/*--- -negative: - phase: parse - type: SyntaxError ----*/ -// the import statement makes it a module but `await = 42` is a SyntaxError -import * as _ from "dummy" -await = 42 diff --git a/quickjs-ng/tests/detect_module/4.js b/quickjs-ng/tests/detect_module/4.js deleted file mode 100644 index 5713f31..0000000 --- a/quickjs-ng/tests/detect_module/4.js +++ /dev/null @@ -1,3 +0,0 @@ -// imports should classify it as a module, even when not at the top -os.now() -import * as os from "qjs:os" diff --git a/quickjs-ng/tests/empty.js b/quickjs-ng/tests/empty.js deleted file mode 100644 index e69de29..0000000 diff --git a/quickjs-ng/tests/function_source.js b/quickjs-ng/tests/function_source.js deleted file mode 100644 index 640420a..0000000 --- a/quickjs-ng/tests/function_source.js +++ /dev/null @@ -1,14 +0,0 @@ -"use strict" -const expect = "function f() { return 42 }" -function f() { return 42 } - -{ - const actual = f.toString() - if (actual !== expect) throw Error(actual) -} - -{ - const f = eval(expect + "f") - const actual = f.toString() - if (actual !== expect) throw Error(actual) -} diff --git a/quickjs-ng/tests/str-pad-leak.js b/quickjs-ng/tests/str-pad-leak.js deleted file mode 100644 index 5511a69..0000000 --- a/quickjs-ng/tests/str-pad-leak.js +++ /dev/null @@ -1,5 +0,0 @@ -var v1 = ''; -try { - var v2 = v1.padEnd(2147483620, 0); -} catch(_) {} - diff --git a/quickjs-ng/tests/test_bigint.js b/quickjs-ng/tests/test_bigint.js deleted file mode 100644 index 4dc977f..0000000 --- a/quickjs-ng/tests/test_bigint.js +++ /dev/null @@ -1,107 +0,0 @@ -import { assert, assertThrows } from "./assert.js"; - - -function bigint_pow(a, n) -{ - var r, i; - r = 1n; - for(i = 0n; i < n; i++) - r *= a; - return r; -} - -/* a must be < b */ -function test_less(a, b) -{ - assert(a < b); - assert(!(b < a)); - assert(a <= b); - assert(!(b <= a)); - assert(b > a); - assert(!(a > b)); - assert(b >= a); - assert(!(a >= b)); - assert(a != b); - assert(!(a == b)); -} - -/* a must be numerically equal to b */ -function test_eq(a, b) -{ - assert(a == b); - assert(b == a); - assert(!(a != b)); - assert(!(b != a)); - assert(a <= b); - assert(b <= a); - assert(!(a < b)); - assert(a >= b); - assert(b >= a); - assert(!(a > b)); -} - -function test_bigint1() -{ - var a, r; - - test_less(2n, 3n); - test_eq(3n, 3n); - - test_less(2, 3n); - test_eq(3, 3n); - - test_less(2.1, 3n); - test_eq(Math.sqrt(4), 2n); - - a = bigint_pow(3n, 100n); - assert((a - 1n) != a); - assert(a, 515377520732011331036461129765621272702107522001n); - assert(a, 0x5a4653ca673768565b41f775d6947d55cf3813d1n); - - r = 1n << 31n; - assert(r, 2147483648n, "1 << 31n === 2147483648n"); - - r = 1n << 32n; - assert(r, 4294967296n, "1 << 32n === 4294967296n"); - - assert(String(-9223372036854775808n), "-9223372036854775808"); -} - -function test_bigint2() -{ - assert(BigInt(""), 0n); - assert(BigInt(" 123"), 123n); - assert(BigInt(" 123 "), 123n); - assertThrows(SyntaxError, () => { BigInt("+") } ); - assertThrows(SyntaxError, () => { BigInt("-") } ); - assertThrows(SyntaxError, () => { BigInt("\x00a") } ); - assertThrows(SyntaxError, () => { BigInt(" 123 r") } ); -} - -function test_bigint_map() -{ - var m = new Map(); - assert(m.size, 0); - - for (let i = 0n; i < 1337n; i++) { - const r = m.set(i, i.toString()); - assert(r, m); - } - assert(m.size, 1337); - - for (let i = 0n; i < 1337n; i++) { - const r = m.get(i); - assert(r, i.toString()); - } - assert(m.get(1337n), undefined); - assert(m.size, 1337); - - for (let i = 0n; i < 1337n; i++) - assert(m.delete(i)); - assert(!m.delete(1337n)); - assert(m.size, 0); -} - -test_bigint1(); -test_bigint2(); -test_bigint_map(); diff --git a/quickjs-ng/tests/test_domexception.js b/quickjs-ng/tests/test_domexception.js deleted file mode 100644 index 70ff1e7..0000000 --- a/quickjs-ng/tests/test_domexception.js +++ /dev/null @@ -1,35 +0,0 @@ -import { assert, assertThrows } from "./assert.js"; - -function test_code() { - let ex = new DOMException(); - assert(ex.code, 0); - ex = new DOMException("", "HierarchyRequestError\0test"); - assert(ex.code, 0); - ex = new DOMException("test", "HierarchyRequestError"); - assert(ex.code, 3); - assert(ex.code, ex.HIERARCHY_REQUEST_ERR); - assert(ex.code, DOMException.HIERARCHY_REQUEST_ERR); - ex = new DOMException("", "DataCloneError"); - assert(ex.code, ex.DATA_CLONE_ERR); - assert(ex.code, 25); - ex = new DOMException("", "IndexSizeError"); - assert(ex.code, ex.INDEX_SIZE_ERR); - assert(ex.code, 1); -} - -function test_properties() { - let ex = new DOMException("test"); - assert(ex.message, "test"); - assert(ex.name, "Error"); - ex = new DOMException("test", "InvalidCharacterError"); - assert(ex.name, "InvalidCharacterError"); - assertThrows(TypeError, () => ex.message = ""); - assertThrows(TypeError, () => ex.name = "test"); - assert(ex.__proto__, DOMException.prototype); - /* Note: browsers set "stack" on the prototype, not the object. - * This follows node. */ - assert(Object.getOwnPropertyNames(ex), ["stack"]); -} - -test_code(); -test_properties(); diff --git a/quickjs-ng/tests/test_queue_microtask.js b/quickjs-ng/tests/test_queue_microtask.js deleted file mode 100644 index f06dc8b..0000000 --- a/quickjs-ng/tests/test_queue_microtask.js +++ /dev/null @@ -1,39 +0,0 @@ -import { assert, assertArrayEquals, assertThrows } from "./assert.js"; - -function test_types() { - assertThrows(TypeError, () => queueMicrotask(), "no argument"); - assertThrows(TypeError, () => queueMicrotask(undefined), "undefined"); - assertThrows(TypeError, () => queueMicrotask(null), "null"); - assertThrows(TypeError, () => queueMicrotask(0), "0"); - assertThrows(TypeError, () => queueMicrotask({ handleEvent() { } }), "an event handler object"); - assertThrows(TypeError, () => queueMicrotask("window.x = 5;"), "a string"); -} - -function test_async() { - let called = false; - queueMicrotask(() => { - called = true; - }); - assert(!called); -} - -function test_arguments() { - queueMicrotask(function () { // note: intentionally not an arrow function - assert(arguments.length === 0); - }, "x", "y"); -}; - -function test_async_order() { - const happenings = []; - Promise.resolve().then(() => happenings.push("a")); - queueMicrotask(() => happenings.push("b")); - Promise.reject().catch(() => happenings.push("c")); - queueMicrotask(() => { - assertArrayEquals(happenings, ["a", "b", "c"]); - }); -} - -test_types(); -test_async(); -test_arguments(); -test_async_order(); diff --git a/quickjs-ng/unicode_download.sh b/quickjs-ng/unicode_download.sh deleted file mode 100755 index fb8343a..0000000 --- a/quickjs-ng/unicode_download.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -set -e - -url="ftp://ftp.unicode.org/Public/16.0.0/ucd" -emoji_url="${url}/emoji/emoji-data.txt" - -files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ -SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \ -UnicodeData.txt DerivedCoreProperties.txt NormalizationTest.txt Scripts.txt \ -PropertyValueAliases.txt" - -mkdir -p unicode - -for f in $files; do - g="${url}/${f}" - wget $g -O unicode/$f -done - -wget $emoji_url -O unicode/emoji-data.txt diff --git a/quickjs-wz-extensions/quickjs-debugger.c b/quickjs-wz-extensions/quickjs-debugger.c index bb87744..5509963 100644 --- a/quickjs-wz-extensions/quickjs-debugger.c +++ b/quickjs-wz-extensions/quickjs-debugger.c @@ -25,6 +25,12 @@ * THE SOFTWARE. */ +#if defined(QUICKJS_NG) +# define WZ_QJS_GET_FUNC_NAME(ctx, obj) get_func_name(ctx, obj) +#else +# define WZ_QJS_GET_FUNC_NAME(ctx, obj) get_prop_string(ctx, obj, JS_ATOM_name) +#endif + JSValue js_debugger_get_current_funcObject(JSContext *ctx) { JSStackFrame *sf = ctx->rt->current_stack_frame; @@ -57,7 +63,7 @@ JSValue js_debugger_get_caller_name(JSContext *ctx) levels++; } JSValue result; - const char *func_name_str = get_func_name(ctx, sf->cur_func); + const char *func_name_str = WZ_QJS_GET_FUNC_NAME(ctx, sf->cur_func); if (!func_name_str || func_name_str[0] == '\0') result = JS_NewString(ctx, ""); else @@ -80,7 +86,7 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc) uint32_t id = stack_index++; JS_SetPropertyStr(ctx, current_frame, "id", JS_NewUint32(ctx, id)); - func_name_str = get_func_name(ctx, sf->cur_func); + func_name_str = WZ_QJS_GET_FUNC_NAME(ctx, sf->cur_func); if (!func_name_str || func_name_str[0] == '\0') JS_SetPropertyStr(ctx, current_frame, "name", JS_NewString(ctx, "")); else @@ -91,13 +97,23 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc) if (p && js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b; b = p->u.func.function_bytecode; +#if defined(QUICKJS_NG) if (b && sf->cur_pc) { +#else + if (b && b->has_debug) { +#endif int line_num1, col_num1; const uint8_t *pc = sf != ctx->rt->current_stack_frame || !cur_pc ? sf->cur_pc : cur_pc; line_num1 = find_line_num(ctx, b, pc - b->byte_code_buf - 1, &col_num1); +#if defined(QUICKJS_NG) if (b->filename) { JS_SetPropertyStr(ctx, current_frame, "filename", JS_AtomToString(ctx, b->filename)); } +#else + if (b->debug.filename != JS_ATOM_NULL) { + JS_SetPropertyStr(ctx, current_frame, "filename", JS_AtomToString(ctx, b->debug.filename)); + } +#endif if (line_num1 != -1) JS_SetPropertyStr(ctx, current_frame, "line", JS_NewUint32(ctx, line_num1)); } else if (b) { diff --git a/quickjs-wz-extensions/quickjs-limitedcontext.c b/quickjs-wz-extensions/quickjs-limitedcontext.c index f66b884..cc73325 100644 --- a/quickjs-wz-extensions/quickjs-limitedcontext.c +++ b/quickjs-wz-extensions/quickjs-limitedcontext.c @@ -40,6 +40,10 @@ JSContext *JS_NewLimitedContext(JSRuntime *rt, const JSLimitedContextOptions* op JS_AddIntrinsicDate(ctx); if (options->eval) JS_AddIntrinsicEval(ctx); // required for JS_Eval (etc) to work +#if !defined(QUICKJS_NG) + if (options->stringNormalize) + JS_AddIntrinsicStringNormalize(ctx); +#endif if (options->regExp) JS_AddIntrinsicRegExp(ctx); if (options->json) @@ -52,8 +56,10 @@ JSContext *JS_NewLimitedContext(JSRuntime *rt, const JSLimitedContextOptions* op JS_AddIntrinsicTypedArrays(ctx); if (options->promise) JS_AddIntrinsicPromise(ctx); +#if defined(QUICKJS_NG) if (options->bigInt) JS_AddIntrinsicBigInt(ctx); +#endif if (options->weakRef) JS_AddIntrinsicWeakRef(ctx); return ctx; @@ -64,13 +70,20 @@ JSValue JS_Eval_BypassLimitedContext(JSContext *ctx, const char *input, size_t i const char *filename, int eval_flags) { int eval_type = eval_flags & JS_EVAL_TYPE_MASK; +#if defined(QUICKJS_NG) int line = 1; +#endif JSValue ret; assert(eval_type == JS_EVAL_TYPE_GLOBAL || eval_type == JS_EVAL_TYPE_MODULE); +#if defined(QUICKJS_NG) ret = __JS_EvalInternal(ctx, ctx->global_obj, input, input_len, filename, line, eval_flags, -1); +#else + ret = __JS_EvalInternal(ctx, ctx->global_obj, input, input_len, filename, + eval_flags, -1); +#endif return ret; } diff --git a/quickjs-wz-extensions/quickjs-limitedcontext.h b/quickjs-wz-extensions/quickjs-limitedcontext.h index 3e918ac..c0f56db 100644 --- a/quickjs-wz-extensions/quickjs-limitedcontext.h +++ b/quickjs-wz-extensions/quickjs-limitedcontext.h @@ -35,14 +35,14 @@ typedef struct JSLimitedContextOptions int baseObjects; int dateObject; int eval; - int stringNormalize; // no longer has any effect + int stringNormalize; // only has an effect on QuickJS (not QuickJS-NG) int regExp; int json; int proxy; int mapSet; int typedArrays; int promise; - int bigInt; + int bigInt; // only has an effect on QuickJS-NG (ignored on QuickJS) int weakRef; } JSLimitedContextOptions; diff --git a/quickjs/Changelog b/quickjs/Changelog new file mode 100644 index 0000000..7d6afd6 --- /dev/null +++ b/quickjs/Changelog @@ -0,0 +1,219 @@ +- micro optimizations (15% faster on bench-v8) +- added resizable array buffers +- added ArrayBuffer.prototype.transfer +- added the Iterator object and methods +- added set methods +- added Atomics.pause +- added added Map and WeakMap upsert methods +- added Math.sumPrecise() +- misc bug fixes + +2025-09-13: + +- added JSON modules and import attributes +- added JS_PrintValue() API +- qjs: pretty print objects in print() and console.log() +- qjs: better promise rejection tracker heuristics +- added RegExp v flag +- added RegExp modifiers +- added RegExp.escape +- added Float16Array +- added Promise.try +- improved JSON parser spec conformance +- qjs: improved compatibility of std.parseExtJSON() with JSON5 and + accept JSON5 modules +- added JS_FreePropertyEnum() and JS_AtomToCStringLen() API +- added Error.isError() +- misc bug fixes + +2025-04-26: + +- removed the bignum extensions and qjscalc +- new BigInt implementation optimized for small numbers +- added WeakRef, FinalizationRegistry and symbols as weakrefs +- added builtin float64 printing and parsing functions for more correctness +- faster repeated string concatenation +- qjs: promise unhandled rejections are fatal errors by default +- added column number in debug information +- removed the "use strip" extension +- qjs: added -s and --strip-source options +- qjsc: added -s and --keep-source options +- added JS_GetAnyOpaque() +- added more callbacks for exotic objects in JSClassExoticMethods +- misc bug fixes + +2024-01-13: + +- top-level-await support in modules +- allow 'await' in the REPL +- added Array.prototype.{with,toReversed,toSpliced,toSorted} and +TypedArray.prototype.{with,toReversed,toSorted} +- added String.prototype.isWellFormed and String.prototype.toWellFormed +- added Object.groupBy and Map.groupBy +- added Promise.withResolvers +- class static block +- 'in' operator support for private fields +- optional chaining fixes +- added RegExp 'd' flag +- fixed RegExp zero length match logic +- fixed RegExp case insensitive flag +- added os.sleepAsync(), os.getpid() and os.now() +- added cosmopolitan build +- misc bug fixes + +2023-12-09: + +- added Object.hasOwn, {String|Array|TypedArray}.prototype.at, + {Array|TypedArray}.prototype.findLast{Index} +- BigInt support is enabled even if CONFIG_BIGNUM disabled +- updated to Unicode 15.0.0 +- misc bug fixes + +2021-03-27: + +- faster Array.prototype.push and Array.prototype.unshift +- added JS_UpdateStackTop() +- fixed Windows console +- misc bug fixes + +2020-11-08: + +- improved function parameter initializers +- added std.setenv(), std.unsetenv() and std.getenviron() +- added JS_EvalThis() +- misc bug fixes + +2020-09-06: + +- added logical assignment operators +- added IsHTMLDDA support +- faster for-of loops +- os.Worker now takes a module filename as parameter +- qjsc: added -D option to compile dynamically loaded modules or workers +- misc bug fixes + +2020-07-05: + +- modified JS_GetPrototype() to return a live value +- REPL: support unicode characters larger than 16 bits +- added os.Worker +- improved object serialization +- added std.parseExtJSON +- misc bug fixes + +2020-04-12: + +- added cross realm support +- added AggregateError and Promise.any +- added env, uid and gid options in os.exec() +- misc bug fixes + +2020-03-16: + +- reworked error handling in std and os libraries: suppressed I/O + exceptions in std FILE functions and return a positive errno value + when it is explicit +- output exception messages to stderr +- added std.loadFile(), std.strerror(), std.FILE.prototype.tello() +- added JS_GetRuntimeOpaque(), JS_SetRuntimeOpaque(), JS_NewUint32() +- updated to Unicode 13.0.0 +- misc bug fixes + +2020-01-19: + +- keep CONFIG_BIGNUM in the makefile +- added os.chdir() +- qjs: added -I option +- more memory checks in the bignum operations +- modified operator overloading semantics to be closer to the TC39 + proposal +- suppressed "use bigint" mode. Simplified "use math" mode +- BigDecimal: changed suffix from 'd' to 'm' +- misc bug fixes + +2020-01-05: + +- always compile the bignum code. Added '--bignum' option to qjs. +- added BigDecimal +- added String.prototype.replaceAll +- misc bug fixes + +2019-12-21: + +- added nullish coalescing operator (ES2020) +- added optional chaining (ES2020) +- removed recursions in garbage collector +- test stack overflow in the parser +- improved backtrace logic +- added JS_SetHostPromiseRejectionTracker() +- allow exotic constructors +- improved c++ compatibility +- misc bug fixes + +2019-10-27: + +- added example of C class in a module (examples/test_point.js) +- added JS_GetTypedArrayBuffer() +- misc bug fixes + +2019-09-18: + +- added os.exec and other system calls +- exported JS_ValueToAtom() +- qjsc: added 'qjsc_' prefix to the generated C identifiers +- added cross-compilation support +- misc bug fixes + +2019-09-01: + +- added globalThis +- documented JS_EVAL_FLAG_COMPILE_ONLY +- added import.meta.url and import.meta.main +- added 'debugger' statement +- misc bug fixes + +2019-08-18: + +- added os.realpath, os.getcwd, os.mkdir, os.stat, os.lstat, + os.readlink, os.readdir, os.utimes, std.popen +- module autodetection +- added import.meta +- misc bug fixes + +2019-08-10: + +- added public class fields and private class fields, methods and + accessors (TC39 proposal) +- changed JS_ToCStringLen() prototype +- qjsc: handle '-' in module names and modules with the same filename +- added std.urlGet +- exported JS_GetOwnPropertyNames() and JS_GetOwnProperty() +- exported some bigint C functions +- added support for eshost in run-test262 +- misc bug fixes + +2019-07-28: + +- added dynamic import +- added Promise.allSettled +- added String.prototype.matchAll +- added Object.fromEntries +- reduced number of ticks in await +- added BigInt support in Atomics +- exported JS_NewPromiseCapability() +- misc async function and async generator fixes +- enabled hashbang support by default + +2019-07-21: + +- updated test262 tests +- updated to Unicode version 12.1.0 +- fixed missing Date object in qjsc +- fixed multi-context creation +- misc ES2020 related fixes +- simplified power and division operators in bignum extension +- fixed several crash conditions + +2019-07-09: + +- first public release diff --git a/quickjs-ng/LICENSE b/quickjs/LICENSE similarity index 84% rename from quickjs-ng/LICENSE rename to quickjs/LICENSE index 3c78b69..2cf449d 100644 --- a/quickjs-ng/LICENSE +++ b/quickjs/LICENSE @@ -1,9 +1,7 @@ -The MIT License (MIT) - -Copyright (c) 2017-2024 Fabrice Bellard -Copyright (c) 2017-2024 Charlie Gordon -Copyright (c) 2023-2025 Ben Noordhuis -Copyright (c) 2023-2025 Saúl Ibarra Corretgé +QuickJS Javascript Engine + +Copyright (c) 2017-2021 Fabrice Bellard +Copyright (c) 2017-2021 Charlie Gordon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/quickjs/Makefile b/quickjs/Makefile new file mode 100644 index 0000000..ba64923 --- /dev/null +++ b/quickjs/Makefile @@ -0,0 +1,550 @@ +# +# QuickJS Javascript Engine +# +# Copyright (c) 2017-2021 Fabrice Bellard +# Copyright (c) 2017-2021 Charlie Gordon +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +ifeq ($(shell uname -s),Darwin) +CONFIG_DARWIN=y +endif +ifeq ($(shell uname -s),FreeBSD) +CONFIG_FREEBSD=y +endif +# Windows cross compilation from Linux +# May need to have libwinpthread*.dll alongside the executable +# (On Ubuntu/Debian may be installed with mingw-w64-x86-64-dev +# to /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll) +#CONFIG_WIN32=y +# use link time optimization (smaller and faster executables but slower build) +#CONFIG_LTO=y +# consider warnings as errors (for development) +#CONFIG_WERROR=y +# force 32 bit build on x86_64 +#CONFIG_M32=y +# cosmopolitan build (see https://github.com/jart/cosmopolitan) +#CONFIG_COSMO=y + +# installation directory +PREFIX?=/usr/local + +# use the gprof profiler +#CONFIG_PROFILE=y +# use address sanitizer +#CONFIG_ASAN=y +# use memory sanitizer +#CONFIG_MSAN=y +# use UB sanitizer +#CONFIG_UBSAN=y + +# TEST262 bootstrap config: commit id and shallow "since" parameter +TEST262_COMMIT?=42303c7c2bcf1c1edb9e5375c291c6fbc8a261ab +TEST262_SINCE?=2025-09-01 + +OBJDIR=.obj + +ifdef CONFIG_ASAN +OBJDIR:=$(OBJDIR)/asan +endif +ifdef CONFIG_MSAN +OBJDIR:=$(OBJDIR)/msan +endif +ifdef CONFIG_UBSAN +OBJDIR:=$(OBJDIR)/ubsan +endif + +ifdef CONFIG_DARWIN +# use clang instead of gcc +CONFIG_CLANG=y +CONFIG_DEFAULT_AR=y +endif +ifdef CONFIG_FREEBSD +# use clang instead of gcc +CONFIG_CLANG=y +CONFIG_DEFAULT_AR=y +CONFIG_LTO= +endif + +ifdef CONFIG_WIN32 + ifdef CONFIG_M32 + CROSS_PREFIX?=i686-w64-mingw32- + else + CROSS_PREFIX?=x86_64-w64-mingw32- + endif + EXE=.exe +else ifdef MSYSTEM + CONFIG_WIN32=y + CROSS_PREFIX?= + EXE=.exe +else + CROSS_PREFIX?= + EXE= +endif + +ifdef CONFIG_CLANG + HOST_CC=clang + CC=$(CROSS_PREFIX)clang + CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d + CFLAGS += -Wextra + CFLAGS += -Wno-sign-compare + CFLAGS += -Wno-missing-field-initializers + CFLAGS += -Wundef -Wuninitialized + CFLAGS += -Wunused -Wno-unused-parameter + CFLAGS += -Wwrite-strings + CFLAGS += -Wchar-subscripts -funsigned-char + CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d + ifdef CONFIG_DEFAULT_AR + AR=$(CROSS_PREFIX)ar + else + ifdef CONFIG_LTO + AR=$(CROSS_PREFIX)llvm-ar + else + AR=$(CROSS_PREFIX)ar + endif + endif + LIB_FUZZING_ENGINE ?= "-fsanitize=fuzzer" +else ifdef CONFIG_COSMO + CONFIG_LTO= + HOST_CC=gcc + CC=cosmocc + # cosmocc does not correct support -MF + CFLAGS=-g -Wall #-MMD -MF $(OBJDIR)/$(@F).d + CFLAGS += -Wno-array-bounds -Wno-format-truncation + AR=cosmoar +else + HOST_CC=gcc + CC=$(CROSS_PREFIX)gcc + CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d + CFLAGS += -Wno-array-bounds -Wno-format-truncation -Wno-infinite-recursion + ifdef CONFIG_LTO + AR=$(CROSS_PREFIX)gcc-ar + else + AR=$(CROSS_PREFIX)ar + endif +endif +STRIP?=$(CROSS_PREFIX)strip +ifdef CONFIG_M32 +CFLAGS+=-msse2 -mfpmath=sse # use SSE math for correct FP rounding +ifndef CONFIG_WIN32 +CFLAGS+=-m32 +LDFLAGS+=-m32 +endif +endif +CFLAGS+=-fwrapv # ensure that signed overflows behave as expected +ifdef CONFIG_WERROR +CFLAGS+=-Werror +endif +DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" +ifdef CONFIG_WIN32 +DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior +endif +ifndef CONFIG_WIN32 +ifeq ($(shell $(CC) -o /dev/null compat/test-closefrom.c 2>/dev/null && echo 1),1) +DEFINES+=-DHAVE_CLOSEFROM +endif +endif + +CFLAGS+=$(DEFINES) +CFLAGS_DEBUG=$(CFLAGS) -O0 +CFLAGS_SMALL=$(CFLAGS) -Os +CFLAGS_OPT=$(CFLAGS) -O2 +CFLAGS_NOLTO:=$(CFLAGS_OPT) +ifdef CONFIG_COSMO +LDFLAGS+=-s # better to strip by default +else +LDFLAGS+=-g +endif +ifdef CONFIG_LTO +CFLAGS_SMALL+=-flto +CFLAGS_OPT+=-flto +LDFLAGS+=-flto +endif +ifdef CONFIG_PROFILE +CFLAGS+=-p +LDFLAGS+=-p +endif +ifdef CONFIG_ASAN +CFLAGS+=-fsanitize=address -fno-omit-frame-pointer +LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer +endif +ifdef CONFIG_MSAN +CFLAGS+=-fsanitize=memory -fno-omit-frame-pointer +LDFLAGS+=-fsanitize=memory -fno-omit-frame-pointer +endif +ifdef CONFIG_UBSAN +CFLAGS+=-fsanitize=undefined -fno-omit-frame-pointer +LDFLAGS+=-fsanitize=undefined -fno-omit-frame-pointer +endif +ifdef CONFIG_WIN32 +LDEXPORT= +else +LDEXPORT=-rdynamic +endif + +ifndef CONFIG_COSMO +ifndef CONFIG_DARWIN +ifndef CONFIG_WIN32 +CONFIG_SHARED_LIBS=y # building shared libraries is supported +endif +endif +endif + +PROGS=qjs$(EXE) qjsc$(EXE) run-test262$(EXE) + +ifneq ($(CROSS_PREFIX),) +QJSC_CC=gcc +QJSC=./host-qjsc +PROGS+=$(QJSC) +else +QJSC_CC=$(CC) +QJSC=./qjsc$(EXE) +endif +PROGS+=libquickjs.a +ifdef CONFIG_LTO +PROGS+=libquickjs.lto.a +endif + +# examples +ifeq ($(CROSS_PREFIX),) +ifndef CONFIG_ASAN +ifndef CONFIG_MSAN +ifndef CONFIG_UBSAN +PROGS+=examples/hello examples/test_fib +# no -m32 option in qjsc +ifndef CONFIG_M32 +ifndef CONFIG_WIN32 +PROGS+=examples/hello_module +endif +endif +ifdef CONFIG_SHARED_LIBS +PROGS+=examples/fib.so examples/point.so +endif +endif +endif +endif +endif + +all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS) + +QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/dtoa.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o + +QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS) + +HOST_LIBS=-lm -ldl -lpthread +LIBS=-lm -lpthread +ifndef CONFIG_WIN32 +LIBS+=-ldl +endif +LIBS+=$(EXTRA_LIBS) + +$(OBJDIR): + mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests + +qjs$(EXE): $(QJS_OBJS) + $(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) + +qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS)) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +fuzz_eval: $(OBJDIR)/fuzz_eval.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a + $(CC) $(CFLAGS_OPT) $^ -o fuzz_eval $(LIB_FUZZING_ENGINE) + +fuzz_compile: $(OBJDIR)/fuzz_compile.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a + $(CC) $(CFLAGS_OPT) $^ -o fuzz_compile $(LIB_FUZZING_ENGINE) + +fuzz_regexp: $(OBJDIR)/fuzz_regexp.o $(OBJDIR)/libregexp.fuzz.o $(OBJDIR)/cutils.fuzz.o $(OBJDIR)/libunicode.fuzz.o + $(CC) $(CFLAGS_OPT) $^ -o fuzz_regexp $(LIB_FUZZING_ENGINE) + +libfuzzer: fuzz_eval fuzz_compile fuzz_regexp + +ifneq ($(CROSS_PREFIX),) + +$(QJSC): $(OBJDIR)/qjsc.host.o \ + $(patsubst %.o, %.host.o, $(QJS_LIB_OBJS)) + $(HOST_CC) $(LDFLAGS) -o $@ $^ $(HOST_LIBS) + +endif #CROSS_PREFIX + +QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\" +ifdef CONFIG_LTO +QJSC_DEFINES+=-DCONFIG_LTO +endif +QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\" + +$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES) +$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES) + +ifdef CONFIG_LTO +LTOEXT=.lto +else +LTOEXT= +endif + +libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS) + $(AR) rcs $@ $^ + +ifdef CONFIG_LTO +libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS)) + $(AR) rcs $@ $^ +endif # CONFIG_LTO + +libquickjs.fuzz.a: $(patsubst %.o, %.fuzz.o, $(QJS_LIB_OBJS)) + $(AR) rcs $@ $^ + +repl.c: $(QJSC) repl.js + $(QJSC) -s -c -o $@ -m repl.js + +ifneq ($(wildcard unicode/UnicodeData.txt),) +$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.nolto.o: libunicode-table.h + +libunicode-table.h: unicode_gen + ./unicode_gen unicode $@ +endif + +run-test262$(EXE): $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +# object suffix order: nolto + +$(OBJDIR)/%.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -c -o $@ $< + +$(OBJDIR)/fuzz_%.o: fuzz/fuzz_%.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -c -I. -o $@ $< + +$(OBJDIR)/%.host.o: %.c | $(OBJDIR) + $(HOST_CC) $(CFLAGS_OPT) -c -o $@ $< + +$(OBJDIR)/%.pic.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $< + +$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_NOLTO) -c -o $@ $< + +$(OBJDIR)/%.debug.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_DEBUG) -c -o $@ $< + +$(OBJDIR)/%.fuzz.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -fsanitize=fuzzer-no-link -c -o $@ $< + +$(OBJDIR)/%.check.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $< + +regexp_test: libregexp.c libunicode.c cutils.c + $(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS) + +unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h + $(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o + +clean: + rm -f repl.c out.c + rm -f *.a *.o *.d *~ unicode_gen regexp_test fuzz_eval fuzz_compile fuzz_regexp $(PROGS) + rm -f hello.c test_fib.c + rm -f examples/*.so tests/*.so + rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug$(EXE) + rm -rf run-test262-debug$(EXE) + rm -f run_octane run_sunspider_like + +install: all + mkdir -p "$(DESTDIR)$(PREFIX)/bin" + $(STRIP) qjs$(EXE) qjsc$(EXE) + install -m755 qjs$(EXE) qjsc$(EXE) "$(DESTDIR)$(PREFIX)/bin" + mkdir -p "$(DESTDIR)$(PREFIX)/lib/quickjs" + install -m644 libquickjs.a "$(DESTDIR)$(PREFIX)/lib/quickjs" +ifdef CONFIG_LTO + install -m644 libquickjs.lto.a "$(DESTDIR)$(PREFIX)/lib/quickjs" +endif + mkdir -p "$(DESTDIR)$(PREFIX)/include/quickjs" + install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(PREFIX)/include/quickjs" + +############################################################################### +# examples + +# example of static JS compilation +HELLO_SRCS=examples/hello.js +HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ + -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ + -fno-date -fno-module-loader + +hello.c: $(QJSC) $(HELLO_SRCS) + $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) + +examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +# example of static JS compilation with modules +HELLO_MODULE_SRCS=examples/hello_module.js +HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-typedarray \ + -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ + -fno-date -m +examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS) + $(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS) + +# use of an external C module (static compilation) + +test_fib.c: $(QJSC) examples/test_fib.js + $(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js + +examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +examples/fib.so: $(OBJDIR)/examples/fib.pic.o + $(CC) $(LDFLAGS) -shared -o $@ $^ + +examples/point.so: $(OBJDIR)/examples/point.pic.o + $(CC) $(LDFLAGS) -shared -o $@ $^ + +############################################################################### +# documentation + +DOCS=doc/quickjs.pdf doc/quickjs.html + +build_doc: $(DOCS) + +clean_doc: + rm -f $(DOCS) + +doc/version.texi: VERSION + @echo "@set VERSION `cat $<`" > $@ + +doc/%.pdf: doc/%.texi doc/version.texi + texi2pdf --clean -o $@ -q $< + +doc/%.html.pre: doc/%.texi doc/version.texi + makeinfo --html --no-headers --no-split --number-sections -o $@ $< + +doc/%.html: doc/%.html.pre + sed -e 's||\n|' < $< > $@ + +############################################################################### +# tests + +ifdef CONFIG_SHARED_LIBS +test: tests/bjson.so examples/point.so +endif + +test: qjs$(EXE) + $(WINE) ./qjs$(EXE) tests/test_closure.js + $(WINE) ./qjs$(EXE) tests/test_language.js + $(WINE) ./qjs$(EXE) --std tests/test_builtin.js + $(WINE) ./qjs$(EXE) tests/test_loop.js + $(WINE) ./qjs$(EXE) tests/test_bigint.js + $(WINE) ./qjs$(EXE) tests/test_cyclic_import.js + $(WINE) ./qjs$(EXE) tests/test_worker.js +ifndef CONFIG_WIN32 + $(WINE) ./qjs$(EXE) tests/test_std.js +endif +ifdef CONFIG_SHARED_LIBS + $(WINE) ./qjs$(EXE) tests/test_bjson.js + $(WINE) ./qjs$(EXE) examples/test_point.js +endif + +stats: qjs$(EXE) + $(WINE) ./qjs$(EXE) -qd + +microbench: qjs$(EXE) + $(WINE) ./qjs$(EXE) --std tests/microbench.js + +ifeq ($(wildcard test262/features.txt),) +test2-bootstrap: + git clone --single-branch --shallow-since=$(TEST262_SINCE) https://github.com/tc39/test262.git + (cd test262 && git checkout -q $(TEST262_COMMIT) && patch -p1 < ../tests/test262.patch && cd ..) +else +test2-bootstrap: + (cd test262 && git fetch && git reset --hard $(TEST262_COMMIT) && patch -p1 < ../tests/test262.patch && cd ..) +endif + +ifeq ($(wildcard test262o/tests.txt),) +test2o test2o-update: + @echo test262o tests not installed +else +# ES5 tests (obsolete) +test2o: run-test262 + time ./run-test262 -t -m -c test262o.conf + +test2o-update: run-test262 + ./run-test262 -t -u -c test262o.conf +endif + +ifeq ($(wildcard test262/features.txt),) +test2 test2-update test2-default test2-check: + @echo test262 tests not installed +else +# Test262 tests +test2-default: run-test262 + time ./run-test262 -t -m -c test262.conf + +test2: run-test262 + time ./run-test262 -t -m -c test262.conf -a + +test2-update: run-test262 + ./run-test262 -t -u -c test262.conf -a + +test2-check: run-test262 + time ./run-test262 -t -m -c test262.conf -E -a +endif + +testall: all test microbench test2o test2 + +testall-complete: testall + +node-test: + node tests/test_closure.js + node tests/test_language.js + node tests/test_builtin.js + node tests/test_loop.js + node tests/test_bigint.js + +node-microbench: + node tests/microbench.js -s microbench-node.txt + node --jitless tests/microbench.js -s microbench-node-jitless.txt + +bench-v8: qjs + make -C tests/bench-v8 + ./qjs -d tests/bench-v8/combined.js + +node-bench-v8: + make -C tests/bench-v8 + node --jitless tests/bench-v8/combined.js + +tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o + $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) + +BENCHMARKDIR=../quickjs-benchmarks + +run_sunspider_like: $(BENCHMARKDIR)/run_sunspider_like.c + $(CC) $(CFLAGS) $(LDFLAGS) -DNO_INCLUDE_DIR -I. -o $@ $< libquickjs$(LTOEXT).a $(LIBS) + +run_octane: $(BENCHMARKDIR)/run_octane.c + $(CC) $(CFLAGS) $(LDFLAGS) -DNO_INCLUDE_DIR -I. -o $@ $< libquickjs$(LTOEXT).a $(LIBS) + +benchmarks: run_sunspider_like run_octane + ./run_sunspider_like $(BENCHMARKDIR)/kraken-1.0/ + ./run_sunspider_like $(BENCHMARKDIR)/kraken-1.1/ + ./run_sunspider_like $(BENCHMARKDIR)/sunspider-1.0/ + ./run_octane $(BENCHMARKDIR)/ + +-include $(wildcard $(OBJDIR)/*.d) diff --git a/quickjs/TODO b/quickjs/TODO new file mode 100644 index 0000000..af96fb8 --- /dev/null +++ b/quickjs/TODO @@ -0,0 +1,66 @@ +Misc ideas: +- use custom printf to avoid compatibility issues with floating point numbers +- consistent naming for preprocessor defines +- unify coding style and naming conventions +- use names from the ECMA spec in library implementation +- use byte code emitters with typed arguments (for clarity) +- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing + and use the same wrappers in all phases +- use more generic method for line numbers in resolve_variables and resolve_labels +- use custom timezone support to avoid C library compatibility issues + +Memory: +- use memory pools for objects, etc? +- test border cases for max number of atoms, object properties, string length +- add emergency malloc mode for out of memory exceptions. +- test all DynBuf memory errors +- test all js_realloc memory errors +- improve JS_ComputeMemoryUsage() with more info + +Built-in standard library: +- BSD sockets +- modules: use realpath in module name normalizer and put it in quickjs-libc +- modules: if no ".", use a well known module loading path ? +- get rid of __loadScript, use more common name + +REPL: +- debugger +- readline: support MS Windows terminal +- readline: handle dynamic terminal resizing +- readline: handle double width unicode characters +- multiline editing +- runtime object and function inspectors +- interactive object browser +- use more generic approach to display evaluation results +- improve directive handling: dispatch, colorize, completion... +- save history +- close all predefined methods in repl.js and jscalc.js + +Optimization ideas: +- use 64 bit JSValue in 64 bit mode +- use JSValue as atoms and use a specific constant pool in functions to + reference atoms from the bytecode +- reuse stack slots for disjoint scopes, if strip +- add heuristic to avoid some cycles in closures +- small String (1 codepoint) with immediate storage +- perform static string concatenation at compile time +- add implicit numeric strings for Uint32 numbers? +- optimize `s += a + b`, `s += a.b` and similar simple expressions +- ensure string canonical representation and optimise comparisons and hashes? +- property access optimization on the global object, functions, + prototypes and special non extensible objects. +- create object literals with the correct length by backpatching length argument +- remove redundant set_loc_uninitialized/check_uninitialized opcodes +- peephole optim: push_atom_value, to_propkey -> push_atom_value +- peephole optim: put_loc x, get_loc_check x -> set_loc x +- convert slow array to fast array when all properties != length are numeric +- optimize destructuring assignments for global and local variables +- implement some form of tail-call-optimization +- optimize OP_apply +- optimize f(...b) + +Test262o: 0/11262 errors, 463 excluded +Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch) + +Test262: +Result: 61/83149 errors, 1645 excluded, 5538 skipped diff --git a/quickjs/VERSION.txt b/quickjs/VERSION.txt new file mode 100644 index 0000000..433b8f8 --- /dev/null +++ b/quickjs/VERSION.txt @@ -0,0 +1 @@ +2025-09-13 diff --git a/quickjs/compat/test-closefrom.c b/quickjs/compat/test-closefrom.c new file mode 100644 index 0000000..1324e97 --- /dev/null +++ b/quickjs/compat/test-closefrom.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + closefrom(3); + return 0; +} diff --git a/quickjs/cutils.c b/quickjs/cutils.c new file mode 100644 index 0000000..eae734a --- /dev/null +++ b/quickjs/cutils.c @@ -0,0 +1,645 @@ +/* + * C utilities + * + * Copyright (c) 2017 Fabrice Bellard + * Copyright (c) 2018 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include + +#include "cutils.h" + +#if defined(_MSC_VER) +#include "win32-gettimeofday.c" +#endif + +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +char *pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +int strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + +int has_suffix(const char *str, const char *suffix) +{ + size_t len = strlen(str); + size_t slen = strlen(suffix); + return (len >= slen && !memcmp(str + len - slen, suffix, slen)); +} + +/* Dynamic buffer package */ + +static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) +{ + memset(s, 0, sizeof(*s)); + if (!realloc_func) + realloc_func = dbuf_default_realloc; + s->opaque = opaque; + s->realloc_func = realloc_func; +} + +void dbuf_init(DynBuf *s) +{ + dbuf_init2(s, NULL, NULL); +} + +/* Try to allocate 'len' more bytes. return < 0 if error */ +int dbuf_claim(DynBuf *s, size_t len) +{ + size_t new_size, size; + uint8_t *new_buf; + new_size = s->size + len; + if (new_size < len) + return -1; /* overflow case */ + if (new_size > s->allocated_size) { + if (s->error) + return -1; + size = s->allocated_size + (s->allocated_size / 2); + if (size < s->allocated_size) + return -1; /* overflow case */ + if (size > new_size) + new_size = size; + new_buf = s->realloc_func(s->opaque, s->buf, new_size); + if (!new_buf) { + s->error = TRUE; + return -1; + } + s->buf = new_buf; + s->allocated_size = new_size; + } + return 0; +} + +int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) +{ + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) + return -1; + } + memcpy_no_ub(s->buf + s->size, data, len); + s->size += len; + return 0; +} + +int dbuf_put_self(DynBuf *s, size_t offset, size_t len) +{ + if (unlikely((s->allocated_size - s->size) < len)) { + if (dbuf_claim(s, len)) + return -1; + } + memcpy(s->buf + s->size, s->buf + offset, len); + s->size += len; + return 0; +} + +int __dbuf_putc(DynBuf *s, uint8_t c) +{ + return dbuf_put(s, &c, 1); +} + +int __dbuf_put_u16(DynBuf *s, uint16_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 2); +} + +int __dbuf_put_u32(DynBuf *s, uint32_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 4); +} + +int __dbuf_put_u64(DynBuf *s, uint64_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 8); +} + +int dbuf_putstr(DynBuf *s, const char *str) +{ + return dbuf_put(s, (const uint8_t *)str, strlen(str)); +} + +int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, + const char *fmt, ...) +{ + va_list ap; + char buf[128]; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (len < 0) + return -1; + if (len < sizeof(buf)) { + /* fast case */ + return dbuf_put(s, (uint8_t *)buf, len); + } else { + if (dbuf_claim(s, len + 1)) + return -1; + va_start(ap, fmt); + vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, + fmt, ap); + va_end(ap); + s->size += len; + } + return 0; +} + +void dbuf_free(DynBuf *s) +{ + /* we test s->buf as a fail safe to avoid crashing if dbuf_free() + is called twice */ + if (s->buf) { + s->realloc_func(s->opaque, s->buf, 0); + } + memset(s, 0, sizeof(*s)); +} + +/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes + are output. */ +int unicode_to_utf8(uint8_t *buf, unsigned int c) +{ + uint8_t *q = buf; + + if (c < 0x80) { + *q++ = c; + } else { + if (c < 0x800) { + *q++ = (c >> 6) | 0xc0; + } else { + if (c < 0x10000) { + *q++ = (c >> 12) | 0xe0; + } else { + if (c < 0x00200000) { + *q++ = (c >> 18) | 0xf0; + } else { + if (c < 0x04000000) { + *q++ = (c >> 24) | 0xf8; + } else if (c < 0x80000000) { + *q++ = (c >> 30) | 0xfc; + *q++ = ((c >> 24) & 0x3f) | 0x80; + } else { + return 0; + } + *q++ = ((c >> 18) & 0x3f) | 0x80; + } + *q++ = ((c >> 12) & 0x3f) | 0x80; + } + *q++ = ((c >> 6) & 0x3f) | 0x80; + } + *q++ = (c & 0x3f) | 0x80; + } + return q - buf; +} + +static const unsigned int utf8_min_code[5] = { + 0x80, 0x800, 0x10000, 0x00200000, 0x04000000, +}; + +static const unsigned char utf8_first_code_mask[5] = { + 0x1f, 0xf, 0x7, 0x3, 0x1, +}; + +/* return -1 if error. *pp is not updated in this case. max_len must + be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */ +int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) +{ + int l, c, b, i; + + c = *p++; + if (c < 0x80) { + *pp = p; + return c; + } + switch(c) { + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + l = 1; + break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + l = 2; + break; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + l = 3; + break; + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + l = 4; + break; + case 0xfc: case 0xfd: + l = 5; + break; + default: + return -1; + } + /* check that we have enough characters */ + if (l > (max_len - 1)) + return -1; + c &= utf8_first_code_mask[l - 1]; + for(i = 0; i < l; i++) { + b = *p++; + if (b < 0x80 || b >= 0xc0) + return -1; + c = (c << 6) | (b & 0x3f); + } + if (c < utf8_min_code[l - 1]) + return -1; + *pp = p; + return c; +} + +#if 0 + +#if defined(EMSCRIPTEN) || defined(__ANDROID__) + +static void *rqsort_arg; +static int (*rqsort_cmp)(const void *, const void *, void *); + +static int rqsort_cmp2(const void *p1, const void *p2) +{ + return rqsort_cmp(p1, p2, rqsort_arg); +} + +/* not reentrant, but not needed with emscripten */ +void rqsort(void *base, size_t nmemb, size_t size, + int (*cmp)(const void *, const void *, void *), + void *arg) +{ + rqsort_arg = arg; + rqsort_cmp = cmp; + qsort(base, nmemb, size, rqsort_cmp2); +} + +#endif + +#else + +typedef void (*exchange_f)(void *a, void *b, size_t size); +typedef int (*cmp_f)(const void *, const void *, void *opaque); + +static void exchange_bytes(void *a, void *b, size_t size) { + uint8_t *ap = (uint8_t *)a; + uint8_t *bp = (uint8_t *)b; + + while (size-- != 0) { + uint8_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_byte(void *a, void *b, size_t size) { + uint8_t *ap = (uint8_t *)a; + uint8_t *bp = (uint8_t *)b; + uint8_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int16s(void *a, void *b, size_t size) { + uint16_t *ap = (uint16_t *)a; + uint16_t *bp = (uint16_t *)b; + + for (size /= sizeof(uint16_t); size-- != 0;) { + uint16_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int16(void *a, void *b, size_t size) { + uint16_t *ap = (uint16_t *)a; + uint16_t *bp = (uint16_t *)b; + uint16_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int32s(void *a, void *b, size_t size) { + uint32_t *ap = (uint32_t *)a; + uint32_t *bp = (uint32_t *)b; + + for (size /= sizeof(uint32_t); size-- != 0;) { + uint32_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int32(void *a, void *b, size_t size) { + uint32_t *ap = (uint32_t *)a; + uint32_t *bp = (uint32_t *)b; + uint32_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int64s(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + + for (size /= sizeof(uint64_t); size-- != 0;) { + uint64_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int64(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + uint64_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int128s(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + + for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { + uint64_t t = ap[0]; + uint64_t u = ap[1]; + ap[0] = bp[0]; + ap[1] = bp[1]; + bp[0] = t; + bp[1] = u; + } +} + +static void exchange_one_int128(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + uint64_t t = ap[0]; + uint64_t u = ap[1]; + ap[0] = bp[0]; + ap[1] = bp[1]; + bp[0] = t; + bp[1] = u; +} + +static inline exchange_f exchange_func(const void *base, size_t size) { + switch (((uintptr_t)base | (uintptr_t)size) & 15) { + case 0: + if (size == sizeof(uint64_t) * 2) + return exchange_one_int128; + else + return exchange_int128s; + case 8: + if (size == sizeof(uint64_t)) + return exchange_one_int64; + else + return exchange_int64s; + case 4: + case 12: + if (size == sizeof(uint32_t)) + return exchange_one_int32; + else + return exchange_int32s; + case 2: + case 6: + case 10: + case 14: + if (size == sizeof(uint16_t)) + return exchange_one_int16; + else + return exchange_int16s; + default: + if (size == 1) + return exchange_one_byte; + else + return exchange_bytes; + } +} + +static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) +{ + uint8_t *basep = (uint8_t *)base; + size_t i, n, c, r; + exchange_f swap = exchange_func(base, size); + + if (nmemb > 1) { + i = (nmemb / 2) * size; + n = nmemb * size; + + while (i > 0) { + i -= size; + for (r = i; (c = r * 2 + size) < n; r = c) { + if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) + c += size; + if (cmp(basep + r, basep + c, opaque) > 0) + break; + swap(basep + r, basep + c, size); + } + } + for (i = n - size; i > 0; i -= size) { + swap(basep, basep + i, size); + + for (r = 0; (c = r * 2 + size) < i; r = c) { + if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) + c += size; + if (cmp(basep + r, basep + c, opaque) > 0) + break; + swap(basep + r, basep + c, size); + } + } + } +} + +static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) +{ + return cmp(a, b, opaque) < 0 ? + (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : + (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); +} + +/* pointer based version with local stack and insertion sort threshhold */ +void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) +{ + struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; + uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; + size_t m4, i, lt, gt, span, span2; + int c, depth; + exchange_f swap = exchange_func(base, size); + exchange_f swap_block = exchange_func(base, size | 128); + + if (nmemb < 2 || size <= 0) + return; + + sp->base = (uint8_t *)base; + sp->count = nmemb; + sp->depth = 0; + sp++; + + while (sp > stack) { + sp--; + ptr = sp->base; + nmemb = sp->count; + depth = sp->depth; + + while (nmemb > 6) { + if (++depth > 50) { + /* depth check to ensure worst case logarithmic time */ + heapsortx(ptr, nmemb, size, cmp, opaque); + nmemb = 0; + break; + } + /* select median of 3 from 1/4, 1/2, 3/4 positions */ + /* should use median of 5 or 9? */ + m4 = (nmemb >> 2) * size; + m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); + swap(ptr, m, size); /* move the pivot to the start or the array */ + i = lt = 1; + pi = plt = ptr + size; + gt = nmemb; + pj = pgt = top = ptr + nmemb * size; + for (;;) { + while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { + if (c == 0) { + swap(plt, pi, size); + lt++; + plt += size; + } + i++; + pi += size; + } + while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { + if (c == 0) { + gt--; + pgt -= size; + swap(pgt, pj, size); + } + } + if (pi >= pj) + break; + swap(pi, pj, size); + i++; + pi += size; + } + /* array has 4 parts: + * from 0 to lt excluded: elements identical to pivot + * from lt to pi excluded: elements smaller than pivot + * from pi to gt excluded: elements greater than pivot + * from gt to n excluded: elements identical to pivot + */ + /* move elements identical to pivot in the middle of the array: */ + /* swap values in ranges [0..lt[ and [i-lt..i[ + swapping the smallest span between lt and i-lt is sufficient + */ + span = plt - ptr; + span2 = pi - plt; + lt = i - lt; + if (span > span2) + span = span2; + swap_block(ptr, pi - span, span); + /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ + swapping the smallest span between top-gt and gt-i is sufficient + */ + span = top - pgt; + span2 = pgt - pi; + pgt = top - span2; + gt = nmemb - (gt - i); + if (span > span2) + span = span2; + swap_block(pi, top - span, span); + + /* now array has 3 parts: + * from 0 to lt excluded: elements smaller than pivot + * from lt to gt excluded: elements identical to pivot + * from gt to n excluded: elements greater than pivot + */ + /* stack the larger segment and keep processing the smaller one + to minimize stack use for pathological distributions */ + if (lt > nmemb - gt) { + sp->base = ptr; + sp->count = lt; + sp->depth = depth; + sp++; + ptr = pgt; + nmemb -= gt; + } else { + sp->base = pgt; + sp->count = nmemb - gt; + sp->depth = depth; + sp++; + nmemb = lt; + } + } + /* Use insertion sort for small fragments */ + for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { + for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) + swap(pj, pj - size, size); + } + } +} + +#endif diff --git a/quickjs-ng/cutils.h b/quickjs/cutils.h similarity index 51% rename from quickjs-ng/cutils.h rename to quickjs/cutils.h index 5129c3c..cf3cc0e 100644 --- a/quickjs-ng/cutils.h +++ b/quickjs/cutils.h @@ -25,38 +25,17 @@ #ifndef CUTILS_H #define CUTILS_H -#include #include #include #include -#include - -#ifdef __cplusplus -extern "C" { -#endif #if defined(_MSC_VER) -#include -#include -#define alloca _alloca -#define ssize_t ptrdiff_t -#endif -#if defined(__APPLE__) -#include -#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__GLIBC__) -#include -#elif defined(__FreeBSD__) -#include -#elif defined(_WIN32) -#include -#endif -#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__) -#include -#include -#endif -#if !defined(_WIN32) -#include -#include + #if !defined(NOMINMAX) + #define NOMINMAX // For windows.h + #endif + #include + #include + #include // For timeval struct, etc #endif #if defined(_MSC_VER) && !defined(__clang__) @@ -68,13 +47,18 @@ extern "C" { # define __attribute__(x) # define __attribute(x) #else -# define likely(x) __builtin_expect(!!(x), 1) -# define unlikely(x) __builtin_expect(!!(x), 0) -# define force_inline inline __attribute__((always_inline)) -# define no_inline __attribute__((noinline)) -# define __maybe_unused __attribute__((unused)) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define force_inline inline __attribute__((always_inline)) +#define no_inline __attribute__((noinline)) +#define __maybe_unused __attribute__((unused)) #endif +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s + #if defined(_MSC_VER) && !defined(__clang__) #include #define INF INFINITY @@ -89,58 +73,40 @@ extern "C" { #endif #ifndef countof #define countof(x) (sizeof(x) / sizeof((x)[0])) -#ifndef endof -#define endof(x) ((x) + countof(x)) -#endif #endif #ifndef container_of /* return the pointer of type 'type *' containing 'ptr' as field 'member' */ #define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member))) #endif -#if defined(_MSC_VER) || defined(__cplusplus) -#define minimum_length(n) n +#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define minimum_length(n) static n #else -#define minimum_length(n) static n +#define minimum_length(n) n #endif -/* Borrowed from Folly */ -#ifndef JS_PRINTF_FORMAT -#ifdef _MSC_VER -#include -#define JS_PRINTF_FORMAT _Printf_format_string_ -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) -#else -#define JS_PRINTF_FORMAT -#if !defined(__clang__) && defined(__GNUC__) -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ - __attribute__((format(gnu_printf, format_param, dots_param))) -#else -#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ - __attribute__((format(printf, format_param, dots_param))) -#endif -#endif +typedef int BOOL; + +#ifndef FALSE +enum { + FALSE = 0, + TRUE = 1, +}; #endif -#if defined(PATH_MAX) -# define JS__PATH_MAX PATH_MAX -#elif defined(_WIN32) -# define JS__PATH_MAX 32767 -#else -# define JS__PATH_MAX 8192 +#if defined(_MSC_VER) +int gettimeofday(struct timeval * tp, struct timezone * tzp); #endif -void js__pstrcpy(char *buf, int buf_size, const char *str); -char *js__pstrcat(char *buf, int buf_size, const char *s); -int js__strstart(const char *str, const char *val, const char **ptr); -int js__has_suffix(const char *str, const char *suffix); +void pstrcpy(char *buf, int buf_size, const char *str); +char *pstrcat(char *buf, int buf_size, const char *s); +int strstart(const char *str, const char *val, const char **ptr); +int has_suffix(const char *str, const char *suffix); -static inline uint8_t is_be(void) { - union { - uint16_t a; - uint8_t b; - } u = { 0x100 }; - return u.b; +/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */ +static inline void memcpy_no_ub(void *dest, const void *src, size_t n) { + if (n) + memcpy(dest, src, n); } static inline int max_int(int a, int b) @@ -347,89 +313,6 @@ static inline uint64_t bswap64(uint64_t v) } #endif -static inline void inplace_bswap16(uint8_t *tab) { - put_u16(tab, bswap16(get_u16(tab))); -} - -static inline void inplace_bswap32(uint8_t *tab) { - put_u32(tab, bswap32(get_u32(tab))); -} - -static inline double fromfp16(uint16_t v) { - double d, s; - int e; - if ((v & 0x7C00) == 0x7C00) { - d = (v & 0x3FF) ? NAN : INFINITY; - } else { - d = (v & 0x3FF) / 1024.; - e = (v & 0x7C00) >> 10; - if (e == 0) { - e = -14; - } else { - d += 1; - e -= 15; - } - d = scalbn(d, e); - } - s = (v & 0x8000) ? -1.0 : 1.0; - return d * s; -} - -static inline uint16_t tofp16(double d) { - uint16_t f, s; - double t; - int e; - s = 0; - if (copysign(1, d) < 0) { // preserve sign when |d| is negative zero - d = -d; - s = 0x8000; - } - if (isinf(d)) - return s | 0x7C00; - if (isnan(d)) - return s | 0x7C01; - if (d == 0) - return s | 0; - d = 2 * frexp(d, &e); - e--; - if (e > 15) - return s | 0x7C00; // out of range, return +/-infinity - if (e < -25) { - d = 0; - e = 0; - } else if (e < -14) { - d = scalbn(d, e + 14); - e = 0; - } else { - d -= 1; - e += 15; - } - d *= 1024.; - f = (uint16_t)d; - t = d - f; - if (t < 0.5) - goto done; - if (t == 0.5) - if ((f & 1) == 0) - goto done; - // adjust for rounding - if (++f == 1024) { - f = 0; - if (++e == 31) - return s | 0x7C00; // out of range, return +/-infinity - } -done: - return s | (e << 10) | f; -} - -static inline int isfp16nan(uint16_t v) { - return (v & 0x7FFF) > 0x7C00; -} - -static inline int isfp16zero(uint16_t v) { - return (v & 0x7FFF) == 0; -} - /* XXX: should take an extra argument to pass slack information to the caller */ typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); @@ -437,73 +320,92 @@ typedef struct DynBuf { uint8_t *buf; size_t size; size_t allocated_size; - bool error; /* true if a memory allocation error occurred */ + BOOL error; /* true if a memory allocation error occurred */ DynBufReallocFunc *realloc_func; void *opaque; /* for realloc_func */ } DynBuf; void dbuf_init(DynBuf *s); void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); -int dbuf_realloc(DynBuf *s, size_t new_size); -int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len); -int dbuf_put(DynBuf *s, const void *data, size_t len); +int dbuf_claim(DynBuf *s, size_t len); +int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); int dbuf_put_self(DynBuf *s, size_t offset, size_t len); -int dbuf_putc(DynBuf *s, uint8_t c); int dbuf_putstr(DynBuf *s, const char *str); +int __dbuf_putc(DynBuf *s, uint8_t c); +int __dbuf_put_u16(DynBuf *s, uint16_t val); +int __dbuf_put_u32(DynBuf *s, uint32_t val); +int __dbuf_put_u64(DynBuf *s, uint64_t val); + +static inline int dbuf_putc(DynBuf *s, uint8_t val) +{ + if (unlikely((s->allocated_size - s->size) < 1)) { + return __dbuf_putc(s, val); + } else { + s->buf[s->size++] = val; + return 0; + } +} + static inline int dbuf_put_u16(DynBuf *s, uint16_t val) { - return dbuf_put(s, (uint8_t *)&val, 2); + if (unlikely((s->allocated_size - s->size) < 2)) { + return __dbuf_put_u16(s, val); + } else { + put_u16(s->buf + s->size, val); + s->size += 2; + return 0; + } } + static inline int dbuf_put_u32(DynBuf *s, uint32_t val) { - return dbuf_put(s, (uint8_t *)&val, 4); + if (unlikely((s->allocated_size - s->size) < 4)) { + return __dbuf_put_u32(s, val); + } else { + put_u32(s->buf + s->size, val); + s->size += 4; + return 0; + } } + static inline int dbuf_put_u64(DynBuf *s, uint64_t val) { - return dbuf_put(s, (uint8_t *)&val, 8); + if (unlikely((s->allocated_size - s->size) < 8)) { + return __dbuf_put_u64(s, val); + } else { + put_u64(s->buf + s->size, val); + s->size += 8; + return 0; + } } -int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...); + +int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, + const char *fmt, ...); void dbuf_free(DynBuf *s); -static inline bool dbuf_error(DynBuf *s) { +static inline BOOL dbuf_error(DynBuf *s) { return s->error; } static inline void dbuf_set_error(DynBuf *s) { - s->error = true; + s->error = TRUE; } -/*---- UTF-8 and UTF-16 handling ----*/ +#define UTF8_CHAR_LEN_MAX 6 -#define UTF8_CHAR_LEN_MAX 4 +int unicode_to_utf8(uint8_t *buf, unsigned int c); +int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp); -enum { - UTF8_PLAIN_ASCII = 0, // 7-bit ASCII plain text - UTF8_NON_ASCII = 1, // has non ASCII code points (8-bit or more) - UTF8_HAS_16BIT = 2, // has 16-bit code points - UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs - UTF8_HAS_ERRORS = 8, // has encoding errors -}; -int utf8_scan(const char *buf, size_t len, size_t *plen); -size_t utf8_encode_len(uint32_t c); -size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c); -uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp); -uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp); -size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len); -size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len); -size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len); -size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len); - -static inline bool is_surrogate(uint32_t c) +static inline BOOL is_surrogate(uint32_t c) { return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF } -static inline bool is_hi_surrogate(uint32_t c) +static inline BOOL is_hi_surrogate(uint32_t c) { return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF } -static inline bool is_lo_surrogate(uint32_t c) +static inline BOOL is_lo_surrogate(uint32_t c) { return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF } @@ -520,7 +422,7 @@ static inline uint32_t get_lo_surrogate(uint32_t c) static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo) { - return 65536 + 1024 * (hi & 1023) + (lo & 1023); + return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00); } static inline int from_hex(int c) @@ -535,14 +437,6 @@ static inline int from_hex(int c) return -1; } -static inline uint8_t is_upper_ascii(uint8_t c) { - return c >= 'A' && c <= 'Z'; -} - -static inline uint8_t to_upper_ascii(uint8_t c) { - return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c; -} - void rqsort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *, void *), void *arg); @@ -567,75 +461,60 @@ static inline double uint64_as_float64(uint64_t u64) return u.d; } -int64_t js__gettimeofday_us(void); -uint64_t js__hrtime_ns(void); +static inline double fromfp16(uint16_t v) +{ + double d; + uint32_t v1; + v1 = v & 0x7fff; + if (unlikely(v1 >= 0x7c00)) + v1 += 0x1f8000; /* NaN or infinity */ + d = uint64_as_float64(((uint64_t)(v >> 15) << 63) | ((uint64_t)v1 << (52 - 10))); + return d * 0x1p1008; +} + +static inline uint16_t tofp16(double d) +{ + uint64_t a, addend; + uint32_t v, sgn; + int shift; + + a = float64_as_uint64(d); + sgn = a >> 63; + a = a & 0x7fffffffffffffff; + if (unlikely(a > 0x7ff0000000000000)) { + /* nan */ + v = 0x7c01; + } else if (a < 0x3f10000000000000) { /* 0x1p-14 */ + /* subnormal f16 number or zero */ + if (a <= 0x3e60000000000000) { /* 0x1p-25 */ + v = 0x0000; /* zero */ + } else { + shift = 1051 - (a >> 52); + a = ((uint64_t)1 << 52) | (a & (((uint64_t)1 << 52) - 1)); + addend = ((a >> shift) & 1) + (((uint64_t)1 << (shift - 1)) - 1); + v = (a + addend) >> shift; + } + } else { + /* normal number or infinity */ + a -= 0x3f00000000000000; /* adjust the exponent */ + /* round */ + addend = ((a >> (52 - 10)) & 1) + (((uint64_t)1 << (52 - 11)) - 1); + v = (a + addend) >> (52 - 10); + /* overflow ? */ + if (unlikely(v > 0x7c00)) + v = 0x7c00; + } + return v | (sgn << 15); +} -static inline size_t js__malloc_usable_size(const void *ptr) +static inline int isfp16nan(uint16_t v) { -#if defined(__APPLE__) - return malloc_size(ptr); -#elif defined(_WIN32) - return _msize((void *)ptr); -#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__GLIBC__) - return malloc_usable_size((void *)ptr); -#else - return 0; -#endif + return (v & 0x7FFF) > 0x7C00; } -int js_exepath(char* buffer, size_t* size); - -/* Cross-platform threading APIs. */ - -#if defined(EMSCRIPTEN) || defined(__wasi__) - -#define JS_HAVE_THREADS 0 - -#else - -#define JS_HAVE_THREADS 1 - -#if defined(_WIN32) -#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT -typedef INIT_ONCE js_once_t; -typedef CRITICAL_SECTION js_mutex_t; -typedef CONDITION_VARIABLE js_cond_t; -typedef HANDLE js_thread_t; -#else -#define JS_ONCE_INIT PTHREAD_ONCE_INIT -typedef pthread_once_t js_once_t; -typedef pthread_mutex_t js_mutex_t; -typedef pthread_cond_t js_cond_t; -typedef pthread_t js_thread_t; -#endif - -void js_once(js_once_t *guard, void (*callback)(void)); - -void js_mutex_init(js_mutex_t *mutex); -void js_mutex_destroy(js_mutex_t *mutex); -void js_mutex_lock(js_mutex_t *mutex); -void js_mutex_unlock(js_mutex_t *mutex); - -void js_cond_init(js_cond_t *cond); -void js_cond_destroy(js_cond_t *cond); -void js_cond_signal(js_cond_t *cond); -void js_cond_broadcast(js_cond_t *cond); -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex); -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout); - -enum { - JS_THREAD_CREATE_DETACHED = 1, -}; - -// creates threads with 2 MB stacks (glibc default) -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, - int flags); -int js_thread_join(js_thread_t thrd); - -#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */ - -#ifdef __cplusplus -} /* extern "C" { */ -#endif +static inline int isfp16zero(uint16_t v) +{ + return (v & 0x7FFF) == 0; +} #endif /* CUTILS_H */ diff --git a/quickjs/doc/quickjs.texi b/quickjs/doc/quickjs.texi new file mode 100644 index 0000000..0b8c744 --- /dev/null +++ b/quickjs/doc/quickjs.texi @@ -0,0 +1,1073 @@ +\input texinfo + +@iftex +@afourpaper +@headings double +@end iftex + +@include version.texi + +@titlepage +@afourpaper +@sp 7 +@center @titlefont{QuickJS Javascript Engine} +@sp 3 +@center Version: @value{VERSION} +@end titlepage + +@setfilename spec.info +@settitle QuickJS Javascript Engine + +@contents + +@chapter Introduction + +QuickJS (version @value{VERSION}) is a small and embeddable Javascript +engine. It supports most of the ES2024 specification +@footnote{@url{https://tc39.es/ecma262/2024 }} including modules, +asynchronous generators, proxies and BigInt. + +@section Main Features + +@itemize + +@item Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple ``hello world'' program. + +@item Fast interpreter with very low startup time: runs the 77000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in less than 2 minutes on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds. + +@item Almost complete ES2024 support including modules, asynchronous +generators and full Annex B support (legacy web compatibility). Some +features from the upcoming ES2024 specification +@footnote{@url{https://tc39.es/ecma262/}} are also supported. + +@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2024 features. + +@item Compile Javascript sources to executables with no external dependency. + +@item Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal. + +@item Command line interpreter with contextual colorization and completion implemented in Javascript. + +@item Small built-in standard library with C library wrappers. + +@end itemize + +@chapter Usage + +@section Installation + +A Makefile is provided to compile the engine on Linux or MacOS/X. A +preliminary Windows support is available thru cross compilation on a +Linux host with the MingGW tools. + +Edit the top of the @code{Makefile} if you wish to select specific +options then run @code{make}. + +You can type @code{make install} as root if you wish to install the binaries and support files to +@code{/usr/local} (this is not necessary to use QuickJS). + +Note: On some OSes atomic operations are not available or need a +specific library. If you get related errors, you should either add +@code{-latomics} in the Makefile @code{LIBS} variable or disable +@code{CONFIG_ATOMICS} in @file{quickjs.c}. + +@section Quick start + +@code{qjs} is the command line interpreter (Read-Eval-Print Loop). You can pass +Javascript files and/or expressions as arguments to execute them: + +@example +./qjs examples/hello.js +@end example + +@code{qjsc} is the command line compiler: + +@example +./qjsc -o hello examples/hello.js +./hello +@end example + +generates a @code{hello} executable with no external dependency. + +@section Command line options + +@subsection @code{qjs} interpreter + +@verbatim +usage: qjs [options] [file [args]] +@end verbatim + +Options are: +@table @code +@item -h +@item --help +List options. + +@item -e @code{EXPR} +@item --eval @code{EXPR} +Evaluate EXPR. + +@item -i +@item --interactive +Go to interactive mode (it is not the default when files are provided on the command line). + +@item -m +@item --module +Load as ES6 module (default=autodetect). A module is autodetected if +the filename extension is @code{.mjs} or if the first keyword of the +source is @code{import}. + +@item --script +Load as ES6 script (default=autodetect). + +@item -I file +@item --include file +Include an additional file. + +@end table + +Advanced options are: + +@table @code +@item --std +Make the @code{std} and @code{os} modules available to the loaded +script even if it is not a module. + +@item -d +@item --dump +Dump the memory usage stats. + +@item -q +@item --quit +just instantiate the interpreter and quit. + +@end table + +@subsection @code{qjsc} compiler + +@verbatim +usage: qjsc [options] [files] +@end verbatim + +Options are: +@table @code +@item -c +Only output bytecode in a C file. The default is to output an executable file. +@item -e +Output @code{main()} and bytecode in a C file. The default is to output an +executable file. +@item -o output +Set the output filename (default = @file{out.c} or @file{a.out}). + +@item -N cname +Set the C name of the generated data. + +@item -m +Compile as Javascript module (default=autodetect). + +@item -D module_name +Compile a dynamically loaded module and its dependencies. This option +is needed when your code uses the @code{import} keyword or the +@code{os.Worker} constructor because the compiler cannot statically +find the name of the dynamically loaded modules. + +@item -M module_name[,cname] +Add initialization code for an external C module. See the +@code{c_module} example. + +@item -x +Byte swapped output (only used for cross compilation). + +@item -flto +Use link time optimization. The compilation is slower but the +executable is smaller and faster. This option is automatically set +when the @code{-fno-x} options are used. + +@item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint] +Disable selected language features to produce a smaller executable file. + +@end table + +@section Built-in tests + +Run @code{make test} to run the few built-in tests included in the +QuickJS archive. + +@section Test262 (ECMAScript Test Suite) + +A test262 runner is included in the QuickJS archive. The test262 tests +can be installed in the QuickJS source directory with: + +@example +git clone https://github.com/tc39/test262.git test262 +cd test262 +patch -p1 < ../tests/test262.patch +cd .. +@end example + +The patch adds the implementation specific @code{harness} functions +and optimizes the inefficient RegExp character classes and Unicode +property escapes tests (the tests themselves are not modified, only a +slow string initialization function is optimized). + +The tests can be run with +@example +make test2 +@end example + +The configuration files @code{test262.conf} +(resp. @code{test262o.conf} for the old ES5.1 tests@footnote{The old +ES5.1 tests can be extracted with @code{git clone --single-branch +--branch es5-tests https://github.com/tc39/test262.git test262o}})) +contain the options to run the various tests. Tests can be excluded +based on features or filename. + +The file @code{test262_errors.txt} contains the current list of +errors. The runner displays a message when a new error appears or when +an existing error is corrected or modified. Use the @code{-u} option +to update the current list of errors (or @code{make test2-update}). + +The file @code{test262_report.txt} contains the logs of all the +tests. It is useful to have a clearer analysis of a particular +error. In case of crash, the last line corresponds to the failing +test. + +Use the syntax @code{./run-test262 -c test262.conf -f filename.js} to +run a single test. Use the syntax @code{./run-test262 -c test262.conf +N} to start testing at test number @code{N}. + +For more information, run @code{./run-test262} to see the command line +options of the test262 runner. + +@code{run-test262} accepts the @code{-N} option to be invoked from +@code{test262-harness}@footnote{@url{https://github.com/bterlson/test262-harness}} +thru @code{eshost}. Unless you want to compare QuickJS with other +engines under the same conditions, we do not recommend to run the +tests this way as it is much slower (typically half an hour instead of +about 100 seconds). + +@chapter Specifications + +@section Language support + +@subsection ES2024 support + +The ES2024 specification is almost fully supported including the Annex +B (legacy web compatibility) and the Unicode related features. + +The following features are not supported yet: + +@itemize + +@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.} + +@item Atomics.waitAsync + +@end itemize + +@subsection ECMA402 + +ECMA402 (Internationalization API) is not supported. + +@section Modules + +ES6 modules are fully supported. The default name resolution is the +following: + +@itemize + +@item Module names with a leading @code{.} or @code{..} are relative +to the current module path. + +@item Module names without a leading @code{.} or @code{..} are system +modules, such as @code{std} or @code{os}. + +@item Module names ending with @code{.so} are native modules using the +QuickJS C API. + +@end itemize + +@section Standard library + +The standard library is included by default in the command line +interpreter. It contains the two modules @code{std} and @code{os} and +a few global objects. + +@subsection Global objects + +@table @code +@item scriptArgs +Provides the command line arguments. The first argument is the script name. +@item print(...args) +Print the arguments separated by spaces and a trailing newline. +@item console.log(...args) +Same as print(). + +@end table + +@subsection @code{std} module + +The @code{std} module provides wrappers to the libc @file{stdlib.h} +and @file{stdio.h} and a few other utilities. + +Available exports: + +@table @code + +@item exit(n) +Exit the process. + +@item evalScript(str, options = undefined) +Evaluate the string @code{str} as a script (global +eval). @code{options} is an optional object containing the following +optional properties: + + @table @code + @item backtrace_barrier + Boolean (default = false). If true, error backtraces do not list the + stack frames below the evalScript. + @item async + Boolean (default = false). If true, @code{await} is accepted in the + script and a promise is returned. The promise is resolved with an + object whose @code{value} property holds the value returned by the + script. + @end table + +@item loadScript(filename) +Evaluate the file @code{filename} as a script (global eval). + +@item loadFile(filename) +Load the file @code{filename} and return it as a string assuming UTF-8 +encoding. Return @code{null} in case of I/O error. + +@item open(filename, flags, errorObj = undefined) +Open a file (wrapper to the libc @code{fopen()}). Return the FILE +object or @code{null} in case of I/O error. If @code{errorObj} is not +undefined, set its @code{errno} property to the error code or to 0 if +no error occured. + +@item popen(command, flags, errorObj = undefined) +Open a process by creating a pipe (wrapper to the libc +@code{popen()}). Return the FILE +object or @code{null} in case of I/O error. If @code{errorObj} is not +undefined, set its @code{errno} property to the error code or to 0 if +no error occured. + +@item fdopen(fd, flags, errorObj = undefined) +Open a file from a file handle (wrapper to the libc +@code{fdopen()}). Return the FILE +object or @code{null} in case of I/O error. If @code{errorObj} is not +undefined, set its @code{errno} property to the error code or to 0 if +no error occured. + +@item tmpfile(errorObj = undefined) +Open a temporary file. Return the FILE +object or @code{null} in case of I/O error. If @code{errorObj} is not +undefined, set its @code{errno} property to the error code or to 0 if +no error occured. + +@item puts(str) +Equivalent to @code{std.out.puts(str)}. + +@item printf(fmt, ...args) +Equivalent to @code{std.out.printf(fmt, ...args)}. + +@item sprintf(fmt, ...args) +Equivalent to the libc sprintf(). + +@item in +@item out +@item err +Wrappers to the libc file @code{stdin}, @code{stdout}, @code{stderr}. + +@item SEEK_SET +@item SEEK_CUR +@item SEEK_END +Constants for seek(). + +@item Error + +Enumeration object containing the integer value of common errors +(additional error codes may be defined): + + @table @code + @item EINVAL + @item EIO + @item EACCES + @item EEXIST + @item ENOSPC + @item ENOSYS + @item EBUSY + @item ENOENT + @item EPERM + @item EPIPE + @end table + +@item strerror(errno) +Return a string that describes the error @code{errno}. + +@item gc() +Manually invoke the cycle removal algorithm. The cycle removal +algorithm is automatically started when needed, so this function is +useful in case of specific memory constraints or for testing. + +@item getenv(name) +Return the value of the environment variable @code{name} or +@code{undefined} if it is not defined. + +@item setenv(name, value) +Set the value of the environment variable @code{name} to the string +@code{value}. + +@item unsetenv(name) +Delete the environment variable @code{name}. + +@item getenviron() +Return an object containing the environment variables as key-value pairs. + +@item urlGet(url, options = undefined) + +Download @code{url} using the @file{curl} command line +utility. @code{options} is an optional object containing the following +optional properties: + + @table @code + @item binary + Boolean (default = false). If true, the response is an ArrayBuffer + instead of a string. When a string is returned, the data is assumed + to be UTF-8 encoded. + + @item full + + Boolean (default = false). If true, return the an object contains + the properties @code{response} (response content), + @code{responseHeaders} (headers separated by CRLF), @code{status} + (status code). @code{response} is @code{null} is case of protocol or + network error. If @code{full} is false, only the response is + returned if the status is between 200 and 299. Otherwise @code{null} + is returned. + + @end table + +@item parseExtJSON(str) + + Parse @code{str} using a superset of @code{JSON.parse}. The superset + is very close to the JSON5 specification. The following extensions + are accepted: + + @itemize + @item Single line and multiline comments + @item unquoted properties (ASCII-only Javascript identifiers) + @item trailing comma in array and object definitions + @item single quoted strings + @item @code{\v} escape and multi-line strings with trailing @code{\} + @item @code{\f} and @code{\v} are accepted as space characters + @item leading plus or decimal point in numbers + @item hexadecimal (@code{0x} prefix), octal (@code{0o} prefix) and binary (@code{0b} prefix) integers + @item @code{NaN} and @code{Infinity} are accepted as numbers + @end itemize +@end table + +FILE prototype: + +@table @code +@item close() +Close the file. Return 0 if OK or @code{-errno} in case of I/O error. +@item puts(str) +Outputs the string with the UTF-8 encoding. +@item printf(fmt, ...args) +Formatted printf. + +The same formats as the standard C library @code{printf} are +supported. Integer format types (e.g. @code{%d}) truncate the Numbers +or BigInts to 32 bits. Use the @code{l} modifier (e.g. @code{%ld}) to +truncate to 64 bits. + +@item flush() +Flush the buffered file. +@item seek(offset, whence) +Seek to a give file position (whence is +@code{std.SEEK_*}). @code{offset} can be a number or a bigint. Return +0 if OK or @code{-errno} in case of I/O error. +@item tell() +Return the current file position. +@item tello() +Return the current file position as a bigint. +@item eof() +Return true if end of file. +@item fileno() +Return the associated OS handle. +@item error() +Return true if there was an error. +@item clearerr() +Clear the error indication. + +@item read(buffer, position, length) +Read @code{length} bytes from the file to the ArrayBuffer @code{buffer} at byte +position @code{position} (wrapper to the libc @code{fread}). + +@item write(buffer, position, length) +Write @code{length} bytes to the file from the ArrayBuffer @code{buffer} at byte +position @code{position} (wrapper to the libc @code{fwrite}). + +@item getline() +Return the next line from the file, assuming UTF-8 encoding, excluding +the trailing line feed. + +@item readAsString(max_size = undefined) +Read @code{max_size} bytes from the file and return them as a string +assuming UTF-8 encoding. If @code{max_size} is not present, the file +is read up its end. + +@item getByte() +Return the next byte from the file. Return -1 if the end of file is reached. + +@item putByte(c) +Write one byte to the file. +@end table + +@subsection @code{os} module + +The @code{os} module provides Operating System specific functions: + +@itemize +@item low level file access +@item signals +@item timers +@item asynchronous I/O +@item workers (threads) +@end itemize + +The OS functions usually return 0 if OK or an OS specific negative +error code. + +Available exports: + +@table @code +@item open(filename, flags, mode = 0o666) +Open a file. Return a handle or < 0 if error. + +@item O_RDONLY +@item O_WRONLY +@item O_RDWR +@item O_APPEND +@item O_CREAT +@item O_EXCL +@item O_TRUNC +POSIX open flags. + +@item O_TEXT +(Windows specific). Open the file in text mode. The default is binary mode. + +@item close(fd) +Close the file handle @code{fd}. + +@item seek(fd, offset, whence) +Seek in the file. Use @code{std.SEEK_*} for +@code{whence}. @code{offset} is either a number or a bigint. If +@code{offset} is a bigint, a bigint is returned too. + +@item read(fd, buffer, offset, length) +Read @code{length} bytes from the file handle @code{fd} to the +ArrayBuffer @code{buffer} at byte position @code{offset}. +Return the number of read bytes or < 0 if error. + +@item write(fd, buffer, offset, length) +Write @code{length} bytes to the file handle @code{fd} from the +ArrayBuffer @code{buffer} at byte position @code{offset}. +Return the number of written bytes or < 0 if error. + +@item isatty(fd) +Return @code{true} is @code{fd} is a TTY (terminal) handle. + +@item ttyGetWinSize(fd) +Return the TTY size as @code{[width, height]} or @code{null} if not available. + +@item ttySetRaw(fd) +Set the TTY in raw mode. + +@item remove(filename) +Remove a file. Return 0 if OK or @code{-errno}. + +@item rename(oldname, newname) +Rename a file. Return 0 if OK or @code{-errno}. + +@item realpath(path) +Return @code{[str, err]} where @code{str} is the canonicalized absolute +pathname of @code{path} and @code{err} the error code. + +@item getcwd() +Return @code{[str, err]} where @code{str} is the current working directory +and @code{err} the error code. + +@item chdir(path) +Change the current directory. Return 0 if OK or @code{-errno}. + +@item mkdir(path, mode = 0o777) +Create a directory at @code{path}. Return 0 if OK or @code{-errno}. + +@item stat(path) +@item lstat(path) + +Return @code{[obj, err]} where @code{obj} is an object containing the +file status of @code{path}. @code{err} is the error code. The +following fields are defined in @code{obj}: dev, ino, mode, nlink, +uid, gid, rdev, size, blocks, atime, mtime, ctime. The times are +specified in milliseconds since 1970. @code{lstat()} is the same as +@code{stat()} excepts that it returns information about the link +itself. + +@item S_IFMT +@item S_IFIFO +@item S_IFCHR +@item S_IFDIR +@item S_IFBLK +@item S_IFREG +@item S_IFSOCK +@item S_IFLNK +@item S_ISGID +@item S_ISUID +Constants to interpret the @code{mode} property returned by +@code{stat()}. They have the same value as in the C system header +@file{sys/stat.h}. + +@item utimes(path, atime, mtime) +Change the access and modification times of the file @code{path}. The +times are specified in milliseconds since 1970. Return 0 if OK or @code{-errno}. + +@item symlink(target, linkpath) +Create a link at @code{linkpath} containing the string @code{target}. Return 0 if OK or @code{-errno}. + +@item readlink(path) +Return @code{[str, err]} where @code{str} is the link target and @code{err} +the error code. + +@item readdir(path) +Return @code{[array, err]} where @code{array} is an array of strings +containing the filenames of the directory @code{path}. @code{err} is +the error code. + +@item setReadHandler(fd, func) +Add a read handler to the file handle @code{fd}. @code{func} is called +each time there is data pending for @code{fd}. A single read handler +per file handle is supported. Use @code{func = null} to remove the +handler. + +@item setWriteHandler(fd, func) +Add a write handler to the file handle @code{fd}. @code{func} is +called each time data can be written to @code{fd}. A single write +handler per file handle is supported. Use @code{func = null} to remove +the handler. + +@item signal(signal, func) +Call the function @code{func} when the signal @code{signal} +happens. Only a single handler per signal number is supported. Use +@code{null} to set the default handler or @code{undefined} to ignore +the signal. Signal handlers can only be defined in the main thread. + +@item SIGINT +@item SIGABRT +@item SIGFPE +@item SIGILL +@item SIGSEGV +@item SIGTERM +POSIX signal numbers. + +@item kill(pid, sig) +Send the signal @code{sig} to the process @code{pid}. + +@item exec(args[, options]) +Execute a process with the arguments @code{args}. @code{options} is an +object containing optional parameters: + + @table @code + @item block + Boolean (default = true). If true, wait until the process is + terminated. In this case, @code{exec} return the exit code if positive + or the negated signal number if the process was interrupted by a + signal. If false, do not block and return the process id of the child. + + @item usePath + Boolean (default = true). If true, the file is searched in the + @code{PATH} environment variable. + + @item file + String (default = @code{args[0]}). Set the file to be executed. + + @item cwd + String. If present, set the working directory of the new process. + + @item stdin + @item stdout + @item stderr + If present, set the handle in the child for stdin, stdout or stderr. + + @item env + Object. If present, set the process environment from the object + key-value pairs. Otherwise use the same environment as the current + process. + + @item uid + Integer. If present, the process uid with @code{setuid}. + + @item gid + Integer. If present, the process gid with @code{setgid}. + + @end table + +@item getpid() +Return the current process ID. + +@item waitpid(pid, options) +@code{waitpid} Unix system call. Return the array @code{[ret, +status]}. @code{ret} contains @code{-errno} in case of error. + +@item WNOHANG +Constant for the @code{options} argument of @code{waitpid}. + +@item dup(fd) +@code{dup} Unix system call. + +@item dup2(oldfd, newfd) +@code{dup2} Unix system call. + +@item pipe() +@code{pipe} Unix system call. Return two handles as @code{[read_fd, +write_fd]} or null in case of error. + +@item sleep(delay_ms) +Sleep during @code{delay_ms} milliseconds. + +@item sleepAsync(delay_ms) +Asynchronouse sleep during @code{delay_ms} milliseconds. Returns a promise. Example: +@example +await os.sleepAsync(500); +@end example + +@item now() +Return a timestamp in milliseconds with more precision than +@code{Date.now()}. The time origin is unspecified and is normally not +impacted by system clock adjustments. + +@item setTimeout(func, delay) +Call the function @code{func} after @code{delay} ms. Return a handle +to the timer. + +@item clearTimeout(handle) +Cancel a timer. + +@item platform +Return a string representing the platform: @code{"linux"}, @code{"darwin"}, +@code{"win32"} or @code{"js"}. + +@item Worker(module_filename) +Constructor to create a new thread (worker) with an API close to the +@code{WebWorkers}. @code{module_filename} is a string specifying the +module filename which is executed in the newly created thread. As for +dynamically imported module, it is relative to the current script or +module path. Threads normally don't share any data and communicate +between each other with messages. Nested workers are not supported. An +example is available in @file{tests/test_worker.js}. + +The worker class has the following static properties: + + @table @code + @item parent + In the created worker, @code{Worker.parent} represents the parent + worker and is used to send or receive messages. + @end table + +The worker instances have the following properties: + + @table @code + @item postMessage(msg) + + Send a message to the corresponding worker. @code{msg} is cloned in + the destination worker using an algorithm similar to the @code{HTML} + structured clone algorithm. @code{SharedArrayBuffer} are shared + between workers. + + Current limitations: @code{Map} and @code{Set} are not supported + yet. + + @item onmessage + + Getter and setter. Set a function which is called each time a + message is received. The function is called with a single + argument. It is an object with a @code{data} property containing the + received message. The thread is not terminated if there is at least + one non @code{null} @code{onmessage} handler. + + @end table + +@end table + +@section QuickJS C API + +The C API was designed to be simple and efficient. The C API is +defined in the header @code{quickjs.h}. + +@subsection Runtime and contexts + +@code{JSRuntime} represents a Javascript runtime corresponding to an +object heap. Several runtimes can exist at the same time but they +cannot exchange objects. Inside a given runtime, no multi-threading is +supported. + +@code{JSContext} represents a Javascript context (or Realm). Each +JSContext has its own global objects and system objects. There can be +several JSContexts per JSRuntime and they can share objects, similar +to frames of the same origin sharing Javascript objects in a +web browser. + +@subsection JSValue + +@code{JSValue} represents a Javascript value which can be a primitive +type or an object. Reference counting is used, so it is important to +explicitly duplicate (@code{JS_DupValue()}, increment the reference +count) or free (@code{JS_FreeValue()}, decrement the reference count) +JSValues. + +@subsection C functions + +C functions can be created with +@code{JS_NewCFunction()}. @code{JS_SetPropertyFunctionList()} is a +shortcut to easily add functions, setters and getters properties to a +given object. + +Unlike other embedded Javascript engines, there is no implicit stack, +so C functions get their parameters as normal C parameters. As a +general rule, C functions take constant @code{JSValue}s as parameters +(so they don't need to free them) and return a newly allocated (=live) +@code{JSValue}. + +@subsection Exceptions + +Exceptions: most C functions can return a Javascript exception. It +must be explicitly tested and handled by the C code. The specific +@code{JSValue} @code{JS_EXCEPTION} indicates that an exception +occurred. The actual exception object is stored in the +@code{JSContext} and can be retrieved with @code{JS_GetException()}. + +@subsection Script evaluation + +Use @code{JS_Eval()} to evaluate a script or module source. + +If the script or module was compiled to bytecode with @code{qjsc}, it +can be evaluated by calling @code{js_std_eval_binary()}. The advantage +is that no compilation is needed so it is faster and smaller because +the compiler can be removed from the executable if no @code{eval} is +required. + +Note: the bytecode format is linked to a given QuickJS +version. Moreover, no security check is done before its +execution. Hence the bytecode should not be loaded from untrusted +sources. That's why there is no option to output the bytecode to a +binary file in @code{qjsc}. + +@subsection JS Classes + +C opaque data can be attached to a Javascript object. The type of the +C opaque data is determined with the class ID (@code{JSClassID}) of +the object. Hence the first step is to register a new class ID and JS +class (@code{JS_NewClassID()}, @code{JS_NewClass()}). Then you can +create objects of this class with @code{JS_NewObjectClass()} and get or +set the C opaque point with +@code{JS_GetOpaque()}/@code{JS_SetOpaque()}. + +When defining a new JS class, it is possible to declare a finalizer +which is called when the object is destroyed. The finalizer should be +used to release C resources. It is invalid to execute JS code from +it. A @code{gc_mark} method can be provided so that the cycle removal +algorithm can find the other objects referenced by this object. Other +methods are available to define exotic object behaviors. + +The Class ID are globally allocated (i.e. for all runtimes). The +JSClass are allocated per @code{JSRuntime}. @code{JS_SetClassProto()} +is used to define a prototype for a given class in a given +JSContext. @code{JS_NewObjectClass()} sets this prototype in the +created object. + +Examples are available in @file{quickjs-libc.c}. + +@subsection C Modules + +Native ES6 modules are supported and can be dynamically or statically +linked. Look at the @file{test_bjson} and @file{bjson.so} +examples. The standard library @file{quickjs-libc.c} is also a good example +of a native module. + +@subsection Memory handling + +Use @code{JS_SetMemoryLimit()} to set a global memory allocation limit +to a given JSRuntime. + +Custom memory allocation functions can be provided with +@code{JS_NewRuntime2()}. + +The maximum system stack size can be set with @code{JS_SetMaxStackSize()}. + +@subsection Execution timeout and interrupts + +Use @code{JS_SetInterruptHandler()} to set a callback which is +regularly called by the engine when it is executing code. This +callback can be used to implement an execution timeout. + +It is used by the command line interpreter to implement a +@code{Ctrl-C} handler. + +@chapter Internals + +@section Bytecode + +The compiler generates bytecode directly with no intermediate +representation such as a parse tree, hence it is very fast. Several +optimizations passes are done over the generated bytecode. + +A stack-based bytecode was chosen because it is simple and generates +compact code. + +For each function, the maximum stack size is computed at compile time so that +no runtime stack overflow tests are needed. + +A separate compressed line number table is maintained for the debug +information. + +Access to closure variables is optimized and is almost as fast as local +variables. + +Direct @code{eval} in strict mode is optimized. + +@section Executable generation + +@subsection @code{qjsc} compiler + +The @code{qjsc} compiler generates C sources from Javascript files. By +default the C sources are compiled with the system compiler +(@code{gcc} or @code{clang}). + +The generated C source contains the bytecode of the compiled functions +or modules. If a full complete executable is needed, it also +contains a @code{main()} function with the necessary C code to initialize the +Javascript engine and to load and execute the compiled functions and +modules. + +Javascript code can be mixed with C modules. + +In order to have smaller executables, specific Javascript features can +be disabled, in particular @code{eval} or the regular expressions. The +code removal relies on the Link Time Optimization of the system +compiler. + +@subsection Binary JSON + +@code{qjsc} works by compiling scripts or modules and then serializing +them to a binary format. A subset of this format (without functions or +modules) can be used as binary JSON. The example @file{test_bjson.js} +shows how to use it. + +Warning: the binary JSON format may change without notice, so it +should not be used to store persistent data. The @file{test_bjson.js} +example is only used to test the binary object format functions. + +@section Runtime + +@subsection Strings + +Strings are stored either as an 8 bit or a 16 bit array of +characters. Hence random access to characters is always fast. + +The C API provides functions to convert Javascript Strings to C UTF-8 encoded +strings. The most common case where the Javascript string contains +only ASCII characters involves no copying. + +@subsection Objects + +The object shapes (object prototype, property names and flags) are shared +between objects to save memory. + +Arrays with no holes (except at the end of the array) are optimized. + +TypedArray accesses are optimized. + +@subsection Atoms + +Object property names and some strings are stored as Atoms (unique +strings) to save memory and allow fast comparison. Atoms are +represented as a 32 bit integer. Half of the atom range is reserved for +immediate integer literals from @math{0} to @math{2^{31}-1}. + +@subsection Numbers + +Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754 +floating point values. Most operations have fast paths for the 32-bit +integer case. + +@subsection Garbage collection + +Reference counting is used to free objects automatically and +deterministically. A separate cycle removal pass is done when the allocated +memory becomes too large. The cycle removal algorithm only uses the +reference counts and the object content, so no explicit garbage +collection roots need to be manipulated in the C code. + +@subsection JSValue + +It is a Javascript value which can be a primitive type (such as +Number, String, ...) or an Object. NaN boxing is used in the 32-bit version +to store 64-bit floating point numbers. The representation is +optimized so that 32-bit integers and reference counted values can be +efficiently tested. + +In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The +rationale is that in 64-bit code memory usage is less critical. + +In both cases (32 or 64 bits), JSValue exactly fits two CPU registers, +so it can be efficiently returned by C functions. + +@subsection Function call + +The engine is optimized so that function calls are fast. The system +stack holds the Javascript parameters and local variables. + +@section RegExp + +A specific regular expression engine was developed. It is both small +and efficient and supports all the ES2024 features including the +Unicode properties. As the Javascript compiler, it directly generates +bytecode without a parse tree. + +Backtracking with an explicit stack is used so that there is no +recursion on the system stack. Simple quantifiers are specifically +optimized to avoid recursions. + +The full regexp library weights about 15 KiB (x86 code), excluding the +Unicode library. + +@section Unicode + +A specific Unicode library was developed so that there is no +dependency on an external large Unicode library such as ICU. All the +Unicode tables are compressed while keeping a reasonable access +speed. + +The library supports case conversion, Unicode normalization, Unicode +script queries, Unicode general category queries and all Unicode +binary properties. + +The full Unicode library weights about 45 KiB (x86 code). + +@section BigInt + +BigInts are represented using binary two's complement notation. An +additional short bigint value is used to optimize the performance on +small BigInt values. + +@chapter License + +QuickJS is released under the MIT license. + +Unless otherwise specified, the QuickJS sources are copyright Fabrice +Bellard and Charlie Gordon. + +@bye diff --git a/quickjs-ng/dtoa.c b/quickjs/dtoa.c similarity index 98% rename from quickjs-ng/dtoa.c rename to quickjs/dtoa.c index def8608..8fe388a 100644 --- a/quickjs-ng/dtoa.c +++ b/quickjs/dtoa.c @@ -28,9 +28,7 @@ #include #include #include -// #include #include -// #include #include "cutils.h" #include "dtoa.h" @@ -890,7 +888,7 @@ static int output_digits(char *buf, /* return (a, e_offset) such that a = a * (radix1*2^radix_shift)^f * 2^-e_offset. 'f' can be negative. */ -static int mul_pow(mpb_t *a, int radix1, int radix_shift, int f, bool is_int, int e) +static int mul_pow(mpb_t *a, int radix1, int radix_shift, int f, BOOL is_int, int e) { int e_offset, d, n, n0; @@ -962,7 +960,7 @@ static void mul_pow_round(mpb_t *tmp1, uint64_t m, int e, int radix1, int radix_ int e_offset; mpb_set_u64(tmp1, m); - e_offset = mul_pow(tmp1, radix1, radix_shift, f, true, e); + e_offset = mul_pow(tmp1, radix1, radix_shift, f, TRUE, e); mpb_shr_round(tmp1, -e + e_offset, rnd_mode); } @@ -1008,7 +1006,7 @@ static uint64_t mul_pow_round_to_d(int *pe, mpb_t *a, { int e_offset; - e_offset = mul_pow(a, radix1, radix_shift, f, false, 55); + e_offset = mul_pow(a, radix1, radix_shift, f, FALSE, 55); return round_to_d(pe, a, e_offset, rnd_mode); } @@ -1264,7 +1262,7 @@ int js_dtoa(char *buf, double d, int radix, int n_digits, int flags, /* mant_max = radix^P */ mant_max->len = 1; mant_max->tab[0] = 1; - pow_shift = mul_pow(mant_max, radix1, radix_shift, P, false, 0); + pow_shift = mul_pow(mant_max, radix1, radix_shift, P, FALSE, 0); mpb_shr_round(mant_max, pow_shift, JS_RNDZ); for(;;) { @@ -1361,7 +1359,7 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, int radix_bits, expn, e, max_digits, expn_offset, dot_pos, sig_pos, pos; mpb_t *tmp0; double dval; - bool is_bin_exp, is_zero, expn_overflow; + BOOL is_bin_exp, is_zero, expn_overflow; uint64_t m, a; tmp0 = dtoa_malloc(&mptr, sizeof(mpb_t) + sizeof(limb_t) * DBIGNUM_LEN_MAX); @@ -1413,7 +1411,7 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, goto fail; no_prefix: ; } else { - if (!(flags & JS_ATOD_INT_ONLY) && js__strstart(p, "Infinity", &p)) + if (!(flags & JS_ATOD_INT_ONLY) && strstart(p, "Infinity", &p)) goto overflow; } if (radix == 0) @@ -1495,10 +1493,10 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, mpb_mul1_base(tmp0, pow_ui(radix, limb_digit_count), cur_limb); } if (digit_count == 0) { - is_zero = true; + is_zero = TRUE; expn_offset = 0; } else { - is_zero = false; + is_zero = FALSE; if (dot_pos < 0) dot_pos = pos; expn_offset = sig_pos + digit_count - dot_pos; @@ -1512,22 +1510,22 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, /* parse the exponent, if any */ expn = 0; - expn_overflow = false; - is_bin_exp = false; + expn_overflow = FALSE; + is_bin_exp = FALSE; if (!(flags & JS_ATOD_INT_ONLY) && ((radix == 10 && (*p == 'e' || *p == 'E')) || (radix != 10 && (*p == '@' || (radix_bits >= 1 && radix_bits <= 4 && (*p == 'p' || *p == 'P'))))) && p > p_start) { - bool exp_is_neg; + BOOL exp_is_neg; int c; is_bin_exp = (*p == 'p' || *p == 'P'); p++; - exp_is_neg = false; + exp_is_neg = 0; if (*p == '+') { p++; } else if (*p == '-') { - exp_is_neg = true; + exp_is_neg = 1; p++; } c = to_digit(*p); @@ -1543,7 +1541,7 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, break; if (!expn_overflow) { if (unlikely(expn > ((INT32_MAX - 2 - 9) / 10))) { - expn_overflow = true; + expn_overflow = TRUE; } else { expn = expn * 10 + c; } diff --git a/quickjs-ng/dtoa.h b/quickjs/dtoa.h similarity index 100% rename from quickjs-ng/dtoa.h rename to quickjs/dtoa.h diff --git a/quickjs-ng/examples/fib.c b/quickjs/examples/fib.c similarity index 87% rename from quickjs-ng/examples/fib.c rename to quickjs/examples/fib.c index b965acc..be90af5 100644 --- a/quickjs-ng/examples/fib.c +++ b/quickjs/examples/fib.c @@ -35,8 +35,8 @@ static int fib(int n) return fib(n - 1) + fib(n - 2); } -static JSValue js_fib(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) +static JSValue js_fib(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) { int n, res; if (JS_ToInt32(ctx, &n, argv[0])) @@ -61,15 +61,7 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m) #define JS_INIT_MODULE js_init_module_fib #endif -#ifndef JS_EXTERN -#ifdef _WIN32 -#define JS_EXTERN __declspec(dllexport) -#else -#define JS_EXTERN -#endif -#endif - -JS_EXTERN JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, js_fib_init); diff --git a/quickjs-ng/examples/fib_module.js b/quickjs/examples/fib_module.js similarity index 100% rename from quickjs-ng/examples/fib_module.js rename to quickjs/examples/fib_module.js diff --git a/quickjs-ng/examples/hello.js b/quickjs/examples/hello.js similarity index 100% rename from quickjs-ng/examples/hello.js rename to quickjs/examples/hello.js diff --git a/quickjs-ng/examples/hello_module.js b/quickjs/examples/hello_module.js similarity index 51% rename from quickjs-ng/examples/hello_module.js rename to quickjs/examples/hello_module.js index 463660f..5d4c78e 100644 --- a/quickjs-ng/examples/hello_module.js +++ b/quickjs/examples/hello_module.js @@ -1,6 +1,8 @@ -/* example of JS module */ +/* example of JS and JSON modules */ import { fib } from "./fib_module.js"; +import msg from "./message.json"; console.log("Hello World"); console.log("fib(10)=", fib(10)); +console.log("msg=", msg); diff --git a/quickjs/examples/message.json b/quickjs/examples/message.json new file mode 100644 index 0000000..3b7fe48 --- /dev/null +++ b/quickjs/examples/message.json @@ -0,0 +1,2 @@ +{ "x" : 1, "tab": [ 1, 2, 3 ] } + diff --git a/quickjs-ng/examples/pi_bigint.js b/quickjs/examples/pi_bigint.js similarity index 100% rename from quickjs-ng/examples/pi_bigint.js rename to quickjs/examples/pi_bigint.js diff --git a/quickjs-ng/examples/point.c b/quickjs/examples/point.c similarity index 85% rename from quickjs-ng/examples/point.c rename to quickjs/examples/point.c index a82df15..0386230 100644 --- a/quickjs-ng/examples/point.c +++ b/quickjs/examples/point.c @@ -43,8 +43,8 @@ static void js_point_finalizer(JSRuntime *rt, JSValue val) } static JSValue js_point_ctor(JSContext *ctx, - JSValue new_target, - int argc, JSValue *argv) + JSValueConst new_target, + int argc, JSValueConst *argv) { JSPointData *s; JSValue obj = JS_UNDEFINED; @@ -74,7 +74,7 @@ static JSValue js_point_ctor(JSContext *ctx, return JS_EXCEPTION; } -static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic) +static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic) { JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); if (!s) @@ -85,7 +85,7 @@ static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic) return JS_NewInt32(ctx, s->y); } -static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic) +static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) { JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); int v; @@ -100,8 +100,8 @@ static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, in return JS_UNDEFINED; } -static JSValue js_point_norm(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) +static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) { JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); if (!s) @@ -123,11 +123,10 @@ static const JSCFunctionListEntry js_point_proto_funcs[] = { static int js_point_init(JSContext *ctx, JSModuleDef *m) { JSValue point_proto, point_class; - JSRuntime *rt = JS_GetRuntime(ctx); /* create the Point class */ - JS_NewClassID(rt, &js_point_class_id); - JS_NewClass(rt, js_point_class_id, &js_point_class); + JS_NewClassID(&js_point_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class); point_proto = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs)); @@ -141,15 +140,7 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m) return 0; } -#ifndef JS_EXTERN -#ifdef _WIN32 -#define JS_EXTERN __declspec(dllexport) -#else -#define JS_EXTERN -#endif -#endif - -JS_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, js_point_init); diff --git a/quickjs/examples/test_fib.js b/quickjs/examples/test_fib.js new file mode 100644 index 0000000..70d26bd --- /dev/null +++ b/quickjs/examples/test_fib.js @@ -0,0 +1,6 @@ +/* example of JS module importing a C module */ + +import { fib } from "./fib.so"; + +console.log("Hello World"); +console.log("fib(10)=", fib(10)); diff --git a/quickjs-ng/examples/test_point.js b/quickjs/examples/test_point.js similarity index 83% rename from quickjs-ng/examples/test_point.js rename to quickjs/examples/test_point.js index 1e0fafa..0659bc3 100644 --- a/quickjs-ng/examples/test_point.js +++ b/quickjs/examples/test_point.js @@ -1,8 +1,5 @@ /* example of JS module importing a C module */ -import * as os from "qjs:os"; - -const isWin = os.platform === 'win32'; -const { Point } = await import(`./point.${isWin ? 'dll' : 'so'}`); +import { Point } from "./point.so"; function assert(b, str) { diff --git a/quickjs/fuzz/README b/quickjs/fuzz/README new file mode 100644 index 0000000..18c71cd --- /dev/null +++ b/quickjs/fuzz/README @@ -0,0 +1,27 @@ +libFuzzer support for QuickJS +============================= + +Build QuickJS with libFuzzer support as follows: + + CONFIG_CLANG=y make libfuzzer + +This can be extended with sanitizer support to improve efficacy: + + CONFIG_CLANG=y CONFIG_ASAN=y make libfuzzer + + +Currently, there are three fuzzing targets defined: fuzz_eval, fuzz_compile and fuzz_regexp. +The above build command will produce an executable binary for each of them, which can be +simply executed as: + + ./fuzz_eval + +or with an initial corpus: + + ./fuzz_compile corpus_dir/ + +or with a predefined dictionary to improve its efficacy: + + ./fuzz_eval -dict fuzz/fuzz.dict + +or with arbitrary CLI arguments provided by libFuzzer (https://llvm.org/docs/LibFuzzer.html). diff --git a/quickjs/fuzz/fuzz.dict b/quickjs/fuzz/fuzz.dict new file mode 100644 index 0000000..f31eb9f --- /dev/null +++ b/quickjs/fuzz/fuzz.dict @@ -0,0 +1,254 @@ +"__loadScript" +"abs" +"acos" +"acosh" +"add" +"AggregateError" +"and" +"apply" +"Array" +"ArrayBuffer" +"asin" +"asinh" +"atan" +"atan2" +"atanh" +"Atomics" +"BigInt" +"BigInt64Array" +"BigUint64Array" +"Boolean" +"cbrt" +"ceil" +"chdir" +"clearTimeout" +"close" +"clz32" +"compareExchange" +"console" +"construct" +"cos" +"cosh" +"DataView" +"Date" +"decodeURI" +"decodeURIComponent" +"defineProperty" +"deleteProperty" +"dup" +"dup2" +"E" +"encodeURI" +"encodeURIComponent" +"err" +"Error" +"escape" +"eval" +"EvalError" +"evalScript" +"exchange" +"exec" +"exit" +"exp" +"expm1" +"fdopen" +"Float32Array" +"Float64Array" +"floor" +"fround" +"Function" +"gc" +"get" +"getcwd" +"getenv" +"getenviron" +"getOwnPropertyDescriptor" +"getpid" +"getPrototypeOf" +"globalThis" +"has" +"hypot" +"imul" +"in" +"Infinity" +"Int16Array" +"Int32Array" +"Int8Array" +"InternalError" +"isatty" +"isExtensible" +"isFinite" +"isLockFree" +"isNaN" +"iterateBuiltIns" +"JSON" +"kill" +"length" +"LN10" +"LN2" +"load" +"loadFile" +"loadScript" +"log" +"log10" +"LOG10E" +"log1p" +"log2" +"LOG2E" +"lstat" +"Map" +"Math" +"max" +"min" +"mkdir" +"NaN" +"notify" +"now" +"Number" +"O_APPEND" +"O_CREAT" +"O_EXCL" +"O_RDONLY" +"O_RDWR" +"O_TRUNC" +"O_WRONLY" +"Object" +"open" +"Operators" +"or" +"os" +"out" +"ownKeys" +"parse" +"parseExtJSON" +"parseFloat" +"parseInt" +"PI" +"pipe" +"platform" +"popen" +"pow" +"preventExtensions" +"print" +"printf" +"Promise" +"Proxy" +"puts" +"random" +"RangeError" +"read" +"readdir" +"readlink" +"realpath" +"ReferenceError" +"Reflect" +"RegExp" +"remove" +"rename" +"round" +"S_IFBLK" +"S_IFCHR" +"S_IFDIR" +"S_IFIFO" +"S_IFLNK" +"S_IFMT" +"S_IFREG" +"S_IFSOCK" +"S_ISGID" +"S_ISUID" +"scriptArgs" +"seek" +"SEEK_CUR" +"SEEK_END" +"SEEK_SET" +"set" +"Set" +"setenv" +"setPrototypeOf" +"setReadHandler" +"setTimeout" +"setWriteHandler" +"SharedArrayBuffer" +"SIGABRT" +"SIGALRM" +"SIGCHLD" +"SIGCONT" +"SIGFPE" +"SIGILL" +"SIGINT" +"sign" +"signal" +"SIGPIPE" +"SIGQUIT" +"SIGSEGV" +"SIGSTOP" +"SIGTERM" +"SIGTSTP" +"SIGTTIN" +"SIGTTOU" +"SIGUSR1" +"SIGUSR2" +"sin" +"sinh" +"sleep" +"sleepAsync" +"sprintf" +"sqrt" +"SQRT1_2" +"SQRT2" +"stat" +"std" +"store" +"strerror" +"String" +"stringify" +"sub" +"Symbol" +"symlink" +"SyntaxError" +"tan" +"tanh" +"tmpfile" +"trunc" +"ttyGetWinSize" +"ttySetRaw" +"TypeError" +"Uint16Array" +"Uint32Array" +"Uint8Array" +"Uint8ClampedArray" +"undefined" +"unescape" +"unsetenv" +"URIError" +"urlGet" +"utimes" +"wait" +"waitpid" +"WeakMap" +"WeakSet" +"WNOHANG" +"Worker" +"write" +"xor" +"v0" +"v1" +"v2" +"v3" +"v4" +"v5" +"v6" +"v7" +"v8" +"v9" +"v10" +"v11" +"v12" +"v13" +"v14" +"v15" +"v16" +"v17" +"v18" +"v19" +"v20" diff --git a/quickjs/fuzz/fuzz_common.c b/quickjs/fuzz/fuzz_common.c new file mode 100644 index 0000000..92548d2 --- /dev/null +++ b/quickjs/fuzz/fuzz_common.c @@ -0,0 +1,58 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include + +#include "fuzz/fuzz_common.h" + +// handle timeouts from infinite loops +static int interrupt_handler(JSRuntime *rt, void *opaque) +{ + nbinterrupts++; + return (nbinterrupts > 100); +} + +void reset_nbinterrupts() { + nbinterrupts = 0; +} + +void test_one_input_init(JSRuntime *rt, JSContext *ctx) { + // 64 Mo + JS_SetMemoryLimit(rt, 0x4000000); + // 64 Kb + JS_SetMaxStackSize(rt, 0x10000); + + JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); + JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL); + js_std_add_helpers(ctx, 0, NULL); + + // Load os and std + js_std_init_handlers(rt); + js_init_module_std(ctx, "std"); + js_init_module_os(ctx, "os"); + const char *str = "import * as std from 'std';\n" + "import * as os from 'os';\n" + "globalThis.std = std;\n" + "globalThis.os = os;\n"; + JSValue std_val = JS_Eval(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + if (!JS_IsException(std_val)) { + js_module_set_import_meta(ctx, std_val, 1, 1); + std_val = JS_EvalFunction(ctx, std_val); + } else { + js_std_dump_error(ctx); + } + std_val = js_std_await(ctx, std_val); + JS_FreeValue(ctx, std_val); +} diff --git a/quickjs/fuzz/fuzz_common.h b/quickjs/fuzz/fuzz_common.h new file mode 100644 index 0000000..10cb497 --- /dev/null +++ b/quickjs/fuzz/fuzz_common.h @@ -0,0 +1,22 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" + +static int nbinterrupts = 0; + +void reset_nbinterrupts(); +void test_one_input_init(JSRuntime *rt, JSContext *ctx); diff --git a/quickjs/fuzz/fuzz_compile.c b/quickjs/fuzz/fuzz_compile.c new file mode 100644 index 0000000..0ab1b03 --- /dev/null +++ b/quickjs/fuzz/fuzz_compile.c @@ -0,0 +1,93 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" +#include "cutils.h" +#include "fuzz/fuzz_common.h" + +#include +#include + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size == 0) + return 0; + + JSRuntime *rt = JS_NewRuntime(); + JSContext *ctx = JS_NewContext(rt); + test_one_input_init(rt, ctx); + + uint8_t *null_terminated_data = malloc(size + 1); + memcpy(null_terminated_data, data, size); + null_terminated_data[size] = 0; + + JSValue obj = JS_Eval(ctx, (const char *)null_terminated_data, size, "", JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_MODULE); + free(null_terminated_data); + //TODO target with JS_ParseJSON + if (JS_IsException(obj)) { + js_std_free_handlers(rt); + JS_FreeValue(ctx, obj); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + obj = js_std_await(ctx, obj); + size_t bytecode_size; + uint8_t* bytecode = JS_WriteObject(ctx, &bytecode_size, obj, JS_WRITE_OBJ_BYTECODE); + JS_FreeValue(ctx, obj); + if (!bytecode) { + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + obj = JS_ReadObject(ctx, bytecode, bytecode_size, JS_READ_OBJ_BYTECODE); + js_free(ctx, bytecode); + if (JS_IsException(obj)) { + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + reset_nbinterrupts(); + /* this is based on + * js_std_eval_binary(ctx, bytecode, bytecode_size, 0); + * modified so as not to exit on JS exception + */ + JSValue val; + if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { + if (JS_ResolveModule(ctx, obj) < 0) { + JS_FreeValue(ctx, obj); + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + js_module_set_import_meta(ctx, obj, FALSE, TRUE); + } + val = JS_EvalFunction(ctx, obj); + if (JS_IsException(val)) { + js_std_dump_error(ctx); + } else { + js_std_loop(ctx); + } + JS_FreeValue(ctx, val); + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + return 0; +} diff --git a/quickjs/fuzz/fuzz_eval.c b/quickjs/fuzz/fuzz_eval.c new file mode 100644 index 0000000..aa26f1e --- /dev/null +++ b/quickjs/fuzz/fuzz_eval.c @@ -0,0 +1,49 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" +#include "fuzz/fuzz_common.h" + +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size == 0) + return 0; + + JSRuntime *rt = JS_NewRuntime(); + JSContext *ctx = JS_NewContext(rt); + test_one_input_init(rt, ctx); + + uint8_t *null_terminated_data = malloc(size + 1); + memcpy(null_terminated_data, data, size); + null_terminated_data[size] = 0; + + reset_nbinterrupts(); + //the final 0 does not count (as in strlen) + JSValue val = JS_Eval(ctx, (const char *)null_terminated_data, size, "", JS_EVAL_TYPE_GLOBAL); + free(null_terminated_data); + //TODO targets with JS_ParseJSON, JS_ReadObject + if (!JS_IsException(val)) { + js_std_loop(ctx); + JS_FreeValue(ctx, val); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; +} diff --git a/quickjs/fuzz/fuzz_regexp.c b/quickjs/fuzz/fuzz_regexp.c new file mode 100644 index 0000000..ae929e8 --- /dev/null +++ b/quickjs/fuzz/fuzz_regexp.c @@ -0,0 +1,66 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "libregexp.h" +#include "quickjs-libc.h" + +static int nbinterrupts = 0; + +int lre_check_stack_overflow(void *opaque, size_t alloca_size) { return 0; } + +void *lre_realloc(void *opaque, void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +int lre_check_timeout(void *opaque) + { + nbinterrupts++; + return (nbinterrupts > 100); + } + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + int len, ret, i; + uint8_t *bc; + char error_msg[64]; + const uint8_t *input; + uint8_t *capture[255 * 2]; + size_t size1 = size; + + //Splits buffer into 2 sub buffers delimited by null character + for (i = 0; i < size; i++) { + if (data[i] == 0) { + size1 = i; + break; + } + } + if (size1 == size) { + //missing delimiter + return 0; + } + bc = lre_compile(&len, error_msg, sizeof(error_msg), (const char *) data, + size1, 0, NULL); + if (!bc) { + return 0; + } + input = data + size1 + 1; + ret = lre_exec(capture, bc, input, 0, size - (size1 + 1), 0, NULL); + if (ret == 1) { + lre_get_capture_count(bc); + } + free(bc); + + return 0; +} diff --git a/quickjs/fuzz/generate_dict.js b/quickjs/fuzz/generate_dict.js new file mode 100644 index 0000000..1366fea --- /dev/null +++ b/quickjs/fuzz/generate_dict.js @@ -0,0 +1,24 @@ +// Function to recursively iterate through built-in names. +function collectBuiltinNames(obj, visited = new Set(), result = new Set()) { + // Check if the object has already been visited to avoid infinite recursion. + if (visited.has(obj)) + return; + + // Add the current object to the set of visited objects + visited.add(obj); + // Get the property names of the current object + const properties = Object.getOwnPropertyNames(obj); + // Iterate through each property + for (var i=0; i < properties.length; i++) { + var property = properties[i]; + if (property != "collectBuiltinNames" && typeof property != "number") + result.add(property); + // Check if the property is an object and if so, recursively iterate through its properties. + if (typeof obj[property] === 'object' && obj[property] !== null) + collectBuiltinNames(obj[property], visited, result); + } + return result; +} + +// Start the recursive iteration with the global object. +console.log(Array.from(collectBuiltinNames(this)).join('\n')); diff --git a/quickjs-ng/libregexp-opcode.h b/quickjs/libregexp-opcode.h similarity index 85% rename from quickjs-ng/libregexp-opcode.h rename to quickjs/libregexp-opcode.h index 5c1714a..ebab751 100644 --- a/quickjs-ng/libregexp-opcode.h +++ b/quickjs/libregexp-opcode.h @@ -25,13 +25,16 @@ #ifdef DEF DEF(invalid, 1) /* never used */ -DEF(char8, 2) /* 7 bits in fact */ -DEF(char16, 3) +DEF(char, 3) +DEF(char_i, 3) DEF(char32, 5) +DEF(char32_i, 5) DEF(dot, 1) DEF(any, 1) /* same as dot but match any character including line terminator */ DEF(line_start, 1) +DEF(line_start_m, 1) DEF(line_end, 1) +DEF(line_end_m, 1) DEF(goto, 5) DEF(split_goto_first, 5) DEF(split_next_first, 5) @@ -43,11 +46,17 @@ DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ DEF(push_i32, 5) /* push integer on the stack */ DEF(drop, 1) DEF(word_boundary, 1) +DEF(word_boundary_i, 1) DEF(not_word_boundary, 1) +DEF(not_word_boundary_i, 1) DEF(back_reference, 2) -DEF(backward_back_reference, 2) /* must come after back_reference */ +DEF(back_reference_i, 2) /* must come after */ +DEF(backward_back_reference, 2) /* must come after */ +DEF(backward_back_reference_i, 2) /* must come after */ DEF(range, 3) /* variable length */ +DEF(range_i, 3) /* variable length */ DEF(range32, 3) /* variable length */ +DEF(range32_i, 3) /* variable length */ DEF(lookahead, 5) DEF(negative_lookahead, 5) DEF(push_char_pos, 1) /* push the character position on the stack */ diff --git a/quickjs-ng/libregexp.c b/quickjs/libregexp.c similarity index 69% rename from quickjs-ng/libregexp.c rename to quickjs/libregexp.c index 26d96ed..118d950 100644 --- a/quickjs-ng/libregexp.c +++ b/quickjs/libregexp.c @@ -30,6 +30,7 @@ #include "cutils.h" #include "libregexp.h" +#include "libunicode.h" /* TODO: @@ -63,17 +64,17 @@ typedef enum { #define TMP_BUF_SIZE 128 -// invariant: is_unicode ^ unicode_sets (or neither, but not both) typedef struct { DynBuf byte_code; const uint8_t *buf_ptr; const uint8_t *buf_end; const uint8_t *buf_start; int re_flags; - bool is_unicode; - bool unicode_sets; - bool ignore_case; - bool dotall; + BOOL is_unicode; + BOOL unicode_sets; /* if set, is_unicode is also set */ + BOOL ignore_case; + BOOL multi_line; + BOOL dotall; int capture_count; int total_capture_count; /* -1 = not computed yet */ int has_named_captures; /* -1 = don't know, 0 = no, 1 = yes */ @@ -109,20 +110,278 @@ static const REOpCode reopcode_info[REOP_COUNT] = { #define RE_HEADER_LEN 8 -static inline int lre_is_digit(int c) { +static inline int is_digit(int c) { return c >= '0' && c <= '9'; } /* insert 'len' bytes at position 'pos'. Return < 0 if error. */ static int dbuf_insert(DynBuf *s, int pos, int len) { - if (dbuf_realloc(s, s->size + len)) + if (dbuf_claim(s, len)) return -1; memmove(s->buf + pos + len, s->buf + pos, s->size - pos); s->size += len; return 0; } +typedef struct REString { + struct REString *next; + uint32_t hash; + uint32_t len; + uint32_t buf[]; +} REString; + +typedef struct { + /* the string list is the union of 'char_range' and of the strings + in hash_table[]. The strings in hash_table[] have a length != + 1. */ + CharRange cr; + uint32_t n_strings; + uint32_t hash_size; + int hash_bits; + REString **hash_table; +} REStringList; + +static uint32_t re_string_hash(int len, const uint32_t *buf) +{ + int i; + uint32_t h; + h = 1; + for(i = 0; i < len; i++) + h = h * 263 + buf[i]; + return h * 0x61C88647; +} + +static void re_string_list_init(REParseState *s1, REStringList *s) +{ + cr_init(&s->cr, s1->opaque, lre_realloc); + s->n_strings = 0; + s->hash_size = 0; + s->hash_bits = 0; + s->hash_table = NULL; +} + +static void re_string_list_free(REStringList *s) +{ + REString *p, *p_next; + int i; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + lre_realloc(s->cr.mem_opaque, p, 0); + } + } + lre_realloc(s->cr.mem_opaque, s->hash_table, 0); + + cr_free(&s->cr); +} + +static void lre_print_char(int c, BOOL is_range) +{ + if (c == '\'' || c == '\\' || + (is_range && (c == '-' || c == ']'))) { + printf("\\%c", c); + } else if (c >= ' ' && c <= 126) { + printf("%c", c); + } else { + printf("\\u{%04x}", c); + } +} + +static __maybe_unused void re_string_list_dump(const char *str, const REStringList *s) +{ + REString *p; + const CharRange *cr; + int i, j, k; + + printf("%s:\n", str); + printf(" ranges: ["); + cr = &s->cr; + for(i = 0; i < cr->len; i += 2) { + lre_print_char(cr->points[i], TRUE); + if (cr->points[i] != cr->points[i + 1] - 1) { + printf("-"); + lre_print_char(cr->points[i + 1] - 1, TRUE); + } + } + printf("]\n"); + + j = 0; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p->next) { + printf(" %d/%d: '", j, s->n_strings); + for(k = 0; k < p->len; k++) { + lre_print_char(p->buf[k], FALSE); + } + printf("'\n"); + j++; + } + } +} + +static int re_string_find2(REStringList *s, int len, const uint32_t *buf, + uint32_t h0, BOOL add_flag) +{ + uint32_t h = 0; /* avoid warning */ + REString *p; + if (s->n_strings != 0) { + h = h0 >> (32 - s->hash_bits); + for(p = s->hash_table[h]; p != NULL; p = p->next) { + if (p->hash == h0 && p->len == len && + !memcmp(p->buf, buf, len * sizeof(buf[0]))) { + return 1; + } + } + } + /* not found */ + if (!add_flag) + return 0; + /* increase the size of the hash table if needed */ + if (unlikely((s->n_strings + 1) > s->hash_size)) { + REString **new_hash_table, *p_next; + int new_hash_bits, i; + uint32_t new_hash_size; + new_hash_bits = max_int(s->hash_bits + 1, 4); + new_hash_size = 1 << new_hash_bits; + new_hash_table = lre_realloc(s->cr.mem_opaque, NULL, + sizeof(new_hash_table[0]) * new_hash_size); + if (!new_hash_table) + return -1; + memset(new_hash_table, 0, sizeof(new_hash_table[0]) * new_hash_size); + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + h = p->hash >> (32 - new_hash_bits); + p->next = new_hash_table[h]; + new_hash_table[h] = p; + } + } + lre_realloc(s->cr.mem_opaque, s->hash_table, 0); + s->hash_bits = new_hash_bits; + s->hash_size = new_hash_size; + s->hash_table = new_hash_table; + h = h0 >> (32 - s->hash_bits); + } + + p = lre_realloc(s->cr.mem_opaque, NULL, sizeof(REString) + len * sizeof(buf[0])); + if (!p) + return -1; + p->next = s->hash_table[h]; + s->hash_table[h] = p; + s->n_strings++; + p->hash = h0; + p->len = len; + memcpy(p->buf, buf, sizeof(buf[0]) * len); + return 1; +} + +static int re_string_find(REStringList *s, int len, const uint32_t *buf, + BOOL add_flag) +{ + uint32_t h0; + h0 = re_string_hash(len, buf); + return re_string_find2(s, len, buf, h0, add_flag); +} + +/* return -1 if memory error, 0 if OK */ +static int re_string_add(REStringList *s, int len, const uint32_t *buf) +{ + if (len == 1) { + return cr_union_interval(&s->cr, buf[0], buf[0]); + } + if (re_string_find(s, len, buf, TRUE) < 0) + return -1; + return 0; +} + +/* a = a op b */ +static int re_string_list_op(REStringList *a, REStringList *b, int op) +{ + int i, ret; + REString *p, **pp; + + if (cr_op1(&a->cr, b->cr.points, b->cr.len, op)) + return -1; + + switch(op) { + case CR_OP_UNION: + if (b->n_strings != 0) { + for(i = 0; i < b->hash_size; i++) { + for(p = b->hash_table[i]; p != NULL; p = p->next) { + if (re_string_find2(a, p->len, p->buf, p->hash, TRUE) < 0) + return -1; + } + } + } + break; + case CR_OP_INTER: + case CR_OP_SUB: + for(i = 0; i < a->hash_size; i++) { + pp = &a->hash_table[i]; + for(;;) { + p = *pp; + if (p == NULL) + break; + ret = re_string_find2(b, p->len, p->buf, p->hash, FALSE); + if (op == CR_OP_SUB) + ret = !ret; + if (!ret) { + /* remove it */ + *pp = p->next; + a->n_strings--; + lre_realloc(a->cr.mem_opaque, p, 0); + } else { + /* keep it */ + pp = &p->next; + } + } + } + break; + default: + abort(); + } + return 0; +} + +static int re_string_list_canonicalize(REParseState *s1, + REStringList *s, BOOL is_unicode) +{ + if (cr_regexp_canonicalize(&s->cr, is_unicode)) + return -1; + if (s->n_strings != 0) { + REStringList a_s, *a = &a_s; + int i, j; + REString *p; + + /* XXX: simplify */ + re_string_list_init(s1, a); + + a->n_strings = s->n_strings; + a->hash_size = s->hash_size; + a->hash_bits = s->hash_bits; + a->hash_table = s->hash_table; + + s->n_strings = 0; + s->hash_size = 0; + s->hash_bits = 0; + s->hash_table = NULL; + + for(i = 0; i < a->hash_size; i++) { + for(p = a->hash_table[i]; p != NULL; p = p->next) { + for(j = 0; j < p->len; j++) { + p->buf[j] = lre_canonicalize(p->buf[j], is_unicode); + } + if (re_string_add(s, p->len, p->buf)) { + re_string_list_free(a); + return -1; + } + } + } + re_string_list_free(a); + } + return 0; +} + static const uint16_t char_range_d[] = { 1, 0x0030, 0x0039 + 1, @@ -146,32 +405,6 @@ static const uint16_t char_range_s[] = { 0xFEFF, 0xFEFF + 1, }; -bool lre_is_space(int c) -{ - int i, n, low, high; - n = (countof(char_range_s) - 1) / 2; - for(i = 0; i < n; i++) { - low = char_range_s[2 * i + 1]; - if (c < low) - return false; - high = char_range_s[2 * i + 2]; - if (c < high) - return true; - } - return false; -} - -uint32_t const lre_id_start_table_ascii[4] = { - /* $ A-Z _ a-z */ - 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE -}; - -uint32_t const lre_id_continue_table_ascii[4] = { - /* $ 0-9 A-Z _ a-z */ - 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE -}; - - static const uint16_t char_range_w[] = { 4, 0x0030, 0x0039 + 1, @@ -191,33 +424,33 @@ typedef enum { CHAR_RANGE_W, } CharRangeEnum; -static const uint16_t *char_range_table[] = { +static const uint16_t * const char_range_table[] = { char_range_d, char_range_s, char_range_w, }; -static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c) +static int cr_init_char_range(REParseState *s, REStringList *cr, uint32_t c) { - bool invert; + BOOL invert; const uint16_t *c_pt; int len, i; invert = c & 1; c_pt = char_range_table[c >> 1]; len = *c_pt++; - cr_init(cr, s->opaque, lre_realloc); + re_string_list_init(s, cr); for(i = 0; i < len * 2; i++) { - if (cr_add_point(cr, c_pt[i])) + if (cr_add_point(&cr->cr, c_pt[i])) goto fail; } if (invert) { - if (cr_invert(cr)) + if (cr_invert(&cr->cr)) goto fail; } return 0; fail: - cr_free(cr); + re_string_list_free(cr); return -1; } @@ -266,15 +499,17 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, } printf("%s", reopcode_info[opcode].name); switch(opcode) { - case REOP_char8: - val = get_u8(buf + pos + 1); - goto printchar; - case REOP_char16: + case REOP_char: + case REOP_char_i: val = get_u16(buf + pos + 1); - goto printchar; + if (val >= ' ' && val <= 126) + printf(" '%c'", val); + else + printf(" 0x%04x", val); + break; case REOP_char32: + case REOP_char32_i: val = get_u32(buf + pos + 1); - printchar: if (val >= ' ' && val <= 126) printf(" '%c'", val); else @@ -300,7 +535,9 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, case REOP_save_start: case REOP_save_end: case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: + case REOP_backward_back_reference_i: printf(" %u", buf[pos + 1]); break; case REOP_save_reset: @@ -311,6 +548,7 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, printf(" %d", val); break; case REOP_range: + case REOP_range_i: { int n, i; n = get_u16(buf + pos + 1); @@ -322,6 +560,7 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, } break; case REOP_range32: + case REOP_range32_i: { int n, i; n = get_u16(buf + pos + 1); @@ -377,7 +616,7 @@ static void re_emit_op_u16(REParseState *s, int op, uint32_t val) dbuf_put_u16(&s->byte_code, val); } -static int JS_PRINTF_FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...) +static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState *s, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -393,7 +632,7 @@ static int re_parse_out_of_memory(REParseState *s) /* If allow_overflow is false, return -1 in case of overflow. Otherwise return INT32_MAX. */ -static int parse_digits(const uint8_t **pp, bool allow_overflow) +static int parse_digits(const uint8_t **pp, BOOL allow_overflow) { const uint8_t *p; uint64_t v; @@ -524,7 +763,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) c -= '0'; if (allow_utf16 == 2) { /* only accept \0 not followed by digit */ - if (c != 0 || lre_is_digit(*p)) + if (c != 0 || is_digit(*p)) return -1; } else { /* parse a legacy octal sequence */ @@ -550,8 +789,9 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) return c; } +#ifdef CONFIG_ALL_UNICODE /* XXX: we use the same chars for name and value */ -static bool is_unicode_char(int c) +static BOOL is_unicode_char(int c) { return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || @@ -559,13 +799,21 @@ static bool is_unicode_char(int c) (c == '_')); } -static int parse_unicode_property(REParseState *s, CharRange *cr, - const uint8_t **pp, bool is_inv) +/* XXX: memory error test */ +static void seq_prop_cb(void *opaque, const uint32_t *seq, int seq_len) +{ + REStringList *sl = opaque; + re_string_add(sl, seq_len, seq); +} + +static int parse_unicode_property(REParseState *s, REStringList *cr, + const uint8_t **pp, BOOL is_inv, + BOOL allow_sequence_prop) { const uint8_t *p; char name[64], value[64]; char *q; - bool script_ext; + BOOL script_ext; int ret; p = *pp; @@ -595,56 +843,81 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, // printf("name=%s value=%s\n", name, value); if (!strcmp(name, "Script") || !strcmp(name, "sc")) { - script_ext = false; + script_ext = FALSE; goto do_script; } else if (!strcmp(name, "Script_Extensions") || !strcmp(name, "scx")) { - script_ext = true; + script_ext = TRUE; do_script: - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_script(cr, value, script_ext); + re_string_list_init(s, cr); + ret = unicode_script(&cr->cr, value, script_ext); if (ret) { - cr_free(cr); + re_string_list_free(cr); if (ret == -2) return re_parse_error(s, "unknown unicode script"); else goto out_of_memory; } } else if (!strcmp(name, "General_Category") || !strcmp(name, "gc")) { - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_general_category(cr, value); + re_string_list_init(s, cr); + ret = unicode_general_category(&cr->cr, value); if (ret) { - cr_free(cr); + re_string_list_free(cr); if (ret == -2) return re_parse_error(s, "unknown unicode general category"); else goto out_of_memory; } } else if (value[0] == '\0') { - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_general_category(cr, name); + re_string_list_init(s, cr); + ret = unicode_general_category(&cr->cr, name); if (ret == -1) { - cr_free(cr); + re_string_list_free(cr); goto out_of_memory; } if (ret < 0) { - ret = unicode_prop(cr, name); - if (ret) { - cr_free(cr); - if (ret == -2) - goto unknown_property_name; - else - goto out_of_memory; + ret = unicode_prop(&cr->cr, name); + if (ret == -1) { + re_string_list_free(cr); + goto out_of_memory; + } + } + if (ret < 0 && !is_inv && allow_sequence_prop) { + CharRange cr_tmp; + cr_init(&cr_tmp, s->opaque, lre_realloc); + ret = unicode_sequence_prop(name, seq_prop_cb, cr, &cr_tmp); + cr_free(&cr_tmp); + if (ret == -1) { + re_string_list_free(cr); + goto out_of_memory; } } + if (ret < 0) + goto unknown_property_name; } else { unknown_property_name: return re_parse_error(s, "unknown unicode property name"); } + /* the ordering of case folding and inversion differs with + unicode_sets. 'unicode_sets' ordering is more consistent */ + /* XXX: the spec seems incorrect, we do it as the other engines + seem to do it. */ + if (s->ignore_case && s->unicode_sets) { + if (re_string_list_canonicalize(s, cr, s->is_unicode)) { + re_string_list_free(cr); + goto out_of_memory; + } + } if (is_inv) { - if (cr_invert(cr)) { - cr_free(cr); - return -1; + if (cr_invert(&cr->cr)) { + re_string_list_free(cr); + goto out_of_memory; + } + } + if (s->ignore_case && !s->unicode_sets) { + if (re_string_list_canonicalize(s, cr, s->is_unicode)) { + re_string_list_free(cr); + goto out_of_memory; } } *pp = p; @@ -652,14 +925,66 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, out_of_memory: return re_parse_out_of_memory(s); } +#endif /* CONFIG_ALL_UNICODE */ + +static int get_class_atom(REParseState *s, REStringList *cr, + const uint8_t **pp, BOOL inclass); + +static int parse_class_string_disjunction(REParseState *s, REStringList *cr, + const uint8_t **pp) +{ + const uint8_t *p; + DynBuf str; + int c; + + p = *pp; + if (*p != '{') + return re_parse_error(s, "expecting '{' after \\q"); + + dbuf_init2(&str, s->opaque, lre_realloc); + re_string_list_init(s, cr); + + p++; + for(;;) { + str.size = 0; + while (*p != '}' && *p != '|') { + c = get_class_atom(s, NULL, &p, FALSE); + if (c < 0) + goto fail; + if (dbuf_put_u32(&str, c)) { + re_parse_out_of_memory(s); + goto fail; + } + } + if (re_string_add(cr, str.size / 4, (uint32_t *)str.buf)) { + re_parse_out_of_memory(s); + goto fail; + } + if (*p == '}') + break; + p++; + } + if (s->ignore_case) { + if (re_string_list_canonicalize(s, cr, TRUE)) + goto fail; + } + p++; /* skip the '}' */ + dbuf_free(&str); + *pp = p; + return 0; + fail: + dbuf_free(&str); + re_string_list_free(cr); + return -1; +} /* return -1 if error otherwise the character or a class range - (CLASS_RANGE_BASE). In case of class range, 'cr' is + (CLASS_RANGE_BASE) if cr != NULL. In case of class range, 'cr' is initialized. Otherwise, it is ignored. */ -static int get_class_atom(REParseState *s, CharRange *cr, - const uint8_t **pp, bool inclass) +static int get_class_atom(REParseState *s, REStringList *cr, + const uint8_t **pp, BOOL inclass) { - const uint8_t *p, *p_next; + const uint8_t *p; uint32_t c; int ret; @@ -691,6 +1016,8 @@ static int get_class_atom(REParseState *s, CharRange *cr, case 'W': c = CHAR_RANGE_W; class_range: + if (!cr) + goto default_escape; if (cr_init_char_range(s, cr, c)) return -1; c = CLASS_RANGE_BASE; @@ -711,28 +1038,54 @@ static int get_class_atom(REParseState *s, CharRange *cr, c = '\\'; } break; + case '-': + if (!inclass && s->is_unicode) + goto invalid_escape; + break; + case '^': + case '$': + case '\\': + case '.': + case '*': + case '+': + case '?': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '|': + case '/': + /* always valid to escape these characters */ + break; +#ifdef CONFIG_ALL_UNICODE case 'p': case 'P': - if (s->is_unicode) { - if (parse_unicode_property(s, cr, &p, (c == 'P'))) + if (s->is_unicode && cr) { + if (parse_unicode_property(s, cr, &p, (c == 'P'), s->unicode_sets)) + return -1; + c = CLASS_RANGE_BASE; + break; + } + goto default_escape; +#endif + case 'q': + if (s->unicode_sets && cr && inclass) { + if (parse_class_string_disjunction(s, cr, &p)) return -1; c = CLASS_RANGE_BASE; break; } - /* fall thru */ + goto default_escape; default: + default_escape: p--; ret = lre_parse_escape(&p, s->is_unicode * 2); if (ret >= 0) { c = ret; } else { - if (ret == -2 && *p != '\0' && strchr("^$\\.*+?()[]{}|/", *p)) { - /* always valid to escape these characters */ - goto normal_char; - } else if (s->is_unicode) { - // special case: allowed inside [] but not outside - if (ret == -2 && *p == '-' && inclass) - goto normal_char; + if (s->is_unicode) { invalid_escape: return re_parse_error(s, "invalid escape sequence in regular expression"); } else { @@ -749,20 +1102,59 @@ static int get_class_atom(REParseState *s, CharRange *cr, return re_parse_error(s, "unexpected end"); } /* fall thru */ + goto normal_char; + + case '&': + case '!': + case '#': + case '$': + case '%': + case '*': + case '+': + case ',': + case '.': + case ':': + case ';': + case '<': + case '=': + case '>': + case '?': + case '@': + case '^': + case '`': + case '~': + if (s->unicode_sets && p[1] == c) { + /* forbidden double characters */ + return re_parse_error(s, "invalid class set operation in regular expression"); + } + goto normal_char; + + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '/': + case '-': + case '|': + if (s->unicode_sets) { + /* invalid characters in unicode sets */ + return re_parse_error(s, "invalid character in class in regular expression"); + } + goto normal_char; + default: normal_char: - p++; - if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) - return re_parse_error(s, "invalid UTF-8 sequence"); - p = p_next; - if (c > 0xFFFF && !s->is_unicode) { - // TODO(chqrlie): should handle non BMP-1 code points in - // the calling function and no require the source string - // to be CESU-8 encoded if not s->is_unicode + /* normal char */ + if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if ((unsigned)c > 0xffff && !s->is_unicode) { + /* XXX: should handle non BMP-1 code points */ return re_parse_error(s, "malformed unicode char"); } + } else { + p++; } break; } @@ -779,8 +1171,6 @@ static int re_emit_range(REParseState *s, const CharRange *cr) if (len >= 65535) return re_parse_error(s, "too many ranges"); if (len == 0) { - /* not sure it can really happen. Emit a match that is always - false */ re_emit_op_u32(s, REOP_char32, -1); } else { high = cr->points[cr->len - 1]; @@ -789,7 +1179,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) if (high <= 0xffff) { /* can use 16 bit ranges with the conversion that 0xffff = infinity */ - re_emit_op_u16(s, REOP_range, len); + re_emit_op_u16(s, s->ignore_case ? REOP_range_i : REOP_range, len); for(i = 0; i < cr->len; i += 2) { dbuf_put_u16(&s->byte_code, cr->points[i]); high = cr->points[i + 1] - 1; @@ -798,7 +1188,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) dbuf_put_u16(&s->byte_code, high); } } else { - re_emit_op_u16(s, REOP_range32, len); + re_emit_op_u16(s, s->ignore_case ? REOP_range32_i : REOP_range32, len); for(i = 0; i < cr->len; i += 2) { dbuf_put_u32(&s->byte_code, cr->points[i]); dbuf_put_u32(&s->byte_code, cr->points[i + 1] - 1); @@ -808,117 +1198,296 @@ static int re_emit_range(REParseState *s, const CharRange *cr) return 0; } -// s->unicode turns patterns like []] into syntax errors -// s->unicode_sets turns more patterns into errors, like [a-] or [[] -static int re_parse_char_class(REParseState *s, const uint8_t **pp) +static int re_string_cmp_len(const void *a, const void *b, void *arg) +{ + REString *p1 = *(REString **)a; + REString *p2 = *(REString **)b; + return (p1->len < p2->len) - (p1->len > p2->len); +} + +static void re_emit_char(REParseState *s, int c) +{ + if (c <= 0xffff) + re_emit_op_u16(s, s->ignore_case ? REOP_char_i : REOP_char, c); + else + re_emit_op_u32(s, s->ignore_case ? REOP_char32_i : REOP_char32, c); +} + +static int re_emit_string_list(REParseState *s, const REStringList *sl) +{ + REString **tab, *p; + int i, j, split_pos, last_match_pos, n; + BOOL has_empty_string, is_last; + + // re_string_list_dump("sl", sl); + if (sl->n_strings == 0) { + /* simple case: only characters */ + if (re_emit_range(s, &sl->cr)) + return -1; + } else { + /* at least one string list is present : match the longest ones first */ + /* XXX: add a new op_switch opcode to compile as a trie */ + tab = lre_realloc(s->opaque, NULL, sizeof(tab[0]) * sl->n_strings); + if (!tab) { + re_parse_out_of_memory(s); + return -1; + } + has_empty_string = FALSE; + n = 0; + for(i = 0; i < sl->hash_size; i++) { + for(p = sl->hash_table[i]; p != NULL; p = p->next) { + if (p->len == 0) { + has_empty_string = TRUE; + } else { + tab[n++] = p; + } + } + } + assert(n <= sl->n_strings); + + rqsort(tab, n, sizeof(tab[0]), re_string_cmp_len, NULL); + + last_match_pos = -1; + for(i = 0; i < n; i++) { + p = tab[i]; + is_last = !has_empty_string && sl->cr.len == 0 && i == (n - 1); + if (!is_last) + split_pos = re_emit_op_u32(s, REOP_split_next_first, 0); + else + split_pos = 0; + for(j = 0; j < p->len; j++) { + re_emit_char(s, p->buf[j]); + } + if (!is_last) { + last_match_pos = re_emit_op_u32(s, REOP_goto, last_match_pos); + put_u32(s->byte_code.buf + split_pos, s->byte_code.size - (split_pos + 4)); + } + } + + if (sl->cr.len != 0) { + /* char range */ + is_last = !has_empty_string; + if (!is_last) + split_pos = re_emit_op_u32(s, REOP_split_next_first, 0); + else + split_pos = 0; /* not used */ + if (re_emit_range(s, &sl->cr)) { + lre_realloc(s->opaque, tab, 0); + return -1; + } + if (!is_last) + put_u32(s->byte_code.buf + split_pos, s->byte_code.size - (split_pos + 4)); + } + + /* patch the 'goto match' */ + while (last_match_pos != -1) { + int next_pos = get_u32(s->byte_code.buf + last_match_pos); + put_u32(s->byte_code.buf + last_match_pos, s->byte_code.size - (last_match_pos + 4)); + last_match_pos = next_pos; + } + + lre_realloc(s->opaque, tab, 0); + } + return 0; +} + +static int re_parse_nested_class(REParseState *s, REStringList *cr, const uint8_t **pp); + +static int re_parse_class_set_operand(REParseState *s, REStringList *cr, const uint8_t **pp) +{ + int c1; + const uint8_t *p = *pp; + + if (*p == '[') { + if (re_parse_nested_class(s, cr, pp)) + return -1; + } else { + c1 = get_class_atom(s, cr, pp, TRUE); + if (c1 < 0) + return -1; + if (c1 < CLASS_RANGE_BASE) { + /* create a range with a single character */ + re_string_list_init(s, cr); + if (s->ignore_case) + c1 = lre_canonicalize(c1, s->is_unicode); + if (cr_union_interval(&cr->cr, c1, c1)) { + re_string_list_free(cr); + return -1; + } + } + } + return 0; +} + +static int re_parse_nested_class(REParseState *s, REStringList *cr, const uint8_t **pp) { const uint8_t *p; uint32_t c1, c2; - CharRange cr_s, *cr = &cr_s; - CharRange cr1_s, *cr1 = &cr1_s; - bool invert; + int ret; + REStringList cr1_s, *cr1 = &cr1_s; + BOOL invert, is_first; - cr_init(cr, s->opaque, lre_realloc); + if (lre_check_stack_overflow(s->opaque, 0)) + return re_parse_error(s, "stack overflow"); + + re_string_list_init(s, cr); p = *pp; p++; /* skip '[' */ - if (s->unicode_sets) { - static const char verboten[] = - "()[{}/-|" "\0" - "&&!!##$$%%**++,,..::;;<<==>>??@@``~~" "\0" - "^^^_^^"; - const char *s = verboten; - int n = 1; - do { - if (!memcmp(s, p, n)) - if (p[n] == ']') - goto invalid_class_range; - s += n; - if (!*s) { - s++; - n++; - } - } while (n < 4); - } - - invert = false; + invert = FALSE; if (*p == '^') { p++; - invert = true; + invert = TRUE; } - + + /* handle unions */ + is_first = TRUE; for(;;) { if (*p == ']') break; - c1 = get_class_atom(s, cr1, &p, true); - if ((int)c1 < 0) - goto fail; - if (*p == '-' && p[1] == ']' && s->unicode_sets) { - if (c1 >= CLASS_RANGE_BASE) - cr_free(cr1); - goto invalid_class_range; - } - if (*p == '-' && p[1] != ']') { - const uint8_t *p0 = p + 1; - if (c1 >= CLASS_RANGE_BASE) { - if (s->is_unicode) { - cr_free(cr1); - goto invalid_class_range; - } - /* Annex B: match '-' character */ - goto class_atom; - } - c2 = get_class_atom(s, cr1, &p0, true); - if ((int)c2 < 0) - goto fail; - if (c2 >= CLASS_RANGE_BASE) { - cr_free(cr1); - if (s->is_unicode) { - goto invalid_class_range; - } - /* Annex B: match '-' character */ - goto class_atom; - } - p = p0; - if (c2 < c1) { - invalid_class_range: - re_parse_error(s, "invalid class range"); + if (*p == '[' && s->unicode_sets) { + if (re_parse_nested_class(s, cr1, &p)) goto fail; - } - if (cr_union_interval(cr, c1, c2)) - goto memory_error; + goto class_union; } else { - class_atom: - if (c1 >= CLASS_RANGE_BASE) { - int ret; - ret = cr_union1(cr, cr1->points, cr1->len); - cr_free(cr1); - if (ret) - goto memory_error; + c1 = get_class_atom(s, cr1, &p, TRUE); + if ((int)c1 < 0) + goto fail; + if (*p == '-' && p[1] != ']') { + const uint8_t *p0 = p + 1; + if (p[1] == '-' && s->unicode_sets && is_first) + goto class_atom; /* first character class followed by '--' */ + if (c1 >= CLASS_RANGE_BASE) { + if (s->is_unicode) { + re_string_list_free(cr1); + goto invalid_class_range; + } + /* Annex B: match '-' character */ + goto class_atom; + } + c2 = get_class_atom(s, cr1, &p0, TRUE); + if ((int)c2 < 0) + goto fail; + if (c2 >= CLASS_RANGE_BASE) { + re_string_list_free(cr1); + if (s->is_unicode) { + goto invalid_class_range; + } + /* Annex B: match '-' character */ + goto class_atom; + } + p = p0; + if (c2 < c1) { + invalid_class_range: + re_parse_error(s, "invalid class range"); + goto fail; + } + if (s->ignore_case) { + CharRange cr2_s, *cr2 = &cr2_s; + cr_init(cr2, s->opaque, lre_realloc); + if (cr_add_interval(cr2, c1, c2 + 1) || + cr_regexp_canonicalize(cr2, s->is_unicode) || + cr_op1(&cr->cr, cr2->points, cr2->len, CR_OP_UNION)) { + cr_free(cr2); + goto memory_error; + } + cr_free(cr2); + } else { + if (cr_union_interval(&cr->cr, c1, c2)) + goto memory_error; + } + is_first = FALSE; /* union operation */ } else { - if (cr_union_interval(cr, c1, c1)) - goto memory_error; + class_atom: + if (c1 >= CLASS_RANGE_BASE) { + class_union: + ret = re_string_list_op(cr, cr1, CR_OP_UNION); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } else { + if (s->ignore_case) + c1 = lre_canonicalize(c1, s->is_unicode); + if (cr_union_interval(&cr->cr, c1, c1)) + goto memory_error; + } } } + if (s->unicode_sets && is_first) { + if (*p == '&' && p[1] == '&' && p[2] != '&') { + /* handle '&&' */ + for(;;) { + if (*p == ']') { + break; + } else if (*p == '&' && p[1] == '&' && p[2] != '&') { + p += 2; + } else { + goto invalid_operation; + } + if (re_parse_class_set_operand(s, cr1, &p)) + goto fail; + ret = re_string_list_op(cr, cr1, CR_OP_INTER); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } + } else if (*p == '-' && p[1] == '-') { + /* handle '--' */ + for(;;) { + if (*p == ']') { + break; + } else if (*p == '-' && p[1] == '-') { + p += 2; + } else { + invalid_operation: + re_parse_error(s, "invalid operation in regular expression"); + goto fail; + } + if (re_parse_class_set_operand(s, cr1, &p)) + goto fail; + ret = re_string_list_op(cr, cr1, CR_OP_SUB); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } + } + } + is_first = FALSE; } - if (s->ignore_case) { - if (cr_regexp_canonicalize(cr, s->is_unicode)) - goto memory_error; - } + + p++; /* skip ']' */ + *pp = p; if (invert) { - if (cr_invert(cr)) + /* XXX: add may_contain_string syntax check to be fully + compliant. The test here accepts more input than the + spec. */ + if (cr->n_strings != 0) { + re_parse_error(s, "negated character class with strings in regular expression debugger eval code"); + goto fail; + } + if (cr_invert(&cr->cr)) goto memory_error; } - if (re_emit_range(s, cr)) - goto fail; - cr_free(cr); - p++; /* skip ']' */ - *pp = p; return 0; memory_error: re_parse_out_of_memory(s); fail: - cr_free(cr); + re_string_list_free(cr); + return -1; +} + +static int re_parse_char_class(REParseState *s, const uint8_t **pp) +{ + REStringList cr_s, *cr = &cr_s; + + if (re_parse_nested_class(s, cr, pp)) + return -1; + if (re_emit_string_list(s, cr)) + goto fail; + re_string_list_free(cr); + return 0; + fail: + re_string_list_free(cr); return -1; } @@ -926,42 +1495,48 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) - true if the opcodes may not advance the char pointer - false if the opcodes always advance the char pointer */ -static bool re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) +static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) { int pos, opcode, len; uint32_t val; - bool ret; + BOOL ret; - ret = true; + ret = TRUE; pos = 0; - while (pos < bc_buf_len) { opcode = bc_buf[pos]; len = reopcode_info[opcode].size; switch(opcode) { case REOP_range: + case REOP_range_i: val = get_u16(bc_buf + pos + 1); len += val * 4; goto simple_char; case REOP_range32: + case REOP_range32_i: val = get_u16(bc_buf + pos + 1); len += val * 8; goto simple_char; + case REOP_char: + case REOP_char_i: case REOP_char32: - case REOP_char16: - case REOP_char8: + case REOP_char32_i: case REOP_dot: case REOP_any: simple_char: - ret = false; + ret = FALSE; break; case REOP_line_start: + case REOP_line_start_m: case REOP_line_end: + case REOP_line_end_m: case REOP_push_i32: case REOP_push_char_pos: case REOP_drop: case REOP_word_boundary: + case REOP_word_boundary_i: case REOP_not_word_boundary: + case REOP_not_word_boundary_i: case REOP_prev: /* no effect */ break; @@ -969,11 +1544,13 @@ static bool re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) case REOP_save_end: case REOP_save_reset: case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: + case REOP_backward_back_reference_i: break; default: - /* safe behvior: we cannot predict the outcome */ - return true; + /* safe behavior: we cannot predict the outcome */ + return TRUE; } pos += len; } @@ -994,25 +1571,32 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) len = reopcode_info[opcode].size; switch(opcode) { case REOP_range: + case REOP_range_i: val = get_u16(bc_buf + pos + 1); len += val * 4; goto simple_char; case REOP_range32: + case REOP_range32_i: val = get_u16(bc_buf + pos + 1); len += val * 8; goto simple_char; + case REOP_char: + case REOP_char_i: case REOP_char32: - case REOP_char16: - case REOP_char8: + case REOP_char32_i: case REOP_dot: case REOP_any: simple_char: count++; break; case REOP_line_start: + case REOP_line_start_m: case REOP_line_end: + case REOP_line_end_m: case REOP_word_boundary: + case REOP_word_boundary_i: case REOP_not_word_boundary: + case REOP_not_word_boundary_i: break; default: return -1; @@ -1025,35 +1609,35 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) /* '*pp' is the first char after '<' */ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) { - const uint8_t *p, *p_next; + const uint8_t *p, *p1; uint32_t c, d; char *q; p = *pp; q = buf; for(;;) { - c = *p++; + c = *p; if (c == '\\') { + p++; if (*p != 'u') return -1; c = lre_parse_escape(&p, 2); // accept surrogate pairs - if ((int)c < 0) - return -1; } else if (c == '>') { break; - } else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) - return -1; - p = p_next; + } else if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); if (is_hi_surrogate(c)) { - d = utf8_decode(p, &p_next); + d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); if (is_lo_surrogate(d)) { c = from_surrogate(c, d); - p = p_next; + p = p1; } } + } else { + p++; } + if (c > 0x10FFFF) + return -1; if (q == buf) { if (!lre_js_is_ident_first(c)) return -1; @@ -1063,15 +1647,16 @@ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) } if ((q - buf + UTF8_CHAR_LEN_MAX + 1) > buf_size) return -1; - if (c < 0x80) { + if (c < 128) { *q++ = c; } else { - q += utf8_encode((uint8_t*)q, c); + q += unicode_to_utf8((uint8_t*)q, c); } } if (q == buf) return -1; *q = '\0'; + p++; *pp = p; return 0; } @@ -1139,7 +1724,7 @@ static int re_count_captures(REParseState *s) return s->total_capture_count; } -static bool re_has_named_captures(REParseState *s) +static BOOL re_has_named_captures(REParseState *s) { if (s->has_named_captures < 0) re_count_captures(s); @@ -1167,14 +1752,49 @@ static int find_group_name(REParseState *s, const char *name) return -1; } -static int re_parse_disjunction(REParseState *s, bool is_backward_dir); +static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir); -static int re_parse_term(REParseState *s, bool is_backward_dir) +static int re_parse_modifiers(REParseState *s, const uint8_t **pp) +{ + const uint8_t *p = *pp; + int mask = 0; + int val; + + for(;;) { + if (*p == 'i') { + val = LRE_FLAG_IGNORECASE; + } else if (*p == 'm') { + val = LRE_FLAG_MULTILINE; + } else if (*p == 's') { + val = LRE_FLAG_DOTALL; + } else { + break; + } + if (mask & val) + return re_parse_error(s, "duplicate modifier: '%c'", *p); + mask |= val; + p++; + } + *pp = p; + return mask; +} + +static BOOL update_modifier(BOOL val, int add_mask, int remove_mask, + int mask) +{ + if (add_mask & mask) + val = TRUE; + if (remove_mask & mask) + val = FALSE; + return val; +} + +static int re_parse_term(REParseState *s, BOOL is_backward_dir) { const uint8_t *p; int c, last_atom_start, quant_min, quant_max, last_capture_count; - bool greedy, add_zero_advance_check, is_neg, is_backward_lookahead; - CharRange cr_s, *cr = &cr_s; + BOOL greedy, add_zero_advance_check, is_neg, is_backward_lookahead; + REStringList cr_s, *cr = &cr_s; last_atom_start = -1; last_capture_count = 0; @@ -1183,11 +1803,11 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) switch(c) { case '^': p++; - re_emit_op(s, REOP_line_start); + re_emit_op(s, s->multi_line ? REOP_line_start_m : REOP_line_start); break; case '$': p++; - re_emit_op(s, REOP_line_end); + re_emit_op(s, s->multi_line ? REOP_line_end_m : REOP_line_end); break; case '.': p++; @@ -1202,18 +1822,18 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) case '{': if (s->is_unicode) { return re_parse_error(s, "syntax error"); - } else if (!lre_is_digit(p[1])) { + } else if (!is_digit(p[1])) { /* Annex B: we accept '{' not followed by digits as a normal atom */ goto parse_class_atom; } else { const uint8_t *p1 = p + 1; /* Annex B: error if it is like a repetition count */ - parse_digits(&p1, true); + parse_digits(&p1, TRUE); if (*p1 == ',') { p1++; - if (lre_is_digit(*p1)) { - parse_digits(&p1, true); + if (is_digit(*p1)) { + parse_digits(&p1, TRUE); } } if (*p1 != '}') { @@ -1237,16 +1857,54 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) p = s->buf_ptr; if (re_parse_expect(s, &p, ')')) return -1; + } else if (p[2] == 'i' || p[2] == 'm' || p[2] == 's' || p[2] == '-') { + BOOL saved_ignore_case, saved_multi_line, saved_dotall; + int add_mask, remove_mask; + p += 2; + remove_mask = 0; + add_mask = re_parse_modifiers(s, &p); + if (add_mask < 0) + return -1; + if (*p == '-') { + p++; + remove_mask = re_parse_modifiers(s, &p); + if (remove_mask < 0) + return -1; + } + if ((add_mask == 0 && remove_mask == 0) || + (add_mask & remove_mask) != 0) { + return re_parse_error(s, "invalid modifiers"); + } + if (re_parse_expect(s, &p, ':')) + return -1; + saved_ignore_case = s->ignore_case; + saved_multi_line = s->multi_line; + saved_dotall = s->dotall; + s->ignore_case = update_modifier(s->ignore_case, add_mask, remove_mask, LRE_FLAG_IGNORECASE); + s->multi_line = update_modifier(s->multi_line, add_mask, remove_mask, LRE_FLAG_MULTILINE); + s->dotall = update_modifier(s->dotall, add_mask, remove_mask, LRE_FLAG_DOTALL); + + last_atom_start = s->byte_code.size; + last_capture_count = s->capture_count; + s->buf_ptr = p; + if (re_parse_disjunction(s, is_backward_dir)) + return -1; + p = s->buf_ptr; + if (re_parse_expect(s, &p, ')')) + return -1; + s->ignore_case = saved_ignore_case; + s->multi_line = saved_multi_line; + s->dotall = saved_dotall; } else if ((p[2] == '=' || p[2] == '!')) { is_neg = (p[2] == '!'); - is_backward_lookahead = false; + is_backward_lookahead = FALSE; p += 3; goto lookahead; } else if (p[2] == '<' && (p[3] == '=' || p[3] == '!')) { int pos; is_neg = (p[3] == '!'); - is_backward_lookahead = true; + is_backward_lookahead = TRUE; p += 4; /* lookahead */ lookahead: @@ -1315,7 +1973,11 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) switch(p[1]) { case 'b': case 'B': - re_emit_op(s, REOP_word_boundary + (p[1] != 'b')); + if (p[1] != 'b') { + re_emit_op(s, s->ignore_case ? REOP_not_word_boundary_i : REOP_not_word_boundary); + } else { + re_emit_op(s, s->ignore_case ? REOP_word_boundary_i : REOP_word_boundary); + } p += 2; break; case 'k': @@ -1360,7 +2022,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) p += 2; c = 0; if (s->is_unicode) { - if (lre_is_digit(*p)) { + if (is_digit(*p)) { return re_parse_error(s, "invalid decimal escape in regular expression"); } } else { @@ -1379,7 +2041,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) { const uint8_t *q = ++p; - c = parse_digits(&p, false); + c = parse_digits(&p, FALSE); if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) { if (!s->is_unicode) { /* Annex B.1.4: accept legacy octal */ @@ -1404,7 +2066,8 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) emit_back_reference: last_atom_start = s->byte_code.size; last_capture_count = s->capture_count; - re_emit_op_u8(s, REOP_back_reference + is_backward_dir, c); + + re_emit_op_u8(s, REOP_back_reference + 2 * is_backward_dir + s->ignore_case, c); } break; default: @@ -1428,7 +2091,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) goto parse_class_atom; default: parse_class_atom: - c = get_class_atom(s, cr, &p, false); + c = get_class_atom(s, cr, &p, FALSE); if ((int)c < 0) return -1; normal_char: @@ -1438,20 +2101,14 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) re_emit_op(s, REOP_prev); if (c >= CLASS_RANGE_BASE) { int ret; - /* Note: canonicalization is not needed */ - ret = re_emit_range(s, cr); - cr_free(cr); + ret = re_emit_string_list(s, cr); + re_string_list_free(cr); if (ret) return -1; } else { if (s->ignore_case) c = lre_canonicalize(c, s->is_unicode); - if (c <= 0x7f) - re_emit_op_u8(s, REOP_char8, c); - else if (c <= 0xffff) - re_emit_op_u16(s, REOP_char16, c); - else - re_emit_op_u32(s, REOP_char32, c); + re_emit_char(s, c); } if (is_backward_dir) re_emit_op(s, REOP_prev); @@ -1482,18 +2139,18 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) const uint8_t *p1 = p; /* As an extension (see ES6 annex B), we accept '{' not followed by digits as a normal atom */ - if (!lre_is_digit(p[1])) { + if (!is_digit(p[1])) { if (s->is_unicode) goto invalid_quant_count; break; } p++; - quant_min = parse_digits(&p, true); + quant_min = parse_digits(&p, TRUE); quant_max = quant_min; if (*p == ',') { p++; - if (lre_is_digit(*p)) { - quant_max = parse_digits(&p, true); + if (is_digit(*p)) { + quant_max = parse_digits(&p, TRUE); if (quant_max < quant_min) { invalid_quant_count: return re_parse_error(s, "invalid repetition count"); @@ -1511,10 +2168,10 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) return -1; } quantifier: - greedy = true; + greedy = TRUE; if (*p == '?') { p++; - greedy = false; + greedy = FALSE; } if (last_atom_start < 0) { return re_parse_error(s, "nothing to repeat"); @@ -1574,7 +2231,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) if (quant_max == 0) { s->byte_code.size = last_atom_start; } else if (quant_max == 1 || quant_max == INT32_MAX) { - bool has_goto = (quant_max == INT32_MAX); + BOOL has_goto = (quant_max == INT32_MAX); if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check)) goto out_of_memory; s->byte_code.buf[last_atom_start] = REOP_split_goto_first + @@ -1661,7 +2318,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) return re_parse_out_of_memory(s); } -static int re_parse_alternative(REParseState *s, bool is_backward_dir) +static int re_parse_alternative(REParseState *s, BOOL is_backward_dir) { const uint8_t *p; int ret; @@ -1683,7 +2340,7 @@ static int re_parse_alternative(REParseState *s, bool is_backward_dir) speed is not really critical here) */ end = s->byte_code.size; term_size = end - term_start; - if (dbuf_realloc(&s->byte_code, end + term_size)) + if (dbuf_claim(&s->byte_code, term_size)) return -1; memmove(s->byte_code.buf + start + term_size, s->byte_code.buf + start, @@ -1695,7 +2352,7 @@ static int re_parse_alternative(REParseState *s, bool is_backward_dir) return 0; } -static int re_parse_disjunction(REParseState *s, bool is_backward_dir) +static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) { int start, len, pos; @@ -1730,7 +2387,7 @@ static int re_parse_disjunction(REParseState *s, bool is_backward_dir) } /* the control flow is recursive so the analysis can be linear */ -static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) +static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) { int stack_size, stack_size_max, pos, opcode, len; uint32_t val; @@ -1761,10 +2418,12 @@ static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) stack_size--; break; case REOP_range: + case REOP_range_i: val = get_u16(bc_buf + pos + 1); len += val * 4; break; case REOP_range32: + case REOP_range32_i: val = get_u16(bc_buf + pos + 1); len += val * 8; break; @@ -1774,6 +2433,17 @@ static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) return stack_size_max; } +static void *lre_bytecode_realloc(void *opaque, void *ptr, size_t size) +{ + if (size > (INT32_MAX / 2)) { + /* the bytecode cannot be larger than 2G. Leave some slack to + avoid some overflows. */ + return NULL; + } else { + return lre_realloc(opaque, ptr, size); + } +} + /* 'buf' must be a zero terminated UTF-8 string of length buf_len. Return NULL if error and allocate an error message in *perror_msg, otherwise the compiled bytecode and its length in plen. @@ -1784,7 +2454,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, { REParseState s_s, *s = &s_s; int stack_size; - bool is_sticky; + BOOL is_sticky; memset(s, 0, sizeof(*s)); s->opaque = opaque; @@ -1792,16 +2462,17 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, s->buf_end = s->buf_ptr + buf_len; s->buf_start = s->buf_ptr; s->re_flags = re_flags; - s->is_unicode = ((re_flags & LRE_FLAG_UNICODE) != 0); + s->is_unicode = ((re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0); is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0); s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 0); + s->multi_line = ((re_flags & LRE_FLAG_MULTILINE) != 0); s->dotall = ((re_flags & LRE_FLAG_DOTALL) != 0); s->unicode_sets = ((re_flags & LRE_FLAG_UNICODE_SETS) != 0); s->capture_count = 1; s->total_capture_count = -1; s->has_named_captures = -1; - dbuf_init2(&s->byte_code, opaque, lre_realloc); + dbuf_init2(&s->byte_code, opaque, lre_bytecode_realloc); dbuf_init2(&s->group_names, opaque, lre_realloc); dbuf_put_u16(&s->byte_code, re_flags); /* first element is the flags */ @@ -1820,11 +2491,11 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, } re_emit_op_u8(s, REOP_save_start, 0); - if (re_parse_disjunction(s, false)) { + if (re_parse_disjunction(s, FALSE)) { error: dbuf_free(&s->byte_code); dbuf_free(&s->group_names); - js__pstrcpy(error_msg, error_msg_size, s->u.error_msg); + pstrcpy(error_msg, error_msg_size, s->u.error_msg); *plen = 0; return NULL; } @@ -1843,7 +2514,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, goto error; } - stack_size = lre_compute_stack_size(s->byte_code.buf, s->byte_code.size); + stack_size = compute_stack_size(s->byte_code.buf, s->byte_code.size); if (stack_size < 0) { re_parse_error(s, "too many imbricated quantifiers"); goto error; @@ -1858,7 +2529,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, if (s->group_names.size > (s->capture_count - 1)) { dbuf_put(&s->byte_code, s->group_names.buf, s->group_names.size); put_u16(s->byte_code.buf + RE_HEADER_FLAGS, - LRE_FLAG_NAMED_GROUPS | lre_get_flags(s->byte_code.buf)); + lre_get_flags(s->byte_code.buf) | LRE_FLAG_NAMED_GROUPS); } dbuf_free(&s->group_names); @@ -1871,12 +2542,12 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, return s->byte_code.buf; } -static bool is_line_terminator(uint32_t c) +static BOOL is_line_terminator(uint32_t c) { return (c == '\n' || c == '\r' || c == CP_LS || c == CP_PS); } -static bool is_word_char(uint32_t c) +static BOOL is_word_char(uint32_t c) { return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || @@ -1892,11 +2563,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr; \ const uint16_t *_end = (const uint16_t *)cbuf_end; \ c = *_p++; \ - if (is_hi_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p < _end) \ - if (is_lo_surrogate(*_p)) \ - c = from_surrogate(c, *_p++); \ + if (is_hi_surrogate(c) && cbuf_type == 2) { \ + if (_p < _end && is_lo_surrogate(*_p)) { \ + c = from_surrogate(c, *_p++); \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) @@ -1909,11 +2580,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr; \ const uint16_t *_end = (const uint16_t *)cbuf_end; \ c = *_p++; \ - if (is_hi_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p < _end) \ - if (is_lo_surrogate(*_p)) \ - c = from_surrogate(c, *_p); \ + if (is_hi_surrogate(c) && cbuf_type == 2) { \ + if (_p < _end && is_lo_surrogate(*_p)) { \ + c = from_surrogate(c, *_p); \ + } \ + } \ } \ } while (0) @@ -1925,11 +2596,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ c = *_p; \ - if (is_lo_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - c = from_surrogate(*--_p, c); \ + if (is_lo_surrogate(c) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ + } \ + } \ } \ } while (0) @@ -1942,11 +2613,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ c = *_p; \ - if (is_lo_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - c = from_surrogate(*--_p, c); \ + if (is_lo_surrogate(c) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) @@ -1958,11 +2629,11 @@ static bool is_word_char(uint32_t c) } else { \ const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ - if (is_lo_surrogate(*_p)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - _p--; \ + if (is_lo_surrogate(*_p) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + --_p; \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) @@ -1982,7 +2653,7 @@ typedef struct REExecState { size_t count; /* only used for RE_EXEC_STATE_GREEDY_QUANT */ const uint8_t *cptr; const uint8_t *pc; - void *buf[]; + void *buf[0]; } REExecState; typedef struct { @@ -1992,9 +2663,7 @@ typedef struct { int cbuf_type; int capture_count; int stack_size_max; - bool multi_line; - bool ignore_case; - bool is_unicode; + BOOL is_unicode; int interrupt_counter; void *opaque; /* used for stack overflow check */ @@ -2056,7 +2725,7 @@ static int lre_poll_timeout(REExecContext *s) static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, StackInt *stack, int stack_len, const uint8_t *pc, const uint8_t *cptr, - bool no_recurse) + BOOL no_recurse) { int opcode, ret; int cbuf_type; @@ -2142,21 +2811,19 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, } break; case REOP_char32: + case REOP_char32_i: val = get_u32(pc); pc += 4; goto test_char; - case REOP_char16: + case REOP_char: + case REOP_char_i: val = get_u16(pc); pc += 2; - goto test_char; - case REOP_char8: - val = get_u8(pc); - pc += 1; test_char: if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_char_i || opcode == REOP_char32_i) { c = lre_canonicalize(c, s->is_unicode); } if (val != c) @@ -2200,18 +2867,20 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, return LRE_RET_TIMEOUT; break; case REOP_line_start: + case REOP_line_start_m: if (cptr == s->cbuf) break; - if (!s->multi_line) + if (opcode == REOP_line_start) goto no_match; PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); if (!is_line_terminator(c)) goto no_match; break; case REOP_line_end: + case REOP_line_end_m: if (cptr == cbuf_end) break; - if (!s->multi_line) + if (opcode == REOP_line_end) goto no_match; PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); if (!is_line_terminator(c)) @@ -2274,29 +2943,39 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, goto no_match; break; case REOP_word_boundary: + case REOP_word_boundary_i: case REOP_not_word_boundary: + case REOP_not_word_boundary_i: { - bool v1, v2; + BOOL v1, v2; + int ignore_case = (opcode == REOP_word_boundary_i || opcode == REOP_not_word_boundary_i); + BOOL is_boundary = (opcode == REOP_word_boundary || opcode == REOP_word_boundary_i); /* char before */ if (cptr == s->cbuf) { - v1 = false; + v1 = FALSE; } else { PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); + if (ignore_case) + c = lre_canonicalize(c, s->is_unicode); v1 = is_word_char(c); } /* current char */ if (cptr >= cbuf_end) { - v2 = false; + v2 = FALSE; } else { PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); + if (ignore_case) + c = lre_canonicalize(c, s->is_unicode); v2 = is_word_char(c); } - if (v1 ^ v2 ^ (REOP_not_word_boundary - opcode)) + if (v1 ^ v2 ^ is_boundary) goto no_match; } break; case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: + case REOP_backward_back_reference_i: { const uint8_t *cptr1, *cptr1_end, *cptr1_start; uint32_t c1, c2; @@ -2308,14 +2987,15 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, cptr1_end = capture[2 * val + 1]; if (!cptr1_start || !cptr1_end) break; - if (opcode == REOP_back_reference) { + if (opcode == REOP_back_reference || + opcode == REOP_back_reference_i) { cptr1 = cptr1_start; while (cptr1 < cptr1_end) { if (cptr >= cbuf_end) goto no_match; GET_CHAR(c1, cptr1, cptr1_end, cbuf_type); GET_CHAR(c2, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_back_reference_i) { c1 = lre_canonicalize(c1, s->is_unicode); c2 = lre_canonicalize(c2, s->is_unicode); } @@ -2329,7 +3009,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, goto no_match; GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type); GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_backward_back_reference_i) { c1 = lre_canonicalize(c1, s->is_unicode); c2 = lre_canonicalize(c2, s->is_unicode); } @@ -2340,6 +3020,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, } break; case REOP_range: + case REOP_range_i: { int n; uint32_t low, high, idx_min, idx_max, idx; @@ -2349,7 +3030,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_range_i) { c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; @@ -2380,6 +3061,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, } break; case REOP_range32: + case REOP_range32_i: { int n; uint32_t low, high, idx_min, idx_max, idx; @@ -2389,7 +3071,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_range32_i) { c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; @@ -2441,7 +3123,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (lre_poll_timeout(s)) return LRE_RET_TIMEOUT; res = lre_exec_backtrack(s, capture, stack, stack_len, - pc1, cptr, true); + pc1, cptr, TRUE); if (res == LRE_RET_MEMORY_ERROR || res == LRE_RET_TIMEOUT) return res; @@ -2481,11 +3163,10 @@ int lre_exec(uint8_t **capture, REExecContext s_s, *s = &s_s; int re_flags, i, alloca_size, ret; StackInt *stack_buf; + const uint8_t *cptr; re_flags = lre_get_flags(bc_buf); - s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0; - s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0; - s->is_unicode = (re_flags & LRE_FLAG_UNICODE) != 0; + s->is_unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0; s->capture_count = bc_buf[RE_HEADER_CAPTURE_COUNT]; s->stack_size_max = bc_buf[RE_HEADER_STACK_SIZE]; s->cbuf = cbuf; @@ -2507,8 +3188,17 @@ int lre_exec(uint8_t **capture, capture[i] = NULL; alloca_size = s->stack_size_max * sizeof(stack_buf[0]); stack_buf = alloca(alloca_size); + + cptr = cbuf + (cindex << cbuf_type); + if (0 < cindex && cindex < clen && s->cbuf_type == 2) { + const uint16_t *p = (const uint16_t *)cptr; + if (is_lo_surrogate(*p) && is_hi_surrogate(p[-1])) { + cptr = (const uint8_t *)(p - 1); + } + } + ret = lre_exec_backtrack(s, capture, stack_buf, 0, bc_buf + RE_HEADER_LEN, - cbuf + (cindex << cbuf_type), false); + cptr, FALSE); lre_realloc(s->opaque, s->state_stack, 0); return ret; } @@ -2534,85 +3224,11 @@ const char *lre_get_groupnames(const uint8_t *bc_buf) return (const char *)(bc_buf + RE_HEADER_LEN + re_bytecode_len); } -void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped) -{ - uint8_t *p, *pe; - uint32_t n, r, nw; - - p = buf; - if (len < RE_HEADER_LEN) - abort(); - - // format is: - //
- // - // - // - // etc. - inplace_bswap16(&p[RE_HEADER_FLAGS]); - - n = get_u32(&p[RE_HEADER_BYTECODE_LEN]); - inplace_bswap32(&p[RE_HEADER_BYTECODE_LEN]); - if (is_byte_swapped) - n = bswap32(n); - if (n > len - RE_HEADER_LEN) - abort(); - - p = &buf[RE_HEADER_LEN]; - pe = &p[n]; - - while (p < pe) { - n = reopcode_info[*p].size; - switch (n) { - case 1: - case 2: - break; - case 3: - switch (*p) { - case REOP_save_reset: // has two 8 bit arguments - break; - case REOP_range32: // variable length - nw = get_u16(&p[1]); // number of pairs of uint32_t - if (is_byte_swapped) - n = bswap16(n); - for (r = 3 + 8 * nw; n < r; n += 4) - inplace_bswap32(&p[n]); - goto doswap16; - case REOP_range: // variable length - nw = get_u16(&p[1]); // number of pairs of uint16_t - if (is_byte_swapped) - n = bswap16(n); - for (r = 3 + 4 * nw; n < r; n += 2) - inplace_bswap16(&p[n]); - goto doswap16; - default: - doswap16: - inplace_bswap16(&p[1]); - break; - } - break; - case 5: - inplace_bswap32(&p[1]); - break; - case 17: - assert(*p == REOP_simple_greedy_quant); - inplace_bswap32(&p[1]); - inplace_bswap32(&p[5]); - inplace_bswap32(&p[9]); - inplace_bswap32(&p[13]); - break; - default: - abort(); - } - p = &p[n]; - } -} - #ifdef TEST -bool lre_check_stack_overflow(void *opaque, size_t alloca_size) +BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size) { - return false; + return FALSE; } void *lre_realloc(void *opaque, void *ptr, size_t size) @@ -2631,7 +3247,7 @@ int main(int argc, char **argv) if (argc < 4) { printf("usage: %s regexp flags input\n", argv[0]); - exit(1); + return 1; } flags = atoi(argv[2]); bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1], diff --git a/quickjs-ng/libregexp.h b/quickjs/libregexp.h similarity index 71% rename from quickjs-ng/libregexp.h rename to quickjs/libregexp.h index 898e9a7..da76e4c 100644 --- a/quickjs-ng/libregexp.h +++ b/quickjs/libregexp.h @@ -24,14 +24,8 @@ #ifndef LIBREGEXP_H #define LIBREGEXP_H -#include #include - -#include "libunicode.h" - -#ifdef __cplusplus -extern "C" { -#endif +#include #define LRE_FLAG_GLOBAL (1 << 0) #define LRE_FLAG_IGNORECASE (1 << 1) @@ -57,41 +51,11 @@ int lre_exec(uint8_t **capture, int cbuf_type, void *opaque); int lre_parse_escape(const uint8_t **pp, int allow_utf16); -bool lre_is_space(int c); -void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped); - -/* must be provided by the user */ -bool lre_check_stack_overflow(void *opaque, size_t alloca_size); +/* must be provided by the user, return non zero if overflow */ +int lre_check_stack_overflow(void *opaque, size_t alloca_size); /* must be provided by the user, return non zero if time out */ int lre_check_timeout(void *opaque); void *lre_realloc(void *opaque, void *ptr, size_t size); -/* JS identifier test */ -extern uint32_t const lre_id_start_table_ascii[4]; -extern uint32_t const lre_id_continue_table_ascii[4]; - -static inline int lre_js_is_ident_first(int c) -{ - if ((uint32_t)c < 128) { - return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; - } else { - return lre_is_id_start(c); - } -} - -static inline int lre_js_is_ident_next(int c) -{ - if ((uint32_t)c < 128) { - return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; - } else { - /* ZWNJ and ZWJ are accepted in identifiers */ - return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; - } -} - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - #endif /* LIBREGEXP_H */ diff --git a/quickjs-ng/libunicode-table.h b/quickjs/libunicode-table.h similarity index 89% rename from quickjs-ng/libunicode-table.h rename to quickjs/libunicode-table.h index b48a3a7..67df6b3 100644 --- a/quickjs-ng/libunicode-table.h +++ b/quickjs/libunicode-table.h @@ -192,9 +192,12 @@ static const uint8_t unicode_prop_Cased1_table[193] = { }; static const uint8_t unicode_prop_Cased1_index[18] = { - 0xb9, 0x02, 0x80, 0xa0, 0x1e, 0x40, 0x9e, 0xa6, - 0x40, 0xbb, 0x07, 0x01, 0xdb, 0xd6, 0x01, 0x8a, - 0xf1, 0x01, + 0xb9, 0x02, 0x80, // 002B9 at 36 + 0xa0, 0x1e, 0x40, // 01EA0 at 66 + 0x9e, 0xa6, 0x40, // 0A69E at 98 + 0xbb, 0x07, 0x01, // 107BB at 128 + 0xdb, 0xd6, 0x01, // 1D6DB at 160 + 0x8a, 0xf1, 0x01, // 1F18A at 192 (upper bound) }; static const uint8_t unicode_prop_Case_Ignorable_table[764] = { @@ -297,15 +300,30 @@ static const uint8_t unicode_prop_Case_Ignorable_table[764] = { }; static const uint8_t unicode_prop_Case_Ignorable_index[72] = { - 0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a, - 0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f, - 0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20, - 0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0, - 0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56, - 0xfe, 0x20, 0xb1, 0x07, 0x01, 0x02, 0x10, 0x01, - 0x42, 0x12, 0x41, 0xc4, 0x14, 0x21, 0xe1, 0x19, - 0x81, 0x48, 0x1d, 0x01, 0x44, 0x6b, 0x01, 0x83, - 0xd1, 0x21, 0x3e, 0xe1, 0x01, 0xf0, 0x01, 0x0e, + 0xbe, 0x05, 0x00, // 005BE at 32 + 0xfe, 0x07, 0x00, // 007FE at 64 + 0x52, 0x0a, 0xa0, // 00A52 at 101 + 0xc1, 0x0b, 0x00, // 00BC1 at 128 + 0x82, 0x0d, 0x00, // 00D82 at 160 + 0x3f, 0x10, 0x80, // 0103F at 196 + 0xd4, 0x17, 0x40, // 017D4 at 226 + 0xcf, 0x1a, 0x20, // 01ACF at 257 + 0xf5, 0x1c, 0x00, // 01CF5 at 288 + 0x80, 0x20, 0x00, // 02080 at 320 + 0x16, 0xa0, 0x00, // 0A016 at 352 + 0xc6, 0xa8, 0x00, // 0A8C6 at 384 + 0xc2, 0xaa, 0x60, // 0AAC2 at 419 + 0x56, 0xfe, 0x20, // 0FE56 at 449 + 0xb1, 0x07, 0x01, // 107B1 at 480 + 0x02, 0x10, 0x01, // 11002 at 512 + 0x42, 0x12, 0x41, // 11242 at 546 + 0xc4, 0x14, 0x21, // 114C4 at 577 + 0xe1, 0x19, 0x81, // 119E1 at 612 + 0x48, 0x1d, 0x01, // 11D48 at 640 + 0x44, 0x6b, 0x01, // 16B44 at 672 + 0x83, 0xd1, 0x21, // 1D183 at 705 + 0x3e, 0xe1, 0x01, // 1E13E at 736 + 0xf0, 0x01, 0x0e, // E01F0 at 768 (upper bound) }; static const uint8_t unicode_prop_ID_Start_table[1133] = { @@ -454,20 +472,42 @@ static const uint8_t unicode_prop_ID_Start_table[1133] = { }; static const uint8_t unicode_prop_ID_Start_index[108] = { - 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09, - 0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b, - 0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00, - 0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d, - 0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00, - 0x32, 0x00, 0xdd, 0xa7, 0x00, 0x4c, 0xaa, 0x20, - 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02, - 0x21, 0x96, 0x05, 0x01, 0x9f, 0x08, 0x01, 0x49, - 0x0c, 0x21, 0x76, 0x10, 0x21, 0xa9, 0x12, 0x01, - 0xb0, 0x14, 0x01, 0x42, 0x19, 0x41, 0x90, 0x1c, - 0x01, 0xf1, 0x2f, 0x21, 0x90, 0x6b, 0x21, 0x33, - 0xb1, 0x21, 0x06, 0xd5, 0x01, 0xc3, 0xd7, 0x01, - 0xff, 0xe7, 0x21, 0x63, 0xee, 0x01, 0x5e, 0xee, - 0x42, 0xb0, 0x23, 0x03, + 0xf6, 0x03, 0x20, // 003F6 at 33 + 0xa6, 0x07, 0x00, // 007A6 at 64 + 0xa9, 0x09, 0x20, // 009A9 at 97 + 0xb1, 0x0a, 0x00, // 00AB1 at 128 + 0xba, 0x0b, 0x20, // 00BBA at 161 + 0x3b, 0x0d, 0x20, // 00D3B at 193 + 0xc7, 0x0e, 0x20, // 00EC7 at 225 + 0x49, 0x12, 0x00, // 01249 at 256 + 0x9b, 0x16, 0x00, // 0169B at 288 + 0xac, 0x19, 0x00, // 019AC at 320 + 0xc0, 0x1d, 0x80, // 01DC0 at 356 + 0x80, 0x20, 0x20, // 02080 at 385 + 0x70, 0x2d, 0x00, // 02D70 at 416 + 0x00, 0x32, 0x00, // 03200 at 448 + 0xdd, 0xa7, 0x00, // 0A7DD at 480 + 0x4c, 0xaa, 0x20, // 0AA4C at 513 + 0xc7, 0xd7, 0x20, // 0D7C7 at 545 + 0xfc, 0xfd, 0x20, // 0FDFC at 577 + 0x9d, 0x02, 0x21, // 1029D at 609 + 0x96, 0x05, 0x01, // 10596 at 640 + 0x9f, 0x08, 0x01, // 1089F at 672 + 0x49, 0x0c, 0x21, // 10C49 at 705 + 0x76, 0x10, 0x21, // 11076 at 737 + 0xa9, 0x12, 0x01, // 112A9 at 768 + 0xb0, 0x14, 0x01, // 114B0 at 800 + 0x42, 0x19, 0x41, // 11942 at 834 + 0x90, 0x1c, 0x01, // 11C90 at 864 + 0xf1, 0x2f, 0x21, // 12FF1 at 897 + 0x90, 0x6b, 0x21, // 16B90 at 929 + 0x33, 0xb1, 0x21, // 1B133 at 961 + 0x06, 0xd5, 0x01, // 1D506 at 992 + 0xc3, 0xd7, 0x01, // 1D7C3 at 1024 + 0xff, 0xe7, 0x21, // 1E7FF at 1057 + 0x63, 0xee, 0x01, // 1EE63 at 1088 + 0x5e, 0xee, 0x42, // 2EE5E at 1122 + 0xb0, 0x23, 0x03, // 323B0 at 1152 (upper bound) }; static const uint8_t unicode_prop_ID_Continue1_table[695] = { @@ -561,26 +601,31 @@ static const uint8_t unicode_prop_ID_Continue1_table[695] = { }; static const uint8_t unicode_prop_ID_Continue1_index[66] = { - 0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a, - 0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x60, 0xc7, - 0x0f, 0x20, 0xea, 0x17, 0x40, 0x05, 0x1b, 0x00, - 0x0e, 0x20, 0x00, 0xa0, 0xa6, 0x20, 0xe6, 0xa9, - 0x20, 0x10, 0xfe, 0x00, 0x40, 0x0a, 0x01, 0xc3, - 0x10, 0x01, 0x4e, 0x13, 0x01, 0x41, 0x16, 0x01, - 0x0b, 0x1a, 0x01, 0xaa, 0x1d, 0x01, 0x7a, 0x6d, - 0x21, 0x45, 0xd2, 0x21, 0xaf, 0xe2, 0x01, 0xf0, - 0x01, 0x0e, + 0xfa, 0x06, 0x00, // 006FA at 32 + 0x70, 0x09, 0x00, // 00970 at 64 + 0xf0, 0x0a, 0x40, // 00AF0 at 98 + 0x57, 0x0c, 0x00, // 00C57 at 128 + 0xf0, 0x0d, 0x60, // 00DF0 at 163 + 0xc7, 0x0f, 0x20, // 00FC7 at 193 + 0xea, 0x17, 0x40, // 017EA at 226 + 0x05, 0x1b, 0x00, // 01B05 at 256 + 0x0e, 0x20, 0x00, // 0200E at 288 + 0xa0, 0xa6, 0x20, // 0A6A0 at 321 + 0xe6, 0xa9, 0x20, // 0A9E6 at 353 + 0x10, 0xfe, 0x00, // 0FE10 at 384 + 0x40, 0x0a, 0x01, // 10A40 at 416 + 0xc3, 0x10, 0x01, // 110C3 at 448 + 0x4e, 0x13, 0x01, // 1134E at 480 + 0x41, 0x16, 0x01, // 11641 at 512 + 0x0b, 0x1a, 0x01, // 11A0B at 544 + 0xaa, 0x1d, 0x01, // 11DAA at 576 + 0x7a, 0x6d, 0x21, // 16D7A at 609 + 0x45, 0xd2, 0x21, // 1D245 at 641 + 0xaf, 0xe2, 0x01, // 1E2AF at 672 + 0xf0, 0x01, 0x0e, // E01F0 at 704 (upper bound) }; -static const uint8_t unicode_prop_White_Space_table[22] = { - 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x99, 0x80, - 0x55, 0xde, 0x80, 0x49, 0x7e, 0x8a, 0x9c, 0x0c, - 0x80, 0xae, 0x80, 0x4f, 0x9f, 0x80, -}; - -static const uint8_t unicode_prop_White_Space_index[3] = { - 0x01, 0x30, 0x00, -}; +#ifdef CONFIG_ALL_UNICODE static const uint8_t unicode_cc_table[916] = { 0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00, @@ -701,17 +746,35 @@ static const uint8_t unicode_cc_table[916] = { }; static const uint8_t unicode_cc_index[87] = { - 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05, - 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c, - 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00, - 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10, - 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3, - 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00, - 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab, - 0x00, 0x39, 0x0a, 0x01, 0x4c, 0x0f, 0x01, 0x35, - 0x11, 0x21, 0x66, 0x13, 0x01, 0x40, 0x16, 0x01, - 0x47, 0x1a, 0x01, 0xf0, 0x6a, 0x21, 0x8a, 0xd1, - 0x01, 0xec, 0xe4, 0x21, 0x4b, 0xe9, 0x01, + 0x4d, 0x03, 0x00, // 0034D at 32 + 0x97, 0x05, 0x20, // 00597 at 65 + 0xc6, 0x05, 0x00, // 005C6 at 96 + 0xe7, 0x06, 0x00, // 006E7 at 128 + 0x45, 0x07, 0x00, // 00745 at 160 + 0x9c, 0x08, 0x00, // 0089C at 192 + 0x4d, 0x09, 0x00, // 0094D at 224 + 0x3c, 0x0b, 0x00, // 00B3C at 256 + 0x3d, 0x0d, 0x00, // 00D3D at 288 + 0x36, 0x0f, 0x00, // 00F36 at 320 + 0x38, 0x10, 0x20, // 01038 at 353 + 0x3a, 0x19, 0x00, // 0193A at 384 + 0xcb, 0x1a, 0x20, // 01ACB at 417 + 0xd3, 0x1c, 0x00, // 01CD3 at 448 + 0xcf, 0x1d, 0x00, // 01DCF at 480 + 0xe2, 0x20, 0x00, // 020E2 at 512 + 0x2e, 0x30, 0x20, // 0302E at 545 + 0x2b, 0xa9, 0x20, // 0A92B at 577 + 0xed, 0xab, 0x00, // 0ABED at 608 + 0x39, 0x0a, 0x01, // 10A39 at 640 + 0x4c, 0x0f, 0x01, // 10F4C at 672 + 0x35, 0x11, 0x21, // 11135 at 705 + 0x66, 0x13, 0x01, // 11366 at 736 + 0x40, 0x16, 0x01, // 11640 at 768 + 0x47, 0x1a, 0x01, // 11A47 at 800 + 0xf0, 0x6a, 0x21, // 16AF0 at 833 + 0x8a, 0xd1, 0x01, // 1D18A at 864 + 0xec, 0xe4, 0x21, // 1E4EC at 897 + 0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound) }; static const uint32_t unicode_decomp_table1[709] = { @@ -2932,10 +2995,10 @@ typedef enum { UNICODE_SCRIPT_Elbasan, UNICODE_SCRIPT_Elymaic, UNICODE_SCRIPT_Ethiopic, + UNICODE_SCRIPT_Garay, UNICODE_SCRIPT_Georgian, UNICODE_SCRIPT_Glagolitic, UNICODE_SCRIPT_Gothic, - UNICODE_SCRIPT_Garay, UNICODE_SCRIPT_Grantha, UNICODE_SCRIPT_Greek, UNICODE_SCRIPT_Gujarati, @@ -3067,6 +3130,7 @@ typedef enum { } UnicodeScriptEnum; static const char unicode_script_name_table[] = + "Unknown,Zzzz" "\0" "Adlam,Adlm" "\0" "Ahom,Ahom" "\0" "Anatolian_Hieroglyphs,Hluw" "\0" @@ -3106,10 +3170,10 @@ static const char unicode_script_name_table[] = "Elbasan,Elba" "\0" "Elymaic,Elym" "\0" "Ethiopic,Ethi" "\0" + "Garay,Gara" "\0" "Georgian,Geor" "\0" "Glagolitic,Glag" "\0" "Gothic,Goth" "\0" - "Garay,Gara" "\0" "Grantha,Gran" "\0" "Greek,Grek" "\0" "Gujarati,Gujr" "\0" @@ -3317,9 +3381,9 @@ static const uint8_t unicode_script_table[2803] = { 0x1f, 0xc7, 0x9c, 0x00, 0xa3, 0x9c, 0x03, 0xa6, 0x9c, 0x00, 0xa3, 0x9c, 0x00, 0x8e, 0x9c, 0x00, 0x86, 0x9c, 0x83, 0x19, 0x81, 0x9c, 0x24, 0xe0, - 0x3f, 0x63, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, - 0x80, 0x28, 0x01, 0xaa, 0x28, 0x80, 0x19, 0x83, - 0x28, 0xe0, 0x9f, 0x33, 0xc8, 0x27, 0x00, 0x83, + 0x3f, 0x63, 0xa5, 0x29, 0x00, 0x80, 0x29, 0x04, + 0x80, 0x29, 0x01, 0xaa, 0x29, 0x80, 0x19, 0x83, + 0x29, 0xe0, 0x9f, 0x33, 0xc8, 0x27, 0x00, 0x83, 0x27, 0x01, 0x86, 0x27, 0x00, 0x80, 0x27, 0x00, 0x83, 0x27, 0x01, 0xa8, 0x27, 0x00, 0x83, 0x27, 0x01, 0xa0, 0x27, 0x00, 0x83, 0x27, 0x01, 0x86, @@ -3345,7 +3409,7 @@ static const uint8_t unicode_script_table[2803] = { 0xcc, 0x07, 0x00, 0xb1, 0x07, 0xbf, 0x8d, 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x4b, 0x02, 0x8e, 0x4b, 0x02, 0x82, 0x4b, 0xaf, 0x6d, 0x8a, 0x1d, - 0x04, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87, 0x8d, + 0x04, 0xaa, 0x29, 0x01, 0x82, 0x29, 0x87, 0x8d, 0x07, 0x82, 0x3a, 0x80, 0x19, 0x8c, 0x3a, 0x80, 0x19, 0x86, 0x3a, 0x83, 0x19, 0x80, 0x3a, 0x85, 0x19, 0x80, 0x3a, 0x82, 0x19, 0x81, 0x3a, 0x80, @@ -3368,9 +3432,9 @@ static const uint8_t unicode_script_table[2803] = { 0xe2, 0x39, 0x19, 0x15, 0x8a, 0x19, 0x14, 0xe3, 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, 0x19, 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19, 0xdf, - 0x29, 0x9f, 0x4a, 0xe0, 0x13, 0x1a, 0x04, 0x86, - 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, 0x80, - 0x28, 0x01, 0xb7, 0x9d, 0x06, 0x81, 0x9d, 0x0d, + 0x2a, 0x9f, 0x4a, 0xe0, 0x13, 0x1a, 0x04, 0x86, + 0x1a, 0xa5, 0x29, 0x00, 0x80, 0x29, 0x04, 0x80, + 0x29, 0x01, 0xb7, 0x9d, 0x06, 0x81, 0x9d, 0x0d, 0x80, 0x9d, 0x96, 0x27, 0x08, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, @@ -3429,7 +3493,7 @@ static const uint8_t unicode_script_table[2803] = { 0x80, 0x2d, 0x2e, 0xac, 0x19, 0x80, 0x3a, 0x60, 0x21, 0x9c, 0x50, 0x02, 0xb0, 0x13, 0x0e, 0x80, 0x3a, 0x9a, 0x19, 0x03, 0xa3, 0x70, 0x08, 0x82, - 0x70, 0x9a, 0x2a, 0x04, 0xaa, 0x72, 0x04, 0x9d, + 0x70, 0x9a, 0x2b, 0x04, 0xaa, 0x72, 0x04, 0x9d, 0xa3, 0x00, 0x80, 0xa3, 0xa3, 0x73, 0x03, 0x8d, 0x73, 0x29, 0xcf, 0x1f, 0xaf, 0x86, 0x9d, 0x7a, 0x01, 0x89, 0x7a, 0x05, 0xa3, 0x79, 0x03, 0xa3, @@ -3457,7 +3521,7 @@ static const uint8_t unicode_script_table[2803] = { 0x83, 0x80, 0x0b, 0x86, 0x80, 0x4f, 0xc8, 0x76, 0x36, 0xb2, 0x6f, 0x0c, 0xb2, 0x6f, 0x06, 0x85, 0x6f, 0xa7, 0x34, 0x07, 0x89, 0x34, 0x05, 0xa5, - 0x2b, 0x02, 0x9c, 0x2b, 0x07, 0x81, 0x2b, 0x60, + 0x28, 0x02, 0x9c, 0x28, 0x07, 0x81, 0x28, 0x60, 0x6f, 0x9e, 0x04, 0x00, 0xa9, 0xa8, 0x00, 0x82, 0xa8, 0x01, 0x81, 0xa8, 0x0f, 0x82, 0x04, 0x36, 0x83, 0x04, 0xa7, 0x74, 0x07, 0xa9, 0x8a, 0x15, @@ -3544,8 +3608,8 @@ static const uint8_t unicode_script_table[2803] = { 0x01, 0xe0, 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, 0x2b, 0x88, 0x0e, 0x84, 0x88, 0x00, 0x8e, 0x88, 0x63, 0xef, 0x9e, 0x4a, 0x05, 0x85, 0x4a, 0x60, - 0x74, 0x86, 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, - 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, + 0x74, 0x86, 0x2a, 0x00, 0x90, 0x2a, 0x01, 0x86, + 0x2a, 0x00, 0x81, 0x2a, 0x00, 0x84, 0x2a, 0x04, 0xbd, 0x1d, 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, 0x6b, 0x02, 0x8d, 0x6b, 0x01, 0x89, 0x6b, 0x03, 0x81, 0x6b, 0x60, 0xdf, 0x9e, 0xa1, 0x10, 0xb9, @@ -3595,7 +3659,7 @@ static const uint8_t unicode_script_table[2803] = { static const uint8_t unicode_script_ext_table[1253] = { 0x80, 0x36, 0x00, 0x00, 0x10, 0x06, 0x13, 0x1a, - 0x23, 0x25, 0x28, 0x29, 0x2f, 0x2a, 0x2d, 0x32, + 0x23, 0x25, 0x29, 0x2a, 0x2f, 0x2b, 0x2d, 0x32, 0x4a, 0x51, 0x53, 0x72, 0x86, 0x81, 0x83, 0x00, 0x00, 0x07, 0x0b, 0x1d, 0x20, 0x4a, 0x4f, 0x9b, 0xa1, 0x09, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x00, @@ -3605,13 +3669,13 @@ static const uint8_t unicode_script_ext_table[1253] = { 0x00, 0x00, 0x08, 0x17, 0x1a, 0x1d, 0x2d, 0x4a, 0x72, 0x8e, 0x93, 0x00, 0x08, 0x17, 0x1d, 0x2d, 0x4a, 0x79, 0x8e, 0x93, 0xa0, 0x00, 0x04, 0x17, - 0x1d, 0x4a, 0x9d, 0x00, 0x05, 0x29, 0x4a, 0x8e, + 0x1d, 0x4a, 0x9d, 0x00, 0x05, 0x2a, 0x4a, 0x8e, 0x90, 0x9b, 0x00, 0x0b, 0x14, 0x17, 0x1a, 0x1d, - 0x2a, 0x2d, 0x4a, 0x79, 0x90, 0x9d, 0xa0, 0x00, - 0x06, 0x1a, 0x25, 0x29, 0x2a, 0x40, 0x4a, 0x00, + 0x2b, 0x2d, 0x4a, 0x79, 0x90, 0x9d, 0xa0, 0x00, + 0x06, 0x1a, 0x25, 0x2a, 0x2b, 0x40, 0x4a, 0x00, 0x04, 0x1d, 0x2d, 0x4a, 0x72, 0x00, 0x09, 0x1a, 0x23, 0x37, 0x4a, 0x72, 0x90, 0x93, 0x9d, 0xa0, - 0x00, 0x0a, 0x05, 0x1d, 0x23, 0x2a, 0x2d, 0x37, + 0x00, 0x0a, 0x05, 0x1d, 0x23, 0x2b, 0x2d, 0x37, 0x4a, 0x72, 0x90, 0x93, 0x00, 0x02, 0x4a, 0x9d, 0x00, 0x03, 0x23, 0x4a, 0x90, 0x00, 0x04, 0x17, 0x1d, 0x4a, 0x79, 0x00, 0x03, 0x17, 0x4a, 0x93, @@ -3624,19 +3688,19 @@ static const uint8_t unicode_script_ext_table[1253] = { 0x00, 0x02, 0x4a, 0x90, 0x06, 0x00, 0x00, 0x03, 0x4a, 0x8e, 0x90, 0x00, 0x02, 0x4a, 0x90, 0x00, 0x00, 0x00, 0x03, 0x17, 0x4a, 0x90, 0x00, 0x06, - 0x14, 0x17, 0x2a, 0x4a, 0x8e, 0x9b, 0x0f, 0x00, + 0x14, 0x17, 0x2b, 0x4a, 0x8e, 0x9b, 0x0f, 0x00, 0x00, 0x01, 0x2d, 0x01, 0x00, 0x00, 0x01, 0x2d, 0x11, 0x00, 0x00, 0x02, 0x4a, 0x79, 0x04, 0x00, 0x00, 0x03, 0x14, 0x4a, 0xa0, 0x03, 0x00, 0x0c, 0x01, 0x4a, 0x03, 0x00, 0x01, 0x02, 0x1a, 0x2d, 0x80, 0x8c, 0x00, 0x00, 0x02, 0x1d, 0x72, 0x00, - 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x4a, 0x00, - 0x02, 0x1d, 0x29, 0x80, 0x80, 0x00, 0x00, 0x03, - 0x05, 0x28, 0x29, 0x80, 0x01, 0x00, 0x00, 0x07, - 0x04, 0x2b, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x0d, - 0x00, 0x00, 0x07, 0x04, 0x2b, 0x69, 0x34, 0x90, + 0x02, 0x1d, 0x2a, 0x01, 0x02, 0x1d, 0x4a, 0x00, + 0x02, 0x1d, 0x2a, 0x80, 0x80, 0x00, 0x00, 0x03, + 0x05, 0x29, 0x2a, 0x80, 0x01, 0x00, 0x00, 0x07, + 0x04, 0x28, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x0d, + 0x00, 0x00, 0x07, 0x04, 0x28, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x00, 0x03, 0x04, 0x90, 0x9a, 0x01, - 0x00, 0x00, 0x08, 0x01, 0x04, 0x2b, 0x69, 0x34, + 0x00, 0x00, 0x08, 0x01, 0x04, 0x28, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x55, 0x56, 0x77, 0x80, 0x34, 0x8a, 0x90, 0x09, 0x00, 0x0a, 0x02, 0x04, 0x90, 0x09, 0x00, @@ -3659,7 +3723,7 @@ static const uint8_t unicode_script_ext_table[1253] = { 0x02, 0x2c, 0x97, 0x80, 0x71, 0x00, 0x09, 0x03, 0x3f, 0x66, 0xa2, 0x82, 0xcf, 0x00, 0x09, 0x03, 0x15, 0x63, 0x93, 0x80, 0x30, 0x00, 0x00, 0x03, - 0x28, 0x29, 0x4a, 0x85, 0x6e, 0x00, 0x02, 0x01, + 0x29, 0x2a, 0x4a, 0x85, 0x6e, 0x00, 0x02, 0x01, 0x82, 0x46, 0x00, 0x01, 0x04, 0x11, 0x35, 0x92, 0x91, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x02, 0x60, 0x7e, 0x84, 0x49, @@ -3683,14 +3747,14 @@ static const uint8_t unicode_script_ext_table[1253] = { 0x90, 0x00, 0x00, 0x00, 0x01, 0x90, 0x81, 0xb3, 0x00, 0x00, 0x03, 0x4a, 0x60, 0x7e, 0x1e, 0x00, 0x00, 0x02, 0x01, 0x04, 0x09, 0x00, 0x00, 0x06, - 0x13, 0x28, 0x29, 0x6f, 0x50, 0x76, 0x01, 0x00, + 0x13, 0x29, 0x2a, 0x6f, 0x50, 0x76, 0x01, 0x00, 0x00, 0x04, 0x13, 0x2d, 0x6f, 0x5d, 0x80, 0x11, 0x00, 0x00, 0x03, 0x20, 0x2c, 0x4a, 0x8c, 0xa5, 0x00, 0x00, 0x02, 0x1a, 0x4a, 0x17, 0x00, 0x00, - 0x02, 0x06, 0x76, 0x00, 0x07, 0x06, 0x13, 0x28, + 0x02, 0x06, 0x76, 0x00, 0x07, 0x06, 0x13, 0x29, 0x6f, 0x3e, 0x51, 0x83, 0x09, 0x00, 0x00, 0x01, 0x23, 0x03, 0x00, 0x00, 0x03, 0x01, 0x04, 0x6f, - 0x00, 0x00, 0x00, 0x02, 0x1d, 0x29, 0x81, 0x2b, + 0x00, 0x00, 0x00, 0x02, 0x1d, 0x2a, 0x81, 0x2b, 0x00, 0x0f, 0x02, 0x32, 0x98, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, 0xa9, 0x00, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, @@ -3718,7 +3782,7 @@ static const uint8_t unicode_script_ext_table[1253] = { 0x01, 0x32, 0x57, 0x00, 0x18, 0x01, 0x32, 0x09, 0x00, 0x04, 0x01, 0x32, 0x5f, 0x00, 0x1e, 0x01, 0x32, 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, - 0x29, 0x80, 0x0f, 0x00, 0x07, 0x02, 0x32, 0x4a, + 0x2a, 0x80, 0x0f, 0x00, 0x07, 0x02, 0x32, 0x4a, 0x80, 0xa7, 0x00, 0x02, 0x10, 0x20, 0x22, 0x2e, 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x54, 0x5f, 0x66, 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x02, 0x0f, 0x20, @@ -3991,6 +4055,89 @@ static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[450] = { 0x4f, 0xff, }; +static const uint8_t unicode_prop_Basic_Emoji1_table[143] = { + 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, + 0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b, + 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, + 0x0c, 0x0f, 0x04, 0x80, 0x94, 0x06, 0x08, 0x03, + 0x01, 0x06, 0x03, 0x81, 0x9b, 0x80, 0xa2, 0x00, + 0x03, 0x10, 0x80, 0xbc, 0x82, 0x97, 0x80, 0x8d, + 0x80, 0x43, 0x5a, 0x81, 0xb2, 0x03, 0x80, 0x61, + 0xc4, 0xad, 0x80, 0x40, 0xc9, 0x80, 0x40, 0xbd, + 0x01, 0x89, 0xe5, 0x80, 0x97, 0x80, 0x93, 0x01, + 0x20, 0x82, 0x94, 0x81, 0x40, 0xad, 0xa0, 0x8b, + 0x88, 0x80, 0xc5, 0x80, 0x95, 0x8b, 0xaa, 0x1c, + 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80, 0x40, + 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91, 0x80, + 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf, 0xc5, + 0x28, 0x12, 0x0a, 0x1b, 0x8a, 0x0e, 0x88, 0x40, + 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, + 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, 0x84, + 0xb7, 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88, +}; + +static const uint8_t unicode_prop_Basic_Emoji2_table[183] = { + 0x40, 0xa8, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, + 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, + 0x8e, 0x81, 0x41, 0x7c, 0x80, 0x40, 0xa5, 0x80, + 0x9c, 0x10, 0x0c, 0x82, 0x40, 0xc6, 0x80, 0x40, + 0xe6, 0x81, 0x89, 0x80, 0x88, 0x80, 0xb9, 0x0a, + 0x84, 0x88, 0x01, 0x05, 0x03, 0x01, 0x00, 0x09, + 0x02, 0x02, 0x0f, 0x14, 0x00, 0x80, 0x9b, 0x09, + 0x00, 0x08, 0x80, 0x91, 0x01, 0x80, 0x92, 0x00, + 0x18, 0x00, 0x0a, 0x05, 0x07, 0x81, 0x95, 0x05, + 0x00, 0x00, 0x80, 0x94, 0x05, 0x09, 0x01, 0x17, + 0x04, 0x09, 0x08, 0x01, 0x00, 0x00, 0x05, 0x02, + 0x80, 0x90, 0x81, 0x8e, 0x01, 0x80, 0x9a, 0x81, + 0xbb, 0x80, 0x41, 0x91, 0x81, 0x41, 0xce, 0x82, + 0x45, 0x27, 0x80, 0x8b, 0x80, 0x42, 0x58, 0x00, + 0x80, 0x61, 0xbe, 0xd5, 0x81, 0x8b, 0x81, 0x40, + 0x81, 0x80, 0xb3, 0x80, 0x40, 0xe8, 0x01, 0x88, + 0x88, 0x80, 0xc5, 0x80, 0x97, 0x08, 0x11, 0x81, + 0xaa, 0x1c, 0x8b, 0x92, 0x00, 0x00, 0x80, 0xc6, + 0x00, 0x80, 0x40, 0xba, 0x80, 0xca, 0x81, 0xa3, + 0x09, 0x86, 0x8c, 0x01, 0x19, 0x80, 0x93, 0x01, + 0x07, 0x81, 0x88, 0x04, 0x82, 0x8b, 0x17, 0x11, + 0x00, 0x03, 0x05, 0x02, 0x05, 0x80, 0x40, 0xcf, + 0x00, 0x82, 0x8f, 0x2a, 0x05, 0x01, 0x80, +}; + +static const uint8_t unicode_prop_RGI_Emoji_Modifier_Sequence_table[73] = { + 0x60, 0x26, 0x1c, 0x80, 0x40, 0xda, 0x80, 0x8f, + 0x83, 0x61, 0xcc, 0x76, 0x80, 0xbb, 0x11, 0x01, + 0x82, 0xf4, 0x09, 0x8a, 0x94, 0x18, 0x18, 0x88, + 0x10, 0x1a, 0x02, 0x30, 0x00, 0x97, 0x80, 0x40, + 0xc8, 0x0b, 0x80, 0x94, 0x03, 0x81, 0x40, 0xad, + 0x12, 0x84, 0xd2, 0x80, 0x8f, 0x82, 0x88, 0x80, + 0x8a, 0x80, 0x42, 0x3e, 0x01, 0x07, 0x3d, 0x80, + 0x88, 0x89, 0x11, 0xb7, 0x80, 0xbc, 0x08, 0x08, + 0x80, 0x90, 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, + 0x88, +}; + +static const uint8_t unicode_prop_RGI_Emoji_Flag_Sequence_table[128] = { + 0x0c, 0x00, 0x09, 0x00, 0x04, 0x01, 0x02, 0x06, + 0x03, 0x03, 0x01, 0x02, 0x01, 0x03, 0x07, 0x0d, + 0x18, 0x00, 0x09, 0x00, 0x00, 0x89, 0x08, 0x00, + 0x00, 0x81, 0x88, 0x83, 0x8c, 0x10, 0x00, 0x01, + 0x07, 0x08, 0x29, 0x10, 0x28, 0x00, 0x80, 0x8a, + 0x00, 0x0a, 0x00, 0x0e, 0x15, 0x18, 0x83, 0x89, + 0x06, 0x00, 0x81, 0x8d, 0x00, 0x12, 0x08, 0x00, + 0x03, 0x00, 0x24, 0x00, 0x05, 0x21, 0x00, 0x00, + 0x29, 0x90, 0x00, 0x02, 0x00, 0x08, 0x09, 0x00, + 0x08, 0x18, 0x8b, 0x80, 0x8c, 0x02, 0x19, 0x1a, + 0x11, 0x00, 0x00, 0x80, 0x9c, 0x80, 0x88, 0x02, + 0x00, 0x00, 0x02, 0x20, 0x88, 0x0a, 0x00, 0x03, + 0x01, 0x02, 0x05, 0x08, 0x00, 0x01, 0x09, 0x20, + 0x21, 0x18, 0x22, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x28, 0x89, 0x80, 0x8b, 0x80, 0x90, 0x80, 0x92, + 0x80, 0x8d, 0x05, 0x80, 0x8a, 0x80, 0x88, 0x80, +}; + +static const uint8_t unicode_prop_Emoji_Keycap_Sequence_table[4] = { + 0xa2, 0x05, 0x04, 0x89, +}; + static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = { 0xaf, 0x89, 0x35, 0x99, 0x85, }; @@ -4272,6 +4419,12 @@ static const uint8_t unicode_prop_Variation_Selector_table[13] = { 0x6d, 0x02, 0xef, 0x40, 0xef, }; +static const uint8_t unicode_prop_White_Space_table[22] = { + 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x99, 0x80, + 0x55, 0xde, 0x80, 0x49, 0x7e, 0x8a, 0x9c, 0x0c, + 0x80, 0xae, 0x80, 0x4f, 0x9f, 0x80, +}; + static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = { 0xa7, 0x81, 0x91, 0x00, 0x80, 0x9b, 0x00, 0x80, 0x9c, 0x00, 0x80, 0xac, 0x80, 0x8e, 0x80, 0x4e, @@ -4424,6 +4577,11 @@ typedef enum { UNICODE_PROP_Changes_When_Titlecased1, UNICODE_PROP_Changes_When_Casefolded1, UNICODE_PROP_Changes_When_NFKC_Casefolded1, + UNICODE_PROP_Basic_Emoji1, + UNICODE_PROP_Basic_Emoji2, + UNICODE_PROP_RGI_Emoji_Modifier_Sequence, + UNICODE_PROP_RGI_Emoji_Flag_Sequence, + UNICODE_PROP_Emoji_Keycap_Sequence, UNICODE_PROP_ASCII_Hex_Digit, UNICODE_PROP_Bidi_Control, UNICODE_PROP_Dash, @@ -4476,13 +4634,13 @@ typedef enum { UNICODE_PROP_ID_Continue, UNICODE_PROP_ID_Compat_Math_Start, UNICODE_PROP_ID_Compat_Math_Continue, + UNICODE_PROP_InCB, UNICODE_PROP_Lowercase, UNICODE_PROP_Math, UNICODE_PROP_Uppercase, UNICODE_PROP_XID_Continue, UNICODE_PROP_XID_Start, UNICODE_PROP_Cased1, - UNICODE_PROP_InCB, UNICODE_PROP_COUNT, } UnicodePropertyEnum; @@ -4539,6 +4697,7 @@ static const char unicode_prop_name_table[] = "ID_Continue,IDC" "\0" "ID_Compat_Math_Start" "\0" "ID_Compat_Math_Continue" "\0" + "InCB" "\0" "Lowercase,Lower" "\0" "Math" "\0" "Uppercase,Upper" "\0" @@ -4563,6 +4722,11 @@ static const uint8_t * const unicode_prop_table[] = { unicode_prop_Changes_When_Titlecased1_table, unicode_prop_Changes_When_Casefolded1_table, unicode_prop_Changes_When_NFKC_Casefolded1_table, + unicode_prop_Basic_Emoji1_table, + unicode_prop_Basic_Emoji2_table, + unicode_prop_RGI_Emoji_Modifier_Sequence_table, + unicode_prop_RGI_Emoji_Flag_Sequence_table, + unicode_prop_Emoji_Keycap_Sequence_table, unicode_prop_ASCII_Hex_Digit_table, unicode_prop_Bidi_Control_table, unicode_prop_Dash_table, @@ -4618,6 +4782,11 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Changes_When_Titlecased1_table), countof(unicode_prop_Changes_When_Casefolded1_table), countof(unicode_prop_Changes_When_NFKC_Casefolded1_table), + countof(unicode_prop_Basic_Emoji1_table), + countof(unicode_prop_Basic_Emoji2_table), + countof(unicode_prop_RGI_Emoji_Modifier_Sequence_table), + countof(unicode_prop_RGI_Emoji_Flag_Sequence_table), + countof(unicode_prop_Emoji_Keycap_Sequence_table), countof(unicode_prop_ASCII_Hex_Digit_table), countof(unicode_prop_Bidi_Control_table), countof(unicode_prop_Dash_table), @@ -4656,3 +4825,325 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Case_Ignorable_table), }; +typedef enum { + UNICODE_SEQUENCE_PROP_Basic_Emoji, + UNICODE_SEQUENCE_PROP_Emoji_Keycap_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Flag_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Tag_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji, + UNICODE_SEQUENCE_PROP_COUNT, +} UnicodeSequencePropertyEnum; + +static const char unicode_sequence_prop_name_table[] = + "Basic_Emoji" "\0" + "Emoji_Keycap_Sequence" "\0" + "RGI_Emoji_Modifier_Sequence" "\0" + "RGI_Emoji_Flag_Sequence" "\0" + "RGI_Emoji_Tag_Sequence" "\0" + "RGI_Emoji_ZWJ_Sequence" "\0" + "RGI_Emoji" "\0" +; + +static const uint8_t unicode_rgi_emoji_tag_sequence[18] = { + 0x67, 0x62, 0x65, 0x6e, 0x67, 0x00, 0x67, 0x62, + 0x73, 0x63, 0x74, 0x00, 0x67, 0x62, 0x77, 0x6c, + 0x73, 0x00, +}; + +static const uint8_t unicode_rgi_emoji_zwj_sequence[2320] = { + 0x02, 0xb8, 0x19, 0x40, 0x86, 0x02, 0xd1, 0x39, + 0xb0, 0x19, 0x02, 0x26, 0x39, 0x42, 0x86, 0x02, + 0xb4, 0x36, 0x42, 0x86, 0x03, 0x68, 0x54, 0x64, + 0x87, 0x68, 0x54, 0x02, 0xdc, 0x39, 0x42, 0x86, + 0x02, 0xd1, 0x39, 0x73, 0x13, 0x02, 0x39, 0x39, + 0x40, 0x86, 0x02, 0x69, 0x34, 0xbd, 0x19, 0x03, + 0xb6, 0x36, 0x40, 0x86, 0xa1, 0x87, 0x03, 0x68, + 0x74, 0x1d, 0x19, 0x68, 0x74, 0x03, 0x68, 0x34, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0xf1, 0x7a, 0xf2, + 0x7a, 0x02, 0xca, 0x33, 0x42, 0x86, 0x02, 0x69, + 0x34, 0xb0, 0x19, 0x04, 0x68, 0x14, 0x68, 0x14, + 0x67, 0x14, 0x66, 0x14, 0x02, 0xf9, 0x26, 0x42, + 0x86, 0x03, 0x69, 0x74, 0x1d, 0x19, 0x69, 0x74, + 0x03, 0xd1, 0x19, 0xbc, 0x19, 0xa1, 0x87, 0x02, + 0x3c, 0x19, 0x40, 0x86, 0x02, 0x68, 0x34, 0xeb, + 0x13, 0x02, 0xc3, 0x33, 0xa1, 0x87, 0x02, 0x70, + 0x34, 0x40, 0x86, 0x02, 0xd4, 0x39, 0x42, 0x86, + 0x02, 0xcf, 0x39, 0x42, 0x86, 0x02, 0x47, 0x36, + 0x40, 0x86, 0x02, 0x39, 0x39, 0x42, 0x86, 0x04, + 0xd1, 0x79, 0x64, 0x87, 0x8b, 0x14, 0xd1, 0x79, + 0x02, 0xd1, 0x39, 0x95, 0x86, 0x02, 0x68, 0x34, + 0x93, 0x13, 0x02, 0x69, 0x34, 0xed, 0x13, 0x02, + 0xda, 0x39, 0x40, 0x86, 0x03, 0x69, 0x34, 0xaf, + 0x19, 0xa1, 0x87, 0x02, 0xd1, 0x39, 0x93, 0x13, + 0x03, 0xce, 0x39, 0x42, 0x86, 0xa1, 0x87, 0x03, + 0xd1, 0x79, 0x64, 0x87, 0xd1, 0x79, 0x03, 0xc3, + 0x33, 0x42, 0x86, 0xa1, 0x87, 0x03, 0x69, 0x74, + 0x1d, 0x19, 0x68, 0x74, 0x02, 0x69, 0x34, 0x92, + 0x16, 0x02, 0xd1, 0x39, 0x96, 0x86, 0x04, 0x69, + 0x14, 0x64, 0x87, 0x8b, 0x14, 0x68, 0x14, 0x02, + 0x68, 0x34, 0x7c, 0x13, 0x02, 0x47, 0x36, 0x42, + 0x86, 0x02, 0x86, 0x34, 0x42, 0x86, 0x02, 0xd1, + 0x39, 0x7c, 0x13, 0x02, 0x69, 0x14, 0xa4, 0x13, + 0x02, 0xda, 0x39, 0x42, 0x86, 0x02, 0x37, 0x39, + 0x40, 0x86, 0x02, 0xd1, 0x39, 0x08, 0x87, 0x04, + 0x68, 0x54, 0x64, 0x87, 0x8b, 0x14, 0x68, 0x54, + 0x02, 0x4d, 0x36, 0x40, 0x86, 0x02, 0x68, 0x34, + 0x2c, 0x15, 0x02, 0x69, 0x34, 0xaf, 0x19, 0x02, + 0x6e, 0x34, 0x40, 0x86, 0x02, 0xcd, 0x39, 0x42, + 0x86, 0x02, 0xd1, 0x39, 0x2c, 0x15, 0x02, 0x6f, + 0x14, 0x40, 0x86, 0x03, 0xd1, 0x39, 0xbc, 0x19, + 0xa1, 0x87, 0x02, 0x68, 0x34, 0xa8, 0x13, 0x02, + 0x69, 0x34, 0x73, 0x13, 0x04, 0x69, 0x54, 0x64, + 0x87, 0x8b, 0x14, 0x68, 0x54, 0x02, 0x71, 0x34, + 0x42, 0x86, 0x02, 0xd1, 0x39, 0xa8, 0x13, 0x02, + 0x45, 0x36, 0x40, 0x86, 0x03, 0x69, 0x54, 0x64, + 0x87, 0x68, 0x54, 0x03, 0x69, 0x54, 0x64, 0x87, + 0x69, 0x54, 0x03, 0xce, 0x39, 0x40, 0x86, 0xa1, + 0x87, 0x02, 0xd8, 0x39, 0x40, 0x86, 0x03, 0xc3, + 0x33, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x4d, 0x36, + 0x42, 0x86, 0x02, 0xd1, 0x19, 0x92, 0x16, 0x02, + 0xd1, 0x39, 0xeb, 0x13, 0x02, 0x68, 0x34, 0xbc, + 0x14, 0x02, 0xd1, 0x39, 0xbc, 0x14, 0x02, 0x3d, + 0x39, 0x40, 0x86, 0x02, 0xb8, 0x39, 0x42, 0x86, + 0x02, 0xa3, 0x36, 0x40, 0x86, 0x02, 0x75, 0x35, + 0x40, 0x86, 0x02, 0xd8, 0x39, 0x42, 0x86, 0x02, + 0x69, 0x34, 0x93, 0x13, 0x02, 0x35, 0x39, 0x40, + 0x86, 0x02, 0x4b, 0x36, 0x40, 0x86, 0x02, 0x3d, + 0x39, 0x42, 0x86, 0x02, 0x38, 0x39, 0x42, 0x86, + 0x02, 0xa3, 0x36, 0x42, 0x86, 0x03, 0x69, 0x14, + 0x67, 0x14, 0x67, 0x14, 0x02, 0xb6, 0x36, 0x40, + 0x86, 0x02, 0x69, 0x34, 0x7c, 0x13, 0x02, 0x75, + 0x35, 0x42, 0x86, 0x02, 0xcc, 0x93, 0x40, 0x86, + 0x02, 0xcc, 0x33, 0x40, 0x86, 0x03, 0xd1, 0x39, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0x82, 0x34, 0x40, + 0x86, 0x02, 0x87, 0x34, 0x40, 0x86, 0x02, 0x69, + 0x14, 0x3e, 0x13, 0x02, 0xd6, 0x39, 0x40, 0x86, + 0x02, 0x68, 0x14, 0xbd, 0x19, 0x02, 0x46, 0x36, + 0x42, 0x86, 0x02, 0x4b, 0x36, 0x42, 0x86, 0x02, + 0x69, 0x34, 0x2c, 0x15, 0x03, 0xb6, 0x36, 0x42, + 0x86, 0xa1, 0x87, 0x02, 0xc4, 0x33, 0x40, 0x86, + 0x02, 0x26, 0x19, 0x40, 0x86, 0x02, 0x69, 0x14, + 0xb0, 0x19, 0x02, 0xde, 0x19, 0x42, 0x86, 0x02, + 0x69, 0x34, 0xa8, 0x13, 0x02, 0xcc, 0x33, 0x42, + 0x86, 0x02, 0x82, 0x34, 0x42, 0x86, 0x02, 0xd1, + 0x19, 0x93, 0x13, 0x02, 0x81, 0x14, 0x42, 0x86, + 0x02, 0x69, 0x34, 0x95, 0x86, 0x02, 0x68, 0x34, + 0xbb, 0x14, 0x02, 0xd1, 0x39, 0xbb, 0x14, 0x02, + 0x69, 0x34, 0xeb, 0x13, 0x02, 0xd1, 0x39, 0x84, + 0x13, 0x02, 0x69, 0x34, 0xbc, 0x14, 0x04, 0x69, + 0x54, 0x64, 0x87, 0x8b, 0x14, 0x69, 0x54, 0x02, + 0x26, 0x39, 0x40, 0x86, 0x02, 0xb4, 0x36, 0x40, + 0x86, 0x02, 0x47, 0x16, 0x42, 0x86, 0x02, 0xdc, + 0x39, 0x40, 0x86, 0x02, 0xca, 0x33, 0x40, 0x86, + 0x02, 0xf9, 0x26, 0x40, 0x86, 0x02, 0x69, 0x34, + 0x08, 0x87, 0x03, 0x69, 0x14, 0x69, 0x14, 0x66, + 0x14, 0x03, 0xd1, 0x59, 0x1d, 0x19, 0xd1, 0x59, + 0x02, 0xd4, 0x39, 0x40, 0x86, 0x02, 0xcf, 0x39, + 0x40, 0x86, 0x02, 0x68, 0x34, 0xa4, 0x13, 0x02, + 0xd1, 0x39, 0xa4, 0x13, 0x02, 0xd1, 0x19, 0xa8, + 0x13, 0x02, 0xd7, 0x39, 0x42, 0x86, 0x03, 0x69, + 0x34, 0xbc, 0x19, 0xa1, 0x87, 0x02, 0x68, 0x14, + 0xb0, 0x19, 0x02, 0x68, 0x14, 0x73, 0x13, 0x04, + 0x69, 0x14, 0x69, 0x14, 0x66, 0x14, 0x66, 0x14, + 0x03, 0x68, 0x34, 0xaf, 0x19, 0xa1, 0x87, 0x02, + 0x68, 0x34, 0x80, 0x16, 0x02, 0x73, 0x34, 0x42, + 0x86, 0x02, 0xd1, 0x39, 0x80, 0x16, 0x02, 0x68, + 0x34, 0xb0, 0x19, 0x02, 0x86, 0x34, 0x40, 0x86, + 0x02, 0x38, 0x19, 0x42, 0x86, 0x02, 0x69, 0x34, + 0xbb, 0x14, 0x02, 0xb5, 0x36, 0x42, 0x86, 0x02, + 0xcd, 0x39, 0x40, 0x86, 0x02, 0x68, 0x34, 0x95, + 0x86, 0x02, 0x68, 0x34, 0x27, 0x15, 0x03, 0x68, + 0x14, 0x68, 0x14, 0x66, 0x14, 0x02, 0x71, 0x34, + 0x40, 0x86, 0x02, 0xd1, 0x39, 0x27, 0x15, 0x02, + 0x2e, 0x16, 0xa8, 0x14, 0x02, 0xc3, 0x33, 0x42, + 0x86, 0x02, 0x69, 0x14, 0x66, 0x14, 0x02, 0x68, + 0x34, 0x96, 0x86, 0x02, 0x69, 0x34, 0xa4, 0x13, + 0x03, 0x69, 0x14, 0x64, 0x87, 0x68, 0x14, 0x02, + 0xb8, 0x39, 0x40, 0x86, 0x02, 0x68, 0x34, 0x3e, + 0x13, 0x03, 0xd1, 0x19, 0xaf, 0x19, 0xa1, 0x87, + 0x02, 0xd1, 0x39, 0x3e, 0x13, 0x02, 0x68, 0x34, + 0xbd, 0x19, 0x02, 0xd1, 0x19, 0xbb, 0x14, 0x02, + 0xd1, 0x19, 0x95, 0x86, 0x02, 0xdb, 0x39, 0x42, + 0x86, 0x02, 0x38, 0x39, 0x40, 0x86, 0x02, 0x69, + 0x34, 0x80, 0x16, 0x02, 0x69, 0x14, 0xeb, 0x13, + 0x04, 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, 0x67, + 0x14, 0x02, 0x77, 0x34, 0x42, 0x86, 0x02, 0x46, + 0x36, 0x40, 0x86, 0x02, 0x68, 0x34, 0x92, 0x16, + 0x02, 0x4e, 0x36, 0x42, 0x86, 0x03, 0x69, 0x14, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0xde, 0x19, 0x40, + 0x86, 0x02, 0x69, 0x34, 0x27, 0x15, 0x03, 0xc3, + 0x13, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x81, 0x14, + 0x40, 0x86, 0x03, 0xd1, 0x39, 0xaf, 0x19, 0xa1, + 0x87, 0x02, 0x68, 0x34, 0xbc, 0x19, 0x02, 0xd1, + 0x19, 0x80, 0x16, 0x02, 0xd9, 0x39, 0x42, 0x86, + 0x02, 0xd1, 0x39, 0xbc, 0x19, 0x02, 0xdc, 0x19, + 0x42, 0x86, 0x02, 0x68, 0x34, 0x73, 0x13, 0x02, + 0x69, 0x34, 0x3e, 0x13, 0x02, 0x47, 0x16, 0x40, + 0x86, 0x02, 0xd1, 0x39, 0xbd, 0x19, 0x02, 0x3e, + 0x39, 0x42, 0x86, 0x02, 0x69, 0x14, 0x95, 0x86, + 0x02, 0x68, 0x14, 0x96, 0x86, 0x03, 0x69, 0x34, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0xd7, 0x39, 0x40, + 0x86, 0x02, 0x45, 0x16, 0x42, 0x86, 0x02, 0x68, + 0x34, 0xed, 0x13, 0x03, 0x68, 0x34, 0xbc, 0x19, + 0xa1, 0x87, 0x02, 0xd1, 0x39, 0xed, 0x13, 0x02, + 0xd1, 0x39, 0x92, 0x16, 0x02, 0x73, 0x34, 0x40, + 0x86, 0x02, 0x38, 0x19, 0x40, 0x86, 0x02, 0xb5, + 0x36, 0x40, 0x86, 0x02, 0x68, 0x34, 0xaf, 0x19, + 0x02, 0xd1, 0x39, 0xaf, 0x19, 0x02, 0x69, 0x34, + 0xbc, 0x19, 0x02, 0xb6, 0x16, 0x42, 0x86, 0x02, + 0x26, 0x14, 0x25, 0x15, 0x02, 0xc3, 0x33, 0x40, + 0x86, 0x02, 0xdd, 0x39, 0x42, 0x86, 0x02, 0xcb, + 0x93, 0x42, 0x86, 0x02, 0xcb, 0x33, 0x42, 0x86, + 0x02, 0x81, 0x34, 0x42, 0x86, 0x02, 0xce, 0x39, + 0xa1, 0x87, 0x02, 0xdb, 0x39, 0x40, 0x86, 0x02, + 0x68, 0x34, 0x08, 0x87, 0x02, 0xd1, 0x19, 0xb0, + 0x19, 0x02, 0x77, 0x34, 0x40, 0x86, 0x02, 0x4e, + 0x36, 0x40, 0x86, 0x02, 0xce, 0x39, 0x42, 0x86, + 0x02, 0x4e, 0x16, 0x42, 0x86, 0x02, 0xd9, 0x39, + 0x40, 0x86, 0x02, 0xdc, 0x19, 0x40, 0x86, 0x02, + 0x3e, 0x39, 0x40, 0x86, 0x02, 0xb9, 0x39, 0x42, + 0x86, 0x02, 0xda, 0x19, 0x42, 0x86, 0x02, 0x42, + 0x16, 0x94, 0x81, 0x02, 0x45, 0x16, 0x40, 0x86, + 0x02, 0x69, 0x14, 0xbd, 0x19, 0x02, 0x70, 0x34, + 0x42, 0x86, 0x02, 0xce, 0x19, 0xa1, 0x87, 0x02, + 0xc3, 0x13, 0x42, 0x86, 0x02, 0x68, 0x14, 0x08, + 0x87, 0x02, 0xd1, 0x19, 0x7c, 0x13, 0x02, 0x68, + 0x14, 0x92, 0x16, 0x02, 0xb6, 0x16, 0x40, 0x86, + 0x02, 0x37, 0x39, 0x42, 0x86, 0x03, 0xce, 0x19, + 0x42, 0x86, 0xa1, 0x87, 0x03, 0x68, 0x14, 0x67, + 0x14, 0x67, 0x14, 0x02, 0xdd, 0x39, 0x40, 0x86, + 0x02, 0xcf, 0x19, 0x42, 0x86, 0x02, 0xd1, 0x19, + 0x2c, 0x15, 0x02, 0x4b, 0x13, 0xe9, 0x17, 0x02, + 0x68, 0x14, 0x67, 0x14, 0x02, 0xcb, 0x93, 0x40, + 0x86, 0x02, 0x6e, 0x34, 0x42, 0x86, 0x02, 0xcb, + 0x33, 0x40, 0x86, 0x02, 0x81, 0x34, 0x40, 0x86, + 0x02, 0xb6, 0x36, 0xa1, 0x87, 0x02, 0x45, 0x36, + 0x42, 0x86, 0x02, 0xb4, 0x16, 0x42, 0x86, 0x02, + 0x69, 0x14, 0x73, 0x13, 0x04, 0x69, 0x14, 0x69, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x02, 0x35, 0x39, + 0x42, 0x86, 0x02, 0x68, 0x14, 0x93, 0x13, 0x02, + 0xb6, 0x36, 0x42, 0x86, 0x03, 0x68, 0x14, 0x69, + 0x14, 0x66, 0x14, 0x02, 0xce, 0x39, 0x40, 0x86, + 0x02, 0x4e, 0x16, 0x40, 0x86, 0x02, 0x87, 0x34, + 0x42, 0x86, 0x02, 0x86, 0x14, 0x42, 0x86, 0x02, + 0xd6, 0x39, 0x42, 0x86, 0x02, 0xc4, 0x33, 0x42, + 0x86, 0x02, 0x69, 0x34, 0x96, 0x86, 0x02, 0xb9, + 0x39, 0x40, 0x86, 0x02, 0x68, 0x14, 0xa8, 0x13, + 0x02, 0xd1, 0x19, 0x84, 0x13, 0x02, 0xda, 0x19, + 0x40, 0x86, 0x02, 0xd8, 0x19, 0x42, 0x86, 0x02, + 0xc3, 0x13, 0x40, 0x86, 0x02, 0xb9, 0x19, 0x42, + 0x86, 0x02, 0x3d, 0x19, 0x42, 0x86, 0x02, 0xcf, + 0x19, 0x40, 0x86, 0x04, 0x68, 0x14, 0x68, 0x14, + 0x67, 0x14, 0x67, 0x14, 0x03, 0xd1, 0x19, 0xd1, + 0x19, 0xd2, 0x19, 0x02, 0x68, 0x14, 0xbb, 0x14, + 0x02, 0x3b, 0x14, 0x44, 0x87, 0x02, 0xd1, 0x19, + 0x27, 0x15, 0x02, 0xb4, 0x16, 0x40, 0x86, 0x02, + 0xcd, 0x19, 0x42, 0x86, 0x02, 0xd3, 0x86, 0xa5, + 0x14, 0x02, 0x70, 0x14, 0x42, 0x86, 0x03, 0xb6, + 0x16, 0x42, 0x86, 0xa1, 0x87, 0x04, 0x69, 0x14, + 0x64, 0x87, 0x8b, 0x14, 0x69, 0x14, 0x02, 0x36, + 0x16, 0x2b, 0x93, 0x02, 0x68, 0x14, 0x80, 0x16, + 0x02, 0x86, 0x14, 0x40, 0x86, 0x02, 0x08, 0x14, + 0x1b, 0x0b, 0x02, 0xd1, 0x19, 0xbc, 0x19, 0x02, + 0xca, 0x13, 0x42, 0x86, 0x02, 0x41, 0x94, 0xe8, + 0x95, 0x02, 0xd8, 0x19, 0x40, 0x86, 0x02, 0xb9, + 0x19, 0x40, 0x86, 0x02, 0xd1, 0x19, 0xed, 0x13, + 0x02, 0xf9, 0x86, 0x42, 0x86, 0x03, 0xd1, 0x19, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0x3d, 0x19, 0x40, + 0x86, 0x02, 0xd6, 0x19, 0x42, 0x86, 0x03, 0x69, + 0x14, 0x66, 0x14, 0x66, 0x14, 0x02, 0xd1, 0x19, + 0xaf, 0x19, 0x03, 0x69, 0x14, 0x69, 0x14, 0x67, + 0x14, 0x02, 0xcd, 0x19, 0x40, 0x86, 0x02, 0x70, + 0x14, 0x40, 0x86, 0x03, 0x68, 0x14, 0xbc, 0x19, + 0xa1, 0x87, 0x02, 0x6e, 0x14, 0x42, 0x86, 0x02, + 0x69, 0x14, 0x92, 0x16, 0x03, 0x68, 0x14, 0x68, + 0x14, 0x67, 0x14, 0x02, 0x69, 0x14, 0x67, 0x14, + 0x02, 0x75, 0x95, 0x42, 0x86, 0x03, 0x69, 0x14, + 0x64, 0x87, 0x69, 0x14, 0x02, 0xd1, 0x19, 0xbc, + 0x14, 0x02, 0xdf, 0x19, 0x42, 0x86, 0x02, 0xca, + 0x13, 0x40, 0x86, 0x02, 0x82, 0x14, 0x42, 0x86, + 0x02, 0x69, 0x14, 0x93, 0x13, 0x02, 0x68, 0x14, + 0x7c, 0x13, 0x02, 0xf9, 0x86, 0x40, 0x86, 0x02, + 0xd6, 0x19, 0x40, 0x86, 0x02, 0x68, 0x14, 0x2c, + 0x15, 0x02, 0x69, 0x14, 0xa8, 0x13, 0x02, 0xd4, + 0x19, 0x42, 0x86, 0x04, 0x68, 0x14, 0x69, 0x14, + 0x66, 0x14, 0x66, 0x14, 0x02, 0x77, 0x14, 0x42, + 0x86, 0x02, 0x39, 0x19, 0x42, 0x86, 0x02, 0xd1, + 0x19, 0xa4, 0x13, 0x02, 0x6e, 0x14, 0x40, 0x86, + 0x03, 0xd1, 0x19, 0xd2, 0x19, 0xd2, 0x19, 0x02, + 0x69, 0x14, 0xbb, 0x14, 0x02, 0xd1, 0x19, 0x96, + 0x86, 0x02, 0x75, 0x95, 0x40, 0x86, 0x04, 0x68, + 0x14, 0x64, 0x87, 0x8b, 0x14, 0x68, 0x14, 0x02, + 0xd1, 0x19, 0x3e, 0x13, 0x02, 0xdf, 0x19, 0x40, + 0x86, 0x02, 0x82, 0x14, 0x40, 0x86, 0x02, 0x44, + 0x13, 0xeb, 0x17, 0x02, 0xdd, 0x19, 0x42, 0x86, + 0x02, 0x69, 0x14, 0x80, 0x16, 0x03, 0x68, 0x14, + 0xaf, 0x19, 0xa1, 0x87, 0x02, 0xa3, 0x16, 0x42, + 0x86, 0x02, 0x69, 0x14, 0x96, 0x86, 0x02, 0x46, + 0x16, 0x42, 0x86, 0x02, 0xb6, 0x16, 0xa1, 0x87, + 0x02, 0x68, 0x14, 0x27, 0x15, 0x02, 0x26, 0x14, + 0x1b, 0x0b, 0x02, 0xd4, 0x19, 0x40, 0x86, 0x02, + 0x77, 0x14, 0x40, 0x86, 0x02, 0x39, 0x19, 0x40, + 0x86, 0x02, 0x37, 0x19, 0x42, 0x86, 0x03, 0x69, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x03, 0xc3, 0x13, + 0x42, 0x86, 0xa1, 0x87, 0x02, 0x68, 0x14, 0xbc, + 0x19, 0x02, 0xd1, 0x19, 0xeb, 0x13, 0x04, 0x69, + 0x14, 0x69, 0x14, 0x67, 0x14, 0x67, 0x14, 0x02, + 0xd1, 0x19, 0x08, 0x87, 0x02, 0x68, 0x14, 0xed, + 0x13, 0x03, 0x69, 0x14, 0xbc, 0x19, 0xa1, 0x87, + 0x02, 0xdd, 0x19, 0x40, 0x86, 0x02, 0xc3, 0x13, + 0xa1, 0x87, 0x03, 0x68, 0x14, 0x66, 0x14, 0x66, + 0x14, 0x03, 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, + 0x02, 0xa3, 0x16, 0x40, 0x86, 0x02, 0xdb, 0x19, + 0x42, 0x86, 0x02, 0x68, 0x14, 0xaf, 0x19, 0x02, + 0x46, 0x16, 0x40, 0x86, 0x02, 0x35, 0x16, 0xab, + 0x14, 0x02, 0x68, 0x14, 0x95, 0x86, 0x02, 0x42, + 0x16, 0x95, 0x81, 0x02, 0xc4, 0x13, 0x42, 0x86, + 0x02, 0x15, 0x14, 0xba, 0x19, 0x02, 0x69, 0x14, + 0x08, 0x87, 0x03, 0xd1, 0x19, 0x1d, 0x19, 0xd1, + 0x19, 0x02, 0x69, 0x14, 0x7c, 0x13, 0x02, 0x37, + 0x19, 0x40, 0x86, 0x02, 0x73, 0x14, 0x42, 0x86, + 0x02, 0x69, 0x14, 0x2c, 0x15, 0x02, 0xb5, 0x16, + 0x42, 0x86, 0x02, 0x35, 0x19, 0x42, 0x86, 0x04, + 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, 0x66, 0x14, + 0x02, 0x64, 0x87, 0x25, 0x15, 0x02, 0x64, 0x87, + 0x79, 0x1a, 0x02, 0x68, 0x14, 0xbc, 0x14, 0x03, + 0xce, 0x19, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x87, + 0x14, 0x42, 0x86, 0x02, 0x4d, 0x16, 0x42, 0x86, + 0x04, 0x68, 0x14, 0x68, 0x14, 0x66, 0x14, 0x66, + 0x14, 0x02, 0xdb, 0x19, 0x40, 0x86, 0x02, 0xd9, + 0x19, 0x42, 0x86, 0x02, 0xc4, 0x13, 0x40, 0x86, + 0x02, 0xd1, 0x19, 0xbd, 0x19, 0x02, 0x68, 0x14, + 0xa4, 0x13, 0x02, 0x3e, 0x19, 0x42, 0x86, 0x02, + 0xf3, 0x93, 0xa7, 0x86, 0x03, 0x69, 0x14, 0xaf, + 0x19, 0xa1, 0x87, 0x02, 0xf3, 0x93, 0x08, 0x13, + 0x02, 0xd1, 0x19, 0xd2, 0x19, 0x02, 0x73, 0x14, + 0x40, 0x86, 0x02, 0xb5, 0x16, 0x40, 0x86, 0x02, + 0x35, 0x19, 0x40, 0x86, 0x02, 0x69, 0x14, 0x27, + 0x15, 0x02, 0xce, 0x19, 0x42, 0x86, 0x02, 0x71, + 0x14, 0x42, 0x86, 0x02, 0xd1, 0x19, 0x73, 0x13, + 0x02, 0x68, 0x14, 0x3e, 0x13, 0x02, 0xf4, 0x13, + 0x20, 0x86, 0x02, 0x87, 0x14, 0x40, 0x86, 0x03, + 0xb6, 0x16, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x4d, + 0x16, 0x40, 0x86, 0x02, 0x69, 0x14, 0xbc, 0x19, + 0x02, 0x4b, 0x16, 0x42, 0x86, 0x02, 0xd9, 0x19, + 0x40, 0x86, 0x02, 0x3e, 0x19, 0x40, 0x86, 0x02, + 0x69, 0x14, 0xed, 0x13, 0x02, 0xd7, 0x19, 0x42, + 0x86, 0x02, 0xb8, 0x19, 0x42, 0x86, 0x03, 0x68, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x02, 0x3c, 0x19, + 0x42, 0x86, 0x02, 0x68, 0x14, 0x66, 0x14, 0x03, + 0x68, 0x14, 0x64, 0x87, 0x68, 0x14, 0x02, 0x69, + 0x14, 0xaf, 0x19, 0x02, 0xce, 0x19, 0x40, 0x86, + 0x02, 0x71, 0x14, 0x40, 0x86, 0x02, 0x68, 0x14, + 0xeb, 0x13, 0x03, 0x68, 0x14, 0xbd, 0x19, 0xa1, + 0x87, 0x02, 0x6f, 0x14, 0x42, 0x86, 0x04, 0xd1, + 0x19, 0xd1, 0x19, 0xd2, 0x19, 0xd2, 0x19, 0x02, + 0x69, 0x14, 0xbc, 0x14, 0x02, 0xcc, 0x93, 0x42, + 0x86, 0x02, 0x4b, 0x16, 0x40, 0x86, 0x02, 0x26, + 0x19, 0x42, 0x86, 0x02, 0xd7, 0x19, 0x40, 0x86, +}; + +#endif /* CONFIG_ALL_UNICODE */ +/* 71 tables / 36311 bytes, 5 index / 351 bytes */ diff --git a/quickjs-ng/libunicode.c b/quickjs/libunicode.c similarity index 78% rename from quickjs-ng/libunicode.c rename to quickjs/libunicode.c index a621c52..0c510cc 100644 --- a/quickjs-ng/libunicode.c +++ b/quickjs/libunicode.c @@ -31,7 +31,6 @@ #include "libunicode.h" #include "libunicode-table.h" -// note: stored as 4 bit tag, not much room left enum { RUN_TYPE_U, RUN_TYPE_L, @@ -190,7 +189,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) return 1; } -static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, bool is_unicode) +static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_unicode) { uint32_t res[LRE_CC_RES_LEN_MAX]; int len; @@ -216,7 +215,7 @@ static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, bool is_ c = c - 'a' + 'A'; } else { /* legacy regexp: to upper case if single char >= 128 */ - len = lre_case_conv_entry(res, c, false, idx, v); + len = lre_case_conv_entry(res, c, FALSE, idx, v); if (len == 1 && res[0] >= 128) c = res[0]; } @@ -225,7 +224,7 @@ static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, bool is_ } /* JS regexp specific rules for case folding */ -int lre_canonicalize(uint32_t c, bool is_unicode) +int lre_canonicalize(uint32_t c, BOOL is_unicode) { if (c < 128) { /* fast case */ @@ -302,7 +301,7 @@ static int get_index_pos(uint32_t *pcode, uint32_t c, return (idx_min + 1) * UNICODE_INDEX_BLOCK_LEN + (v >> 21); } -static bool lre_is_in_table(uint32_t c, const uint8_t *table, +static BOOL lre_is_in_table(uint32_t c, const uint8_t *table, const uint8_t *index_table, int index_table_len) { uint32_t code, b, bit; @@ -311,9 +310,17 @@ static bool lre_is_in_table(uint32_t c, const uint8_t *table, pos = get_index_pos(&code, c, index_table, index_table_len); if (pos < 0) - return false; /* outside the table */ + return FALSE; /* outside the table */ p = table + pos; bit = 0; + /* Compressed run length encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ for(;;) { b = *p++; if (b < 64) { @@ -337,7 +344,7 @@ static bool lre_is_in_table(uint32_t c, const uint8_t *table, } } -bool lre_is_cased(uint32_t c) +BOOL lre_is_cased(uint32_t c) { uint32_t v, code, len; int idx, idx_min, idx_max; @@ -354,7 +361,7 @@ bool lre_is_cased(uint32_t c) } else if (c >= code + len) { idx_min = idx + 1; } else { - return true; + return TRUE; } } return lre_is_in_table(c, unicode_prop_Cased1_table, @@ -362,7 +369,7 @@ bool lre_is_cased(uint32_t c) sizeof(unicode_prop_Cased1_index) / 3); } -bool lre_is_case_ignorable(uint32_t c) +BOOL lre_is_case_ignorable(uint32_t c) { return lre_is_in_table(c, unicode_prop_Case_Ignorable_table, unicode_prop_Case_Ignorable_index, @@ -492,6 +499,9 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, case CR_OP_XOR: is_in = (a_idx & 1) ^ (b_idx & 1); break; + case CR_OP_SUB: + is_in = (a_idx & 1) & ((b_idx & 1) ^ 1); + break; default: abort(); } @@ -504,14 +514,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, return 0; } -int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len) +int cr_op1(CharRange *cr, const uint32_t *b_pt, int b_len, int op) { CharRange a = *cr; int ret; cr->len = 0; cr->size = 0; cr->points = NULL; - ret = cr_op(cr, a.points, a.len, b_pt, b_len, CR_OP_UNION); + ret = cr_op(cr, a.points, a.len, b_pt, b_len, op); cr_free(&a); return ret; } @@ -530,14 +540,217 @@ int cr_invert(CharRange *cr) return 0; } -bool lre_is_id_start(uint32_t c) +#define CASE_U (1 << 0) +#define CASE_L (1 << 1) +#define CASE_F (1 << 2) + +/* use the case conversion table to generate range of characters. + CASE_U: set char if modified by uppercasing, + CASE_L: set char if modified by lowercasing, + CASE_F: set char if modified by case folding, + */ +static int unicode_case1(CharRange *cr, int case_mask) +{ +#define MR(x) (1 << RUN_TYPE_ ## x) + const uint32_t tab_run_mask[3] = { + MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) | + MR(UF_D1_EXT) | MR(U_EXT) | MR(UF_EXT2) | MR(UF_EXT3), + + MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2), + + MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT) | MR(UF_EXT2) | MR(UF_EXT3), + }; +#undef MR + uint32_t mask, v, code, type, len, i, idx; + + if (case_mask == 0) + return 0; + mask = 0; + for(i = 0; i < 3; i++) { + if ((case_mask >> i) & 1) + mask |= tab_run_mask[i]; + } + for(idx = 0; idx < countof(case_conv_table1); idx++) { + v = case_conv_table1[idx]; + type = (v >> (32 - 17 - 7 - 4)) & 0xf; + code = v >> (32 - 17); + len = (v >> (32 - 17 - 7)) & 0x7f; + if ((mask >> type) & 1) { + // printf("%d: type=%d %04x %04x\n", idx, type, code, code + len - 1); + switch(type) { + case RUN_TYPE_UL: + if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) + goto def_case; + code += ((case_mask & CASE_U) != 0); + for(i = 0; i < len; i += 2) { + if (cr_add_interval(cr, code + i, code + i + 1)) + return -1; + } + break; + case RUN_TYPE_LSU: + if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) + goto def_case; + if (!(case_mask & CASE_U)) { + if (cr_add_interval(cr, code, code + 1)) + return -1; + } + if (cr_add_interval(cr, code + 1, code + 2)) + return -1; + if (case_mask & CASE_U) { + if (cr_add_interval(cr, code + 2, code + 3)) + return -1; + } + break; + default: + def_case: + if (cr_add_interval(cr, code, code + len)) + return -1; + break; + } + } + } + return 0; +} + +static int point_cmp(const void *p1, const void *p2, void *arg) +{ + uint32_t v1 = *(uint32_t *)p1; + uint32_t v2 = *(uint32_t *)p2; + return (v1 > v2) - (v1 < v2); +} + +static void cr_sort_and_remove_overlap(CharRange *cr) +{ + uint32_t start, end, start1, end1, i, j; + + /* the resulting ranges are not necessarily sorted and may overlap */ + rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL); + j = 0; + for(i = 0; i < cr->len; ) { + start = cr->points[i]; + end = cr->points[i + 1]; + i += 2; + while (i < cr->len) { + start1 = cr->points[i]; + end1 = cr->points[i + 1]; + if (start1 > end) { + /* |------| + * |-------| */ + break; + } else if (end1 <= end) { + /* |------| + * |--| */ + i += 2; + } else { + /* |------| + * |-------| */ + end = end1; + i += 2; + } + } + cr->points[j] = start; + cr->points[j + 1] = end; + j += 2; + } + cr->len = j; +} + +/* canonicalize a character set using the JS regex case folding rules + (see lre_canonicalize()) */ +int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode) +{ + CharRange cr_inter, cr_mask, cr_result, cr_sub; + uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d; + + cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func); + cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func); + cr_init(&cr_result, cr->mem_opaque, cr->realloc_func); + cr_init(&cr_sub, cr->mem_opaque, cr->realloc_func); + + if (unicode_case1(&cr_mask, is_unicode ? CASE_F : CASE_U)) + goto fail; + if (cr_op(&cr_inter, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER)) + goto fail; + + if (cr_invert(&cr_mask)) + goto fail; + if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER)) + goto fail; + + /* cr_inter = cr & cr_mask */ + /* cr_sub = cr & ~cr_mask */ + + /* use the case conversion table to compute the result */ + d_start = -1; + d_end = -1; + idx = 0; + v = case_conv_table1[idx]; + code = v >> (32 - 17); + len = (v >> (32 - 17 - 7)) & 0x7f; + for(i = 0; i < cr_inter.len; i += 2) { + start = cr_inter.points[i]; + end = cr_inter.points[i + 1]; + + for(c = start; c < end; c++) { + for(;;) { + if (c >= code && c < code + len) + break; + idx++; + assert(idx < countof(case_conv_table1)); + v = case_conv_table1[idx]; + code = v >> (32 - 17); + len = (v >> (32 - 17 - 7)) & 0x7f; + } + d = lre_case_folding_entry(c, idx, v, is_unicode); + /* try to merge with the current interval */ + if (d_start == -1) { + d_start = d; + d_end = d + 1; + } else if (d_end == d) { + d_end++; + } else { + cr_add_interval(&cr_result, d_start, d_end); + d_start = d; + d_end = d + 1; + } + } + } + if (d_start != -1) { + if (cr_add_interval(&cr_result, d_start, d_end)) + goto fail; + } + + /* the resulting ranges are not necessarily sorted and may overlap */ + cr_sort_and_remove_overlap(&cr_result); + + /* or with the character not affected by the case folding */ + cr->len = 0; + if (cr_op(cr, cr_result.points, cr_result.len, cr_sub.points, cr_sub.len, CR_OP_UNION)) + goto fail; + + cr_free(&cr_inter); + cr_free(&cr_mask); + cr_free(&cr_result); + cr_free(&cr_sub); + return 0; + fail: + cr_free(&cr_inter); + cr_free(&cr_mask); + cr_free(&cr_result); + cr_free(&cr_sub); + return -1; +} + +#ifdef CONFIG_ALL_UNICODE + +BOOL lre_is_id_start(uint32_t c) { return lre_is_in_table(c, unicode_prop_ID_Start_table, unicode_prop_ID_Start_index, sizeof(unicode_prop_ID_Start_index) / 3); } -bool lre_is_id_continue(uint32_t c) +BOOL lre_is_id_continue(uint32_t c) { return lre_is_id_start(c) || lre_is_in_table(c, unicode_prop_ID_Continue1_table, @@ -545,13 +758,6 @@ bool lre_is_id_continue(uint32_t c) sizeof(unicode_prop_ID_Continue1_index) / 3); } -bool lre_is_white_space(uint32_t c) -{ - return lre_is_in_table(c, unicode_prop_White_Space_table, - unicode_prop_White_Space_index, - sizeof(unicode_prop_White_Space_index) / 3); -} - #define UNICODE_DECOMP_LEN_MAX 18 typedef enum { @@ -759,7 +965,7 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, /* return the length of the decomposition (length <= UNICODE_DECOMP_LEN_MAX) or 0 if no decomposition */ -static int unicode_decomp_char(uint32_t *res, uint32_t c, bool is_compat1) +static int unicode_decomp_char(uint32_t *res, uint32_t c, BOOL is_compat1) { uint32_t v, type, is_compat, code, len; int idx_min, idx_max, idx; @@ -835,6 +1041,13 @@ static int unicode_get_cc(uint32_t c) if (pos < 0) return 0; p = unicode_cc_table + pos; + /* Compressed run length encoding: + - 2 high order bits are combining class type + - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte + - 00..2F: range length (add 1) + - 30..37: 3-bit range-length + 1 extra byte + - 38..3F: 3-bit range-length + 2 extra byte + */ for(;;) { b = *p++; type = b >> 6; @@ -899,6 +1112,13 @@ static void sort_cc(int *buf, int len) buf[k + 1] = ch1; j++; } +#if 0 + printf("cc:"); + for(k = start; k < j; k++) { + printf(" %3d", unicode_get_cc(buf[k])); + } + printf("\n"); +#endif i = j; } } @@ -953,13 +1173,13 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, void *opaque, DynBufReallocFunc *realloc_func) { int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len; - bool is_compat; + BOOL is_compat; DynBuf dbuf_s, *dbuf = &dbuf_s; is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); - if (dbuf_realloc(dbuf, sizeof(int) * src_len)) + if (dbuf_claim(dbuf, sizeof(int) * src_len)) goto fail; /* common case: latin1 is unaffected by NFC */ @@ -1053,20 +1273,18 @@ static int unicode_find_name(const char *name_table, const char *name) /* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2 if not found */ int unicode_script(CharRange *cr, - const char *script_name, bool is_ext) + const char *script_name, BOOL is_ext) { int script_idx; const uint8_t *p, *p_end; uint32_t c, c1, b, n, v, v_len, i, type; - CharRange cr1_s = { 0 }, *cr1 = NULL; - CharRange cr2_s = { 0 }, *cr2 = &cr2_s; - bool is_common; + CharRange cr1_s, *cr1; + CharRange cr2_s, *cr2 = &cr2_s; + BOOL is_common; script_idx = unicode_find_name(unicode_script_name_table, script_name); if (script_idx < 0) return -2; - /* Note: we remove the "Unknown" Script */ - script_idx += UNICODE_SCRIPT_Unknown + 1; is_common = (script_idx == UNICODE_SCRIPT_Common || script_idx == UNICODE_SCRIPT_Inherited); @@ -1096,17 +1314,21 @@ int unicode_script(CharRange *cr, n |= *p++; n += 96 + (1 << 12); } - if (type == 0) - v = 0; - else - v = *p++; c1 = c + n + 1; - if (v == script_idx) { - if (cr_add_interval(cr1, c, c1)) - goto fail; + if (type != 0) { + v = *p++; + if (v == script_idx || script_idx == UNICODE_SCRIPT_Unknown) { + if (cr_add_interval(cr1, c, c1)) + goto fail; + } } c = c1; } + if (script_idx == UNICODE_SCRIPT_Unknown) { + /* Unknown is all the characters outside scripts */ + if (cr_invert(cr1)) + goto fail; + } if (is_ext) { /* add the script extensions */ @@ -1180,6 +1402,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask) p = unicode_gc_table; p_end = unicode_gc_table + countof(unicode_gc_table); c = 0; + /* Compressed range encoding: + initial byte: + bits 0..4: category number (special case 31) + bits 5..7: range length (add 1) + special case bits 5..7 == 7: read an extra byte + - 00..7F: range length (add 7 + 1) + - 80..BF: 6-bits plus extra byte for range length (add 7 + 128) + - C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384) + */ while (p < p_end) { b = *p++; n = b >> 5; @@ -1233,6 +1464,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx) p_end = p + unicode_prop_len_table[prop_idx]; c = 0; bit = 0; + /* Compressed range encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ while (p < p_end) { c0 = c; b = *p++; @@ -1263,207 +1502,6 @@ static int unicode_prop1(CharRange *cr, int prop_idx) return 0; } -#define CASE_U (1 << 0) -#define CASE_L (1 << 1) -#define CASE_F (1 << 2) - -/* use the case conversion table to generate range of characters. - CASE_U: set char if modified by uppercasing, - CASE_L: set char if modified by lowercasing, - CASE_F: set char if modified by case folding, - */ -static int unicode_case1(CharRange *cr, int case_mask) -{ -#define MR(x) (1 << RUN_TYPE_ ## x) - const uint32_t tab_run_mask[3] = { - MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) | - MR(UF_D1_EXT) | MR(U_EXT) | MR(UF_EXT2) | MR(UF_EXT3), - - MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2), - - MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT) | MR(UF_EXT2) | MR(UF_EXT3), - }; -#undef MR - uint32_t mask, v, code, type, len, i, idx; - - if (case_mask == 0) - return 0; - mask = 0; - for(i = 0; i < 3; i++) { - if ((case_mask >> i) & 1) - mask |= tab_run_mask[i]; - } - for(idx = 0; idx < countof(case_conv_table1); idx++) { - v = case_conv_table1[idx]; - type = (v >> (32 - 17 - 7 - 4)) & 0xf; - code = v >> (32 - 17); - len = (v >> (32 - 17 - 7)) & 0x7f; - if ((mask >> type) & 1) { - // printf("%d: type=%d %04x %04x\n", idx, type, code, code + len - 1); - switch(type) { - case RUN_TYPE_UL: - if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) - goto def_case; - code += ((case_mask & CASE_U) != 0); - for(i = 0; i < len; i += 2) { - if (cr_add_interval(cr, code + i, code + i + 1)) - return -1; - } - break; - case RUN_TYPE_LSU: - if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) - goto def_case; - if (!(case_mask & CASE_U)) { - if (cr_add_interval(cr, code, code + 1)) - return -1; - } - if (cr_add_interval(cr, code + 1, code + 2)) - return -1; - if (case_mask & CASE_U) { - if (cr_add_interval(cr, code + 2, code + 3)) - return -1; - } - break; - default: - def_case: - if (cr_add_interval(cr, code, code + len)) - return -1; - break; - } - } - } - return 0; -} - -static int point_cmp(const void *p1, const void *p2, void *arg) -{ - uint32_t v1 = *(uint32_t *)p1; - uint32_t v2 = *(uint32_t *)p2; - return (v1 > v2) - (v1 < v2); -} - -static void cr_sort_and_remove_overlap(CharRange *cr) -{ - uint32_t start, end, start1, end1, i, j; - - /* the resulting ranges are not necessarily sorted and may overlap */ - rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL); - j = 0; - for(i = 0; i < cr->len; ) { - start = cr->points[i]; - end = cr->points[i + 1]; - i += 2; - while (i < cr->len) { - start1 = cr->points[i]; - end1 = cr->points[i + 1]; - if (start1 > end) { - /* |------| - * |-------| */ - break; - } else if (end1 <= end) { - /* |------| - * |--| */ - i += 2; - } else { - /* |------| - * |-------| */ - end = end1; - i += 2; - } - } - cr->points[j] = start; - cr->points[j + 1] = end; - j += 2; - } - cr->len = j; -} - -/* canonicalize a character set using the JS regex case folding rules - (see lre_canonicalize()) */ -int cr_regexp_canonicalize(CharRange *cr, bool is_unicode) -{ - CharRange cr_inter, cr_mask, cr_result, cr_sub; - uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d; - - cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func); - cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func); - cr_init(&cr_result, cr->mem_opaque, cr->realloc_func); - cr_init(&cr_sub, cr->mem_opaque, cr->realloc_func); - - if (unicode_case1(&cr_mask, is_unicode ? CASE_F : CASE_U)) - goto fail; - if (cr_op(&cr_inter, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER)) - goto fail; - - if (cr_invert(&cr_mask)) - goto fail; - if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER)) - goto fail; - - /* cr_inter = cr & cr_mask */ - /* cr_sub = cr & ~cr_mask */ - - /* use the case conversion table to compute the result */ - d_start = -1; - d_end = -1; - idx = 0; - v = case_conv_table1[idx]; - code = v >> (32 - 17); - len = (v >> (32 - 17 - 7)) & 0x7f; - for(i = 0; i < cr_inter.len; i += 2) { - start = cr_inter.points[i]; - end = cr_inter.points[i + 1]; - - for(c = start; c < end; c++) { - for(;;) { - if (c >= code && c < code + len) - break; - idx++; - assert(idx < countof(case_conv_table1)); - v = case_conv_table1[idx]; - code = v >> (32 - 17); - len = (v >> (32 - 17 - 7)) & 0x7f; - } - d = lre_case_folding_entry(c, idx, v, is_unicode); - /* try to merge with the current interval */ - if (d_start == -1) { - d_start = d; - d_end = d + 1; - } else if (d_end == d) { - d_end++; - } else { - cr_add_interval(&cr_result, d_start, d_end); - d_start = d; - d_end = d + 1; - } - } - } - if (d_start != -1) { - if (cr_add_interval(&cr_result, d_start, d_end)) - goto fail; - } - - /* the resulting ranges are not necessarily sorted and may overlap */ - cr_sort_and_remove_overlap(&cr_result); - - /* or with the character not affected by the case folding */ - cr->len = 0; - if (cr_op(cr, cr_result.points, cr_result.len, cr_sub.points, cr_sub.len, CR_OP_UNION)) - goto fail; - - cr_free(&cr_inter); - cr_free(&cr_mask); - cr_free(&cr_result); - cr_free(&cr_sub); - return 0; - fail: - cr_free(&cr_inter); - cr_free(&cr_mask); - cr_free(&cr_result); - cr_free(&cr_sub); - return -1; -} - typedef enum { POP_GC, POP_PROP, @@ -1521,6 +1559,7 @@ static int unicode_prop_ops(CharRange *cr, ...) cr2 = &stack[stack_len - 1]; cr3 = &stack[stack_len++]; cr_init(cr3, cr->mem_opaque, cr->realloc_func); + /* CR_OP_XOR may be used here */ if (cr_op(cr3, cr1->points, cr1->len, cr2->points, cr2->len, op - POP_UNION + CR_OP_UNION)) goto fail; @@ -1542,13 +1581,11 @@ static int unicode_prop_ops(CharRange *cr, ...) } } done: - va_end(ap); assert(stack_len == 1); ret = cr_copy(cr, &stack[0]); cr_free(&stack[0]); return ret; fail: - va_end(ap); for(i = 0; i < stack_len; i++) cr_free(&stack[i]); return -1; @@ -1728,6 +1765,42 @@ int unicode_prop(CharRange *cr, const char *prop_name) POP_XOR, POP_END); break; +#if 0 + case UNICODE_PROP_ID_Start: + ret = unicode_prop_ops(cr, + POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl), + POP_PROP, UNICODE_PROP_Other_ID_Start, + POP_UNION, + POP_PROP, UNICODE_PROP_Pattern_Syntax, + POP_PROP, UNICODE_PROP_Pattern_White_Space, + POP_UNION, + POP_INVERT, + POP_INTER, + POP_END); + break; + case UNICODE_PROP_ID_Continue: + ret = unicode_prop_ops(cr, + POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl) | + M(Mn) | M(Mc) | M(Nd) | M(Pc), + POP_PROP, UNICODE_PROP_Other_ID_Start, + POP_UNION, + POP_PROP, UNICODE_PROP_Other_ID_Continue, + POP_UNION, + POP_PROP, UNICODE_PROP_Pattern_Syntax, + POP_PROP, UNICODE_PROP_Pattern_White_Space, + POP_UNION, + POP_INVERT, + POP_INTER, + POP_END); + break; + case UNICODE_PROP_Case_Ignorable: + ret = unicode_prop_ops(cr, + POP_GC, M(Mn) | M(Cf) | M(Lm) | M(Sk), + POP_PROP, UNICODE_PROP_Case_Ignorable1, + POP_XOR, + POP_END); + break; +#else /* we use the existing tables */ case UNICODE_PROP_ID_Continue: ret = unicode_prop_ops(cr, @@ -1736,6 +1809,7 @@ int unicode_prop(CharRange *cr, const char *prop_name) POP_XOR, POP_END); break; +#endif default: if (prop_idx >= countof(unicode_prop_table)) return -2; @@ -1744,3 +1818,306 @@ int unicode_prop(CharRange *cr, const char *prop_name) } return ret; } + +#endif /* CONFIG_ALL_UNICODE */ + +/*---- lre codepoint categorizing functions ----*/ + +#define S UNICODE_C_SPACE +#define D UNICODE_C_DIGIT +#define X UNICODE_C_XDIGIT +#define U UNICODE_C_UPPER +#define L UNICODE_C_LOWER +#define _ UNICODE_C_UNDER +#define d UNICODE_C_DOLLAR + +uint8_t const lre_ctype_bits[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, S, S, S, S, S, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, d, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D, + X|D, X|D, 0, 0, 0, 0, 0, 0, + + 0, X|U, X|U, X|U, X|U, X|U, X|U, U, + U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, + U, U, U, 0, 0, 0, 0, _, + + 0, X|L, X|L, X|L, X|L, X|L, X|L, L, + L, L, L, L, L, L, L, L, + L, L, L, L, L, L, L, L, + L, L, L, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#undef S +#undef D +#undef X +#undef U +#undef L +#undef _ +#undef d + +/* code point ranges for Zs,Zl or Zp property */ +static const uint16_t char_range_s[] = { + 10, + 0x0009, 0x000D + 1, + 0x0020, 0x0020 + 1, + 0x00A0, 0x00A0 + 1, + 0x1680, 0x1680 + 1, + 0x2000, 0x200A + 1, + /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */ + /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */ + 0x2028, 0x2029 + 1, + 0x202F, 0x202F + 1, + 0x205F, 0x205F + 1, + 0x3000, 0x3000 + 1, + /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */ + 0xFEFF, 0xFEFF + 1, +}; + +BOOL lre_is_space_non_ascii(uint32_t c) +{ + size_t i, n; + + n = countof(char_range_s); + for(i = 5; i < n; i += 2) { + uint32_t low = char_range_s[i]; + uint32_t high = char_range_s[i + 1]; + if (c < low) + return FALSE; + if (c < high) + return TRUE; + } + return FALSE; +} + +#define SEQ_MAX_LEN 16 + +static int unicode_sequence_prop1(int seq_prop_idx, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr) +{ + int i, c, j; + uint32_t seq[SEQ_MAX_LEN]; + + switch(seq_prop_idx) { + case UNICODE_SEQUENCE_PROP_Basic_Emoji: + if (unicode_prop1(cr, UNICODE_PROP_Basic_Emoji1) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + cb(opaque, seq, 1); + } + } + + cr->len = 0; + + if (unicode_prop1(cr, UNICODE_PROP_Basic_Emoji2) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + seq[1] = 0xfe0f; + cb(opaque, seq, 2); + } + } + + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_Emoji_Modifier_Base) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + for(j = 0; j < 5; j++) { + seq[0] = c; + seq[1] = 0x1f3fb + j; + cb(opaque, seq, 2); + } + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Flag_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_RGI_Emoji_Flag_Sequence) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + int c0, c1; + c0 = c / 26; + c1 = c % 26; + seq[0] = 0x1F1E6 + c0; + seq[1] = 0x1F1E6 + c1; + cb(opaque, seq, 2); + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence: + { + int len, code, pres, k, mod, mod_count, mod_pos[2], hc_pos, n_mod, n_hc, mod1; + int mod_idx, hc_idx, i0, i1; + const uint8_t *tab = unicode_rgi_emoji_zwj_sequence; + + for(i = 0; i < countof(unicode_rgi_emoji_zwj_sequence);) { + len = tab[i++]; + k = 0; + mod = 0; + mod_count = 0; + hc_pos = -1; + for(j = 0; j < len; j++) { + code = tab[i++]; + code |= tab[i++] << 8; + pres = code >> 15; + mod1 = (code >> 13) & 3; + code &= 0x1fff; + if (code < 0x1000) { + c = code + 0x2000; + } else { + c = 0x1f000 + (code - 0x1000); + } + if (c == 0x1f9b0) + hc_pos = k; + seq[k++] = c; + if (mod1 != 0) { + assert(mod_count < 2); + mod = mod1; + mod_pos[mod_count++] = k; + seq[k++] = 0; /* will be filled later */ + } + if (pres) { + seq[k++] = 0xfe0f; + } + if (j < len - 1) { + seq[k++] = 0x200d; + } + } + + /* genrate all the variants */ + switch(mod) { + case 1: + n_mod = 5; + break; + case 2: + n_mod = 25; + break; + case 3: + n_mod = 20; + break; + default: + n_mod = 1; + break; + } + if (hc_pos >= 0) + n_hc = 4; + else + n_hc = 1; + for(hc_idx = 0; hc_idx < n_hc; hc_idx++) { + for(mod_idx = 0; mod_idx < n_mod; mod_idx++) { + if (hc_pos >= 0) + seq[hc_pos] = 0x1f9b0 + hc_idx; + + switch(mod) { + case 1: + seq[mod_pos[0]] = 0x1f3fb + mod_idx; + break; + case 2: + case 3: + i0 = mod_idx / 5; + i1 = mod_idx % 5; + /* avoid identical values */ + if (mod == 3 && i0 >= i1) + i0++; + seq[mod_pos[0]] = 0x1f3fb + i0; + seq[mod_pos[1]] = 0x1f3fb + i1; + break; + default: + break; + } +#if 0 + for(j = 0; j < k; j++) + printf(" %04x", seq[j]); + printf("\n"); +#endif + cb(opaque, seq, k); + } + } + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Tag_Sequence: + { + for(i = 0; i < countof(unicode_rgi_emoji_tag_sequence);) { + j = 0; + seq[j++] = 0x1F3F4; + for(;;) { + c = unicode_rgi_emoji_tag_sequence[i++]; + if (c == 0x00) + break; + seq[j++] = 0xe0000 + c; + } + seq[j++] = 0xe007f; + cb(opaque, seq, j); + } + } + break; + case UNICODE_SEQUENCE_PROP_Emoji_Keycap_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_Emoji_Keycap_Sequence) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + seq[1] = 0xfe0f; + seq[2] = 0x20e3; + cb(opaque, seq, 3); + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji: + /* all prevous sequences */ + for(i = UNICODE_SEQUENCE_PROP_Basic_Emoji; i <= UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence; i++) { + int ret; + ret = unicode_sequence_prop1(i, cb, opaque, cr); + if (ret < 0) + return ret; + cr->len = 0; + } + break; + default: + return -2; + } + return 0; +} + +/* build a unicode sequence property */ +/* return -2 if not found, -1 if other error. 'cr' is used as temporary memory. */ +int unicode_sequence_prop(const char *prop_name, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr) +{ + int seq_prop_idx; + seq_prop_idx = unicode_find_name(unicode_sequence_prop_name_table, prop_name); + if (seq_prop_idx < 0) + return -2; + return unicode_sequence_prop1(seq_prop_idx, cb, opaque, cr); +} diff --git a/quickjs-ng/libunicode.h b/quickjs/libunicode.h similarity index 56% rename from quickjs-ng/libunicode.h rename to quickjs/libunicode.h index 8e6f2a0..5d964e4 100644 --- a/quickjs-ng/libunicode.h +++ b/quickjs/libunicode.h @@ -24,28 +24,13 @@ #ifndef LIBUNICODE_H #define LIBUNICODE_H -#include -#include -#include +#include -#ifdef __cplusplus -extern "C" { -#endif +/* define it to include all the unicode tables (40KB larger) */ +#define CONFIG_ALL_UNICODE #define LRE_CC_RES_LEN_MAX 3 -typedef enum { - UNICODE_NFC, - UNICODE_NFD, - UNICODE_NFKC, - UNICODE_NFKD, -} UnicodeNormalizationEnum; - -int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); -int lre_canonicalize(uint32_t c, bool is_unicode); -bool lre_is_cased(uint32_t c); -bool lre_is_case_ignorable(uint32_t c); - /* char ranges */ typedef struct { @@ -60,6 +45,7 @@ typedef enum { CR_OP_UNION, CR_OP_INTER, CR_OP_XOR, + CR_OP_SUB, } CharRangeOpEnum; void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); @@ -88,25 +74,28 @@ static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) return 0; } -int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); +int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, + const uint32_t *b_pt, int b_len, int op); +int cr_op1(CharRange *cr, const uint32_t *b_pt, int b_len, int op); static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2) { uint32_t b_pt[2]; b_pt[0] = c1; b_pt[1] = c2 + 1; - return cr_union1(cr, b_pt, 2); + return cr_op1(cr, b_pt, 2, CR_OP_UNION); } -int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, - const uint32_t *b_pt, int b_len, int op); - int cr_invert(CharRange *cr); -int cr_regexp_canonicalize(CharRange *cr, bool is_unicode); -bool lre_is_id_start(uint32_t c); -bool lre_is_id_continue(uint32_t c); -bool lre_is_white_space(uint32_t c); +int cr_regexp_canonicalize(CharRange *cr, int is_unicode); + +typedef enum { + UNICODE_NFC, + UNICODE_NFD, + UNICODE_NFKC, + UNICODE_NFKD, +} UnicodeNormalizationEnum; int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, UnicodeNormalizationEnum n_type, @@ -114,13 +103,84 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, /* Unicode character range functions */ -int unicode_script(CharRange *cr, - const char *script_name, bool is_ext); +int unicode_script(CharRange *cr, const char *script_name, int is_ext); int unicode_general_category(CharRange *cr, const char *gc_name); int unicode_prop(CharRange *cr, const char *prop_name); -#ifdef __cplusplus -} /* extern "C" { */ +typedef void UnicodeSequencePropCB(void *opaque, const uint32_t *buf, int len); +int unicode_sequence_prop(const char *prop_name, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr); + +int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); +int lre_canonicalize(uint32_t c, int is_unicode); + +/* Code point type categories */ +enum { + UNICODE_C_SPACE = (1 << 0), + UNICODE_C_DIGIT = (1 << 1), + UNICODE_C_UPPER = (1 << 2), + UNICODE_C_LOWER = (1 << 3), + UNICODE_C_UNDER = (1 << 4), + UNICODE_C_DOLLAR = (1 << 5), + UNICODE_C_XDIGIT = (1 << 6), +}; +extern uint8_t const lre_ctype_bits[256]; + +/* zero or non-zero return value */ +int lre_is_cased(uint32_t c); +int lre_is_case_ignorable(uint32_t c); +int lre_is_id_start(uint32_t c); +int lre_is_id_continue(uint32_t c); + +static inline int lre_is_space_byte(uint8_t c) { + return lre_ctype_bits[c] & UNICODE_C_SPACE; +} + +static inline int lre_is_id_start_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR); +} + +static inline int lre_is_id_continue_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR | + UNICODE_C_DIGIT); +} + +int lre_is_space_non_ascii(uint32_t c); + +static inline int lre_is_space(uint32_t c) { + if (c < 256) + return lre_is_space_byte(c); + else + return lre_is_space_non_ascii(c); +} + +static inline int lre_js_is_ident_first(uint32_t c) { + if (c < 128) { + return lre_is_id_start_byte(c); + } else { +#ifdef CONFIG_ALL_UNICODE + return lre_is_id_start(c); +#else + return !lre_is_space_non_ascii(c); #endif + } +} + +static inline int lre_js_is_ident_next(uint32_t c) { + if (c < 128) { + return lre_is_id_continue_byte(c); + } else { + /* ZWNJ and ZWJ are accepted in identifiers */ + if (c >= 0x200C && c <= 0x200D) + return TRUE; +#ifdef CONFIG_ALL_UNICODE + return lre_is_id_continue(c); +#else + return !lre_is_space_non_ascii(c); +#endif + } +} #endif /* LIBUNICODE_H */ diff --git a/quickjs-ng/list.h b/quickjs/list.h similarity index 97% rename from quickjs-ng/list.h rename to quickjs/list.h index b8dd716..8098311 100644 --- a/quickjs-ng/list.h +++ b/quickjs/list.h @@ -28,10 +28,6 @@ #include #endif -#ifdef __cplusplus -extern "C" { -#endif - struct list_head { struct list_head *prev; struct list_head *next; @@ -100,8 +96,4 @@ static inline int list_empty(struct list_head *el) for(el = (head)->prev, el1 = el->prev; el != (head); \ el = el1, el1 = el->prev) -#ifdef __cplusplus -} /* extern "C" { */ -#endif - #endif /* LIST_H */ diff --git a/quickjs/qjs.c b/quickjs/qjs.c new file mode 100644 index 0000000..a88e39a --- /dev/null +++ b/quickjs/qjs.c @@ -0,0 +1,551 @@ +/* + * QuickJS stand alone interpreter + * + * Copyright (c) 2017-2021 Fabrice Bellard + * Copyright (c) 2017-2021 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__APPLE__) +#include +#elif defined(__linux__) || defined(__GLIBC__) +#include +#elif defined(__FreeBSD__) +#include +#endif + +#include "cutils.h" +#include "quickjs-libc.h" + +extern const uint8_t qjsc_repl[]; +extern const uint32_t qjsc_repl_size; + +static int eval_buf(JSContext *ctx, const void *buf, int buf_len, + const char *filename, int eval_flags) +{ + JSValue val; + int ret; + + if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) { + /* for the modules, we compile then run to be able to set + import.meta */ + val = JS_Eval(ctx, buf, buf_len, filename, + eval_flags | JS_EVAL_FLAG_COMPILE_ONLY); + if (!JS_IsException(val)) { + js_module_set_import_meta(ctx, val, TRUE, TRUE); + val = JS_EvalFunction(ctx, val); + } + val = js_std_await(ctx, val); + } else { + val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); + } + if (JS_IsException(val)) { + js_std_dump_error(ctx); + ret = -1; + } else { + ret = 0; + } + JS_FreeValue(ctx, val); + return ret; +} + +static int eval_file(JSContext *ctx, const char *filename, int module) +{ + uint8_t *buf; + int ret, eval_flags; + size_t buf_len; + + buf = js_load_file(ctx, &buf_len, filename); + if (!buf) { + perror(filename); + exit(1); + } + + if (module < 0) { + module = (has_suffix(filename, ".mjs") || + JS_DetectModule((const char *)buf, buf_len)); + } + if (module) + eval_flags = JS_EVAL_TYPE_MODULE; + else + eval_flags = JS_EVAL_TYPE_GLOBAL; + ret = eval_buf(ctx, buf, buf_len, filename, eval_flags); + js_free(ctx, buf); + return ret; +} + +/* also used to initialize the worker context */ +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx; + ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + /* system modules */ + js_init_module_std(ctx, "std"); + js_init_module_os(ctx, "os"); + return ctx; +} + +#if defined(__APPLE__) +#define MALLOC_OVERHEAD 0 +#else +#define MALLOC_OVERHEAD 8 +#endif + +struct trace_malloc_data { + uint8_t *base; +}; + +static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, + struct trace_malloc_data *dp) +{ + return ptr - dp->base; +} + +/* default memory allocation functions with memory limitation */ +static size_t js_trace_malloc_usable_size(const void *ptr) +{ +#if defined(__APPLE__) + return malloc_size(ptr); +#elif defined(_WIN32) + return _msize((void *)ptr); +#elif defined(EMSCRIPTEN) + return 0; +#elif defined(__linux__) || defined(__GLIBC__) + return malloc_usable_size((void *)ptr); +#else + /* change this to `return 0;` if compilation fails */ + return malloc_usable_size((void *)ptr); +#endif +} + +static void +#ifdef _WIN32 +/* mingw printf is used */ +__attribute__((format(gnu_printf, 2, 3))) +#else +__attribute__((format(printf, 2, 3))) +#endif + js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...) +{ + va_list ap; + int c; + + va_start(ap, fmt); + while ((c = *fmt++) != '\0') { + if (c == '%') { + /* only handle %p and %zd */ + if (*fmt == 'p') { + uint8_t *ptr = va_arg(ap, void *); + if (ptr == NULL) { + printf("NULL"); + } else { + printf("H%+06lld.%zd", + js_trace_malloc_ptr_offset(ptr, s->opaque), + js_trace_malloc_usable_size(ptr)); + } + fmt++; + continue; + } + if (fmt[0] == 'z' && fmt[1] == 'd') { + size_t sz = va_arg(ap, size_t); + printf("%zd", sz); + fmt += 2; + continue; + } + } + putc(c, stdout); + } + va_end(ap); +} + +static void js_trace_malloc_init(struct trace_malloc_data *s) +{ + free(s->base = malloc(8)); +} + +static void *js_trace_malloc(JSMallocState *s, size_t size) +{ + void *ptr; + + /* Do not allocate zero bytes: behavior is platform dependent */ + assert(size != 0); + + if (unlikely(s->malloc_size + size > s->malloc_limit)) + return NULL; + ptr = malloc(size); + js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr); + if (ptr) { + s->malloc_count++; + s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + } + return ptr; +} + +static void js_trace_free(JSMallocState *s, void *ptr) +{ + if (!ptr) + return; + + js_trace_malloc_printf(s, "F %p\n", ptr); + s->malloc_count--; + s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + free(ptr); +} + +static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size) +{ + size_t old_size; + + if (!ptr) { + if (size == 0) + return NULL; + return js_trace_malloc(s, size); + } + old_size = js_trace_malloc_usable_size(ptr); + if (size == 0) { + js_trace_malloc_printf(s, "R %zd %p\n", size, ptr); + s->malloc_count--; + s->malloc_size -= old_size + MALLOC_OVERHEAD; + free(ptr); + return NULL; + } + if (s->malloc_size + size - old_size > s->malloc_limit) + return NULL; + + js_trace_malloc_printf(s, "R %zd %p", size, ptr); + + ptr = realloc(ptr, size); + js_trace_malloc_printf(s, " -> %p\n", ptr); + if (ptr) { + s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size; + } + return ptr; +} + +static const JSMallocFunctions trace_mf = { + js_trace_malloc, + js_trace_free, + js_trace_realloc, + js_trace_malloc_usable_size, +}; + +static size_t get_suffixed_size(const char *str) +{ + char *p; + size_t v; + v = (size_t)strtod(str, &p); + switch(*p) { + case 'G': + v <<= 30; + break; + case 'M': + v <<= 20; + break; + case 'k': + case 'K': + v <<= 10; + break; + default: + if (*p != '\0') { + fprintf(stderr, "qjs: invalid suffix: %s\n", p); + exit(1); + } + break; + } + return v; +} + +#define PROG_NAME "qjs" + +void help(void) +{ + printf("QuickJS version " CONFIG_VERSION "\n" + "usage: " PROG_NAME " [options] [file [args]]\n" + "-h --help list options\n" + "-e --eval EXPR evaluate EXPR\n" + "-i --interactive go to interactive mode\n" + "-m --module load as ES6 module (default=autodetect)\n" + " --script load as ES6 script (default=autodetect)\n" + "-I --include file include an additional file\n" + " --std make 'std' and 'os' available to the loaded script\n" + "-T --trace trace memory allocation\n" + "-d --dump dump the memory usage stats\n" + " --memory-limit n limit the memory usage to 'n' bytes (SI suffixes allowed)\n" + " --stack-size n limit the stack size to 'n' bytes (SI suffixes allowed)\n" + " --no-unhandled-rejection ignore unhandled promise rejections\n" + "-s strip all the debug info\n" + " --strip-source strip the source code\n" + "-q --quit just instantiate the interpreter and quit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + JSRuntime *rt; + JSContext *ctx; + struct trace_malloc_data trace_data = { NULL }; + int optind; + char *expr = NULL; + int interactive = 0; + int dump_memory = 0; + int trace_memory = 0; + int empty_run = 0; + int module = -1; + int load_std = 0; + int dump_unhandled_promise_rejection = 1; + size_t memory_limit = 0; + char *include_list[32]; + int i, include_count = 0; + int strip_flags = 0; + size_t stack_size = 0; + + /* cannot use getopt because we want to pass the command line to + the script */ + optind = 1; + while (optind < argc && *argv[optind] == '-') { + char *arg = argv[optind] + 1; + const char *longopt = ""; + /* a single - is not an option, it also stops argument scanning */ + if (!*arg) + break; + optind++; + if (*arg == '-') { + longopt = arg + 1; + arg += strlen(arg); + /* -- stops argument scanning */ + if (!*longopt) + break; + } + for (; *arg || *longopt; longopt = "") { + char opt = *arg; + if (opt) + arg++; + if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { + help(); + continue; + } + if (opt == 'e' || !strcmp(longopt, "eval")) { + if (*arg) { + expr = arg; + break; + } + if (optind < argc) { + expr = argv[optind++]; + break; + } + fprintf(stderr, "qjs: missing expression for -e\n"); + exit(2); + } + if (opt == 'I' || !strcmp(longopt, "include")) { + if (optind >= argc) { + fprintf(stderr, "expecting filename"); + exit(1); + } + if (include_count >= countof(include_list)) { + fprintf(stderr, "too many included files"); + exit(1); + } + include_list[include_count++] = argv[optind++]; + continue; + } + if (opt == 'i' || !strcmp(longopt, "interactive")) { + interactive++; + continue; + } + if (opt == 'm' || !strcmp(longopt, "module")) { + module = 1; + continue; + } + if (!strcmp(longopt, "script")) { + module = 0; + continue; + } + if (opt == 'd' || !strcmp(longopt, "dump")) { + dump_memory++; + continue; + } + if (opt == 'T' || !strcmp(longopt, "trace")) { + trace_memory++; + continue; + } + if (!strcmp(longopt, "std")) { + load_std = 1; + continue; + } + if (!strcmp(longopt, "no-unhandled-rejection")) { + dump_unhandled_promise_rejection = 0; + continue; + } + if (opt == 'q' || !strcmp(longopt, "quit")) { + empty_run++; + continue; + } + if (!strcmp(longopt, "memory-limit")) { + if (optind >= argc) { + fprintf(stderr, "expecting memory limit"); + exit(1); + } + memory_limit = get_suffixed_size(argv[optind++]); + continue; + } + if (!strcmp(longopt, "stack-size")) { + if (optind >= argc) { + fprintf(stderr, "expecting stack size"); + exit(1); + } + stack_size = get_suffixed_size(argv[optind++]); + continue; + } + if (opt == 's') { + strip_flags = JS_STRIP_DEBUG; + continue; + } + if (!strcmp(longopt, "strip-source")) { + strip_flags = JS_STRIP_SOURCE; + continue; + } + if (opt) { + fprintf(stderr, "qjs: unknown option '-%c'\n", opt); + } else { + fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); + } + help(); + } + } + + if (trace_memory) { + js_trace_malloc_init(&trace_data); + rt = JS_NewRuntime2(&trace_mf, &trace_data); + } else { + rt = JS_NewRuntime(); + } + if (!rt) { + fprintf(stderr, "qjs: cannot allocate JS runtime\n"); + exit(2); + } + if (memory_limit != 0) + JS_SetMemoryLimit(rt, memory_limit); + if (stack_size != 0) + JS_SetMaxStackSize(rt, stack_size); + JS_SetStripInfo(rt, strip_flags); + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + ctx = JS_NewCustomContext(rt); + if (!ctx) { + fprintf(stderr, "qjs: cannot allocate JS context\n"); + exit(2); + } + + /* loader for ES6 modules */ + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); + + if (dump_unhandled_promise_rejection) { + JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, + NULL); + } + + if (!empty_run) { + js_std_add_helpers(ctx, argc - optind, argv + optind); + + /* make 'std' and 'os' visible to non module code */ + if (load_std) { + const char *str = "import * as std from 'std';\n" + "import * as os from 'os';\n" + "globalThis.std = std;\n" + "globalThis.os = os;\n"; + eval_buf(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE); + } + + for(i = 0; i < include_count; i++) { + if (eval_file(ctx, include_list[i], module)) + goto fail; + } + + if (expr) { + if (eval_buf(ctx, expr, strlen(expr), "", 0)) + goto fail; + } else + if (optind >= argc) { + /* interactive mode */ + interactive = 1; + } else { + const char *filename; + filename = argv[optind]; + if (eval_file(ctx, filename, module)) + goto fail; + } + if (interactive) { + JS_SetHostPromiseRejectionTracker(rt, NULL, NULL); + js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0); + } + js_std_loop(ctx); + } + + if (dump_memory) { + JSMemoryUsage stats; + JS_ComputeMemoryUsage(rt, &stats); + JS_DumpMemoryUsage(stdout, &stats, rt); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + if (empty_run && dump_memory) { + clock_t t[5]; + double best[5]; + int i, j; + for (i = 0; i < 100; i++) { + t[0] = clock(); + rt = JS_NewRuntime(); + t[1] = clock(); + ctx = JS_NewContext(rt); + t[2] = clock(); + JS_FreeContext(ctx); + t[3] = clock(); + JS_FreeRuntime(rt); + t[4] = clock(); + for (j = 4; j > 0; j--) { + double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC; + if (i == 0 || best[j] > ms) + best[j] = ms; + } + } + printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n", + best[1] + best[2] + best[3] + best[4], + best[1], best[2], best[3], best[4]); + } + return 0; + fail: + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 1; +} diff --git a/quickjs/qjsc.c b/quickjs/qjsc.c new file mode 100644 index 0000000..e55ca61 --- /dev/null +++ b/quickjs/qjsc.c @@ -0,0 +1,876 @@ +/* + * QuickJS command line compiler + * + * Copyright (c) 2018-2021 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(_WIN32) +#include +#endif + +#include "cutils.h" +#include "quickjs-libc.h" + +typedef struct { + char *name; + char *short_name; + int flags; +} namelist_entry_t; + +typedef struct namelist_t { + namelist_entry_t *array; + int count; + int size; +} namelist_t; + +typedef struct { + const char *option_name; + const char *init_name; +} FeatureEntry; + +static namelist_t cname_list; +static namelist_t cmodule_list; +static namelist_t init_module_list; +static uint64_t feature_bitmap; +static FILE *outfile; +static BOOL byte_swap; +static BOOL dynamic_export; +static const char *c_ident_prefix = "qjsc_"; + +#define FE_ALL (-1) + +static const FeatureEntry feature_list[] = { + { "date", "Date" }, + { "eval", "Eval" }, + { "string-normalize", "StringNormalize" }, + { "regexp", "RegExp" }, + { "json", "JSON" }, + { "proxy", "Proxy" }, + { "map", "MapSet" }, + { "typedarray", "TypedArrays" }, + { "promise", "Promise" }, +#define FE_MODULE_LOADER 9 + { "module-loader", NULL }, + { "weakref", "WeakRef" }, +}; + +void namelist_add(namelist_t *lp, const char *name, const char *short_name, + int flags) +{ + namelist_entry_t *e; + if (lp->count == lp->size) { + size_t newsize = lp->size + (lp->size >> 1) + 4; + namelist_entry_t *a = + realloc(lp->array, sizeof(lp->array[0]) * newsize); + /* XXX: check for realloc failure */ + lp->array = a; + lp->size = newsize; + } + e = &lp->array[lp->count++]; + e->name = strdup(name); + if (short_name) + e->short_name = strdup(short_name); + else + e->short_name = NULL; + e->flags = flags; +} + +void namelist_free(namelist_t *lp) +{ + while (lp->count > 0) { + namelist_entry_t *e = &lp->array[--lp->count]; + free(e->name); + free(e->short_name); + } + free(lp->array); + lp->array = NULL; + lp->size = 0; +} + +namelist_entry_t *namelist_find(namelist_t *lp, const char *name) +{ + int i; + for(i = 0; i < lp->count; i++) { + namelist_entry_t *e = &lp->array[i]; + if (!strcmp(e->name, name)) + return e; + } + return NULL; +} + +static void get_c_name(char *buf, size_t buf_size, const char *file) +{ + const char *p, *r; + size_t len, i; + int c; + char *q; + + p = strrchr(file, '/'); + if (!p) + p = file; + else + p++; + r = strrchr(p, '.'); + if (!r) + len = strlen(p); + else + len = r - p; + pstrcpy(buf, buf_size, c_ident_prefix); + q = buf + strlen(buf); + for(i = 0; i < len; i++) { + c = p[i]; + if (!((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'))) { + c = '_'; + } + if ((q - buf) < buf_size - 1) + *q++ = c; + } + *q = '\0'; +} + +static void dump_hex(FILE *f, const uint8_t *buf, size_t len) +{ + size_t i, col; + col = 0; + for(i = 0; i < len; i++) { + fprintf(f, " 0x%02x,", buf[i]); + if (++col == 8) { + fprintf(f, "\n"); + col = 0; + } + } + if (col != 0) + fprintf(f, "\n"); +} + +typedef enum { + CNAME_TYPE_SCRIPT, + CNAME_TYPE_MODULE, + CNAME_TYPE_JSON_MODULE, +} CNameTypeEnum; + +static void output_object_code(JSContext *ctx, + FILE *fo, JSValueConst obj, const char *c_name, + CNameTypeEnum c_name_type) +{ + uint8_t *out_buf; + size_t out_buf_len; + int flags; + + if (c_name_type == CNAME_TYPE_JSON_MODULE) + flags = 0; + else + flags = JS_WRITE_OBJ_BYTECODE; + if (byte_swap) + flags |= JS_WRITE_OBJ_BSWAP; + out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); + if (!out_buf) { + js_std_dump_error(ctx); + exit(1); + } + + namelist_add(&cname_list, c_name, NULL, c_name_type); + + fprintf(fo, "const uint32_t %s_size = %u;\n\n", + c_name, (unsigned int)out_buf_len); + fprintf(fo, "const uint8_t %s[%u] = {\n", + c_name, (unsigned int)out_buf_len); + dump_hex(fo, out_buf, out_buf_len); + fprintf(fo, "};\n\n"); + + js_free(ctx, out_buf); +} + +static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) +{ + /* should never be called when compiling JS code */ + abort(); +} + +static void find_unique_cname(char *cname, size_t cname_size) +{ + char cname1[1024]; + int suffix_num; + size_t len, max_len; + assert(cname_size >= 32); + /* find a C name not matching an existing module C name by + adding a numeric suffix */ + len = strlen(cname); + max_len = cname_size - 16; + if (len > max_len) + cname[max_len] = '\0'; + suffix_num = 1; + for(;;) { + snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num); + if (!namelist_find(&cname_list, cname1)) + break; + suffix_num++; + } + pstrcpy(cname, cname_size, cname1); +} + +JSModuleDef *jsc_module_loader(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes) +{ + JSModuleDef *m; + namelist_entry_t *e; + + /* check if it is a declared C or system module */ + e = namelist_find(&cmodule_list, module_name); + if (e) { + /* add in the static init module list */ + namelist_add(&init_module_list, e->name, e->short_name, 0); + /* create a dummy module */ + m = JS_NewCModule(ctx, module_name, js_module_dummy_init); + } else if (has_suffix(module_name, ".so")) { + fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name); + /* create a dummy module */ + m = JS_NewCModule(ctx, module_name, js_module_dummy_init); + /* the resulting executable will export its symbols for the + dynamic library */ + dynamic_export = TRUE; + } else { + size_t buf_len; + uint8_t *buf; + char cname[1024]; + int res; + + buf = js_load_file(ctx, &buf_len, module_name); + if (!buf) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s'", + module_name); + return NULL; + } + + res = js_module_test_json(ctx, attributes); + if (has_suffix(module_name, ".json") || res > 0) { + /* compile as JSON or JSON5 depending on "type" */ + JSValue val; + int flags; + + if (res == 2) + flags = JS_PARSE_JSON_EXT; + else + flags = 0; + val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags); + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + /* create a dummy module */ + m = JS_NewCModule(ctx, module_name, js_module_dummy_init); + if (!m) { + JS_FreeValue(ctx, val); + return NULL; + } + + get_c_name(cname, sizeof(cname), module_name); + if (namelist_find(&cname_list, cname)) { + find_unique_cname(cname, sizeof(cname)); + } + + /* output the module name */ + fprintf(outfile, "static const uint8_t %s_module_name[] = {\n", + cname); + dump_hex(outfile, (const uint8_t *)module_name, strlen(module_name) + 1); + fprintf(outfile, "};\n\n"); + + output_object_code(ctx, outfile, val, cname, CNAME_TYPE_JSON_MODULE); + JS_FreeValue(ctx, val); + } else { + JSValue func_val; + + /* compile the module */ + func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + js_free(ctx, buf); + if (JS_IsException(func_val)) + return NULL; + get_c_name(cname, sizeof(cname), module_name); + if (namelist_find(&cname_list, cname)) { + find_unique_cname(cname, sizeof(cname)); + } + output_object_code(ctx, outfile, func_val, cname, CNAME_TYPE_MODULE); + + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(func_val); + JS_FreeValue(ctx, func_val); + } + } + return m; +} + +static void compile_file(JSContext *ctx, FILE *fo, + const char *filename, + const char *c_name1, + int module) +{ + uint8_t *buf; + char c_name[1024]; + int eval_flags; + JSValue obj; + size_t buf_len; + + buf = js_load_file(ctx, &buf_len, filename); + if (!buf) { + fprintf(stderr, "Could not load '%s'\n", filename); + exit(1); + } + eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; + if (module < 0) { + module = (has_suffix(filename, ".mjs") || + JS_DetectModule((const char *)buf, buf_len)); + } + if (module) + eval_flags |= JS_EVAL_TYPE_MODULE; + else + eval_flags |= JS_EVAL_TYPE_GLOBAL; + obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags); + if (JS_IsException(obj)) { + js_std_dump_error(ctx); + exit(1); + } + js_free(ctx, buf); + if (c_name1) { + pstrcpy(c_name, sizeof(c_name), c_name1); + } else { + get_c_name(c_name, sizeof(c_name), filename); + if (namelist_find(&cname_list, c_name)) { + find_unique_cname(c_name, sizeof(c_name)); + } + } + output_object_code(ctx, fo, obj, c_name, CNAME_TYPE_SCRIPT); + JS_FreeValue(ctx, obj); +} + +static const char main_c_template1[] = + "int main(int argc, char **argv)\n" + "{\n" + " JSRuntime *rt;\n" + " JSContext *ctx;\n" + " rt = JS_NewRuntime();\n" + " js_std_set_worker_new_context_func(JS_NewCustomContext);\n" + " js_std_init_handlers(rt);\n" + ; + +static const char main_c_template2[] = + " js_std_loop(ctx);\n" + " js_std_free_handlers(rt);\n" + " JS_FreeContext(ctx);\n" + " JS_FreeRuntime(rt);\n" + " return 0;\n" + "}\n"; + +#define PROG_NAME "qjsc" + +void help(void) +{ + printf("QuickJS Compiler version " CONFIG_VERSION "\n" + "usage: " PROG_NAME " [options] [files]\n" + "\n" + "options are:\n" + "-c only output bytecode to a C file\n" + "-e output main() and bytecode to a C file (default = executable output)\n" + "-o output set the output filename\n" + "-N cname set the C name of the generated data\n" + "-m compile as Javascript module (default=autodetect)\n" + "-D module_name compile a dynamically loaded module or worker\n" + "-M module_name[,cname] add initialization code for an external C module\n" + "-x byte swapped output\n" + "-p prefix set the prefix of the generated C names\n" + "-S n set the maximum stack size to 'n' bytes (default=%d)\n" + "-s strip all the debug info\n" + "--keep-source keep the source code\n", + JS_DEFAULT_STACK_SIZE); +#ifdef CONFIG_LTO + { + int i; + printf("-flto use link time optimization\n"); + printf("-fno-["); + for(i = 0; i < countof(feature_list); i++) { + if (i != 0) + printf("|"); + printf("%s", feature_list[i].option_name); + } + printf("]\n" + " disable selected language features (smaller code size)\n"); + } +#endif + exit(1); +} + +#if defined(CONFIG_CC) && !defined(_WIN32) + +int exec_cmd(char **argv) +{ + int pid, status, ret; + + pid = fork(); + if (pid == 0) { + execvp(argv[0], argv); + exit(1); + } + + for(;;) { + ret = waitpid(pid, &status, 0); + if (ret == pid && WIFEXITED(status)) + break; + } + return WEXITSTATUS(status); +} + +static int output_executable(const char *out_filename, const char *cfilename, + BOOL use_lto, BOOL verbose, const char *exename) +{ + const char *argv[64]; + const char **arg, *bn_suffix, *lto_suffix; + char libjsname[1024]; + char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p; + int ret; + + /* get the directory of the executable */ + pstrcpy(exe_dir, sizeof(exe_dir), exename); + p = strrchr(exe_dir, '/'); + if (p) { + *p = '\0'; + } else { + pstrcpy(exe_dir, sizeof(exe_dir), "."); + } + + /* if 'quickjs.h' is present at the same path as the executable, we + use it as include and lib directory */ + snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir); + if (access(buf, R_OK) == 0) { + pstrcpy(inc_dir, sizeof(inc_dir), exe_dir); + pstrcpy(lib_dir, sizeof(lib_dir), exe_dir); + } else { + snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX); + snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX); + } + + lto_suffix = ""; + bn_suffix = ""; + + arg = argv; + *arg++ = CONFIG_CC; + *arg++ = "-O2"; +#ifdef CONFIG_LTO + if (use_lto) { + *arg++ = "-flto"; + lto_suffix = ".lto"; + } +#endif + /* XXX: use the executable path to find the includes files and + libraries */ + *arg++ = "-D"; + *arg++ = "_GNU_SOURCE"; + *arg++ = "-I"; + *arg++ = inc_dir; + *arg++ = "-o"; + *arg++ = out_filename; + if (dynamic_export) + *arg++ = "-rdynamic"; + *arg++ = cfilename; + snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a", + lib_dir, bn_suffix, lto_suffix); + *arg++ = libjsname; + *arg++ = "-lm"; + *arg++ = "-ldl"; + *arg++ = "-lpthread"; + *arg = NULL; + + if (verbose) { + for(arg = argv; *arg != NULL; arg++) + printf("%s ", *arg); + printf("\n"); + } + + ret = exec_cmd((char **)argv); + unlink(cfilename); + return ret; +} +#else +static int output_executable(const char *out_filename, const char *cfilename, + BOOL use_lto, BOOL verbose, const char *exename) +{ + fprintf(stderr, "Executable output is not supported for this target\n"); + exit(1); + return 0; +} +#endif + +static size_t get_suffixed_size(const char *str) +{ + char *p; + size_t v; + v = (size_t)strtod(str, &p); + switch(*p) { + case 'G': + v <<= 30; + break; + case 'M': + v <<= 20; + break; + case 'k': + case 'K': + v <<= 10; + break; + default: + if (*p != '\0') { + fprintf(stderr, "qjs: invalid suffix: %s\n", p); + exit(1); + } + break; + } + return v; +} + +typedef enum { + OUTPUT_C, + OUTPUT_C_MAIN, + OUTPUT_EXECUTABLE, +} OutputTypeEnum; + +static const char *get_short_optarg(int *poptind, int opt, + const char *arg, int argc, char **argv) +{ + const char *optarg; + if (*arg) { + optarg = arg; + } else if (*poptind < argc) { + optarg = argv[(*poptind)++]; + } else { + fprintf(stderr, "qjsc: expecting parameter for -%c\n", opt); + exit(1); + } + return optarg; +} + +int main(int argc, char **argv) +{ + int i, verbose, strip_flags; + const char *out_filename, *cname; + char cfilename[1024]; + FILE *fo; + JSRuntime *rt; + JSContext *ctx; + BOOL use_lto; + int module; + OutputTypeEnum output_type; + size_t stack_size; + namelist_t dynamic_module_list; + + out_filename = NULL; + output_type = OUTPUT_EXECUTABLE; + cname = NULL; + feature_bitmap = FE_ALL; + module = -1; + byte_swap = FALSE; + verbose = 0; + strip_flags = JS_STRIP_SOURCE; + use_lto = FALSE; + stack_size = 0; + memset(&dynamic_module_list, 0, sizeof(dynamic_module_list)); + + /* add system modules */ + namelist_add(&cmodule_list, "std", "std", 0); + namelist_add(&cmodule_list, "os", "os", 0); + + optind = 1; + while (optind < argc && *argv[optind] == '-') { + char *arg = argv[optind] + 1; + const char *longopt = ""; + const char *optarg; + /* a single - is not an option, it also stops argument scanning */ + if (!*arg) + break; + optind++; + if (*arg == '-') { + longopt = arg + 1; + arg += strlen(arg); + /* -- stops argument scanning */ + if (!*longopt) + break; + } + for (; *arg || *longopt; longopt = "") { + char opt = *arg; + if (opt) + arg++; + if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { + help(); + continue; + } + if (opt == 'o') { + out_filename = get_short_optarg(&optind, opt, arg, argc, argv); + break; + } + if (opt == 'c') { + output_type = OUTPUT_C; + continue; + } + if (opt == 'e') { + output_type = OUTPUT_C_MAIN; + continue; + } + if (opt == 'N') { + cname = get_short_optarg(&optind, opt, arg, argc, argv); + break; + } + if (opt == 'f') { + const char *p; + optarg = get_short_optarg(&optind, opt, arg, argc, argv); + p = optarg; + if (!strcmp(p, "lto")) { + use_lto = TRUE; + } else if (strstart(p, "no-", &p)) { + use_lto = TRUE; + for(i = 0; i < countof(feature_list); i++) { + if (!strcmp(p, feature_list[i].option_name)) { + feature_bitmap &= ~((uint64_t)1 << i); + break; + } + } + if (i == countof(feature_list)) + goto bad_feature; + } else { + bad_feature: + fprintf(stderr, "unsupported feature: %s\n", optarg); + exit(1); + } + break; + } + if (opt == 'm') { + module = 1; + continue; + } + if (opt == 'M') { + char *p; + char path[1024]; + char cname[1024]; + + optarg = get_short_optarg(&optind, opt, arg, argc, argv); + pstrcpy(path, sizeof(path), optarg); + p = strchr(path, ','); + if (p) { + *p = '\0'; + pstrcpy(cname, sizeof(cname), p + 1); + } else { + get_c_name(cname, sizeof(cname), path); + } + namelist_add(&cmodule_list, path, cname, 0); + break; + } + if (opt == 'D') { + optarg = get_short_optarg(&optind, opt, arg, argc, argv); + namelist_add(&dynamic_module_list, optarg, NULL, 0); + break; + } + if (opt == 'x') { + byte_swap = 1; + continue; + } + if (opt == 'v') { + verbose++; + continue; + } + if (opt == 'p') { + c_ident_prefix = get_short_optarg(&optind, opt, arg, argc, argv); + break; + } + if (opt == 'S') { + optarg = get_short_optarg(&optind, opt, arg, argc, argv); + stack_size = get_suffixed_size(optarg); + break; + } + if (opt == 's') { + strip_flags = JS_STRIP_DEBUG; + continue; + } + if (!strcmp(longopt, "keep-source")) { + strip_flags = 0; + continue; + } + if (opt) { + fprintf(stderr, "qjsc: unknown option '-%c'\n", opt); + } else { + fprintf(stderr, "qjsc: unknown option '--%s'\n", longopt); + } + help(); + } + } + + if (optind >= argc) + help(); + + if (!out_filename) { + if (output_type == OUTPUT_EXECUTABLE) { + out_filename = "a.out"; + } else { + out_filename = "out.c"; + } + } + + if (output_type == OUTPUT_EXECUTABLE) { +#if defined(_WIN32) || defined(__ANDROID__) + /* XXX: find a /tmp directory ? */ + snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid()); +#else + snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid()); +#endif + } else { + pstrcpy(cfilename, sizeof(cfilename), out_filename); + } + + fo = fopen(cfilename, "w"); + if (!fo) { + perror(cfilename); + exit(1); + } + outfile = fo; + + rt = JS_NewRuntime(); + ctx = JS_NewContext(rt); + + JS_SetStripInfo(rt, strip_flags); + + /* loader for ES6 modules */ + JS_SetModuleLoaderFunc2(rt, NULL, jsc_module_loader, NULL, NULL); + + fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" + "\n" + ); + + if (output_type != OUTPUT_C) { + fprintf(fo, "#include \"quickjs-libc.h\"\n" + "\n" + ); + } else { + fprintf(fo, "#include \n" + "\n" + ); + } + + for(i = optind; i < argc; i++) { + const char *filename = argv[i]; + compile_file(ctx, fo, filename, cname, module); + cname = NULL; + } + + for(i = 0; i < dynamic_module_list.count; i++) { + if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL, JS_UNDEFINED)) { + fprintf(stderr, "Could not load dynamic module '%s'\n", + dynamic_module_list.array[i].name); + exit(1); + } + } + + if (output_type != OUTPUT_C) { + fprintf(fo, + "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n" + "{\n" + " JSContext *ctx = JS_NewContextRaw(rt);\n" + " if (!ctx)\n" + " return NULL;\n"); + /* add the basic objects */ + fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n"); + for(i = 0; i < countof(feature_list); i++) { + if ((feature_bitmap & ((uint64_t)1 << i)) && + feature_list[i].init_name) { + fprintf(fo, " JS_AddIntrinsic%s(ctx);\n", + feature_list[i].init_name); + } + } + /* add the precompiled modules (XXX: could modify the module + loader instead) */ + for(i = 0; i < init_module_list.count; i++) { + namelist_entry_t *e = &init_module_list.array[i]; + /* initialize the static C modules */ + + fprintf(fo, + " {\n" + " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" + " js_init_module_%s(ctx, \"%s\");\n" + " }\n", + e->short_name, e->short_name, e->name); + } + for(i = 0; i < cname_list.count; i++) { + namelist_entry_t *e = &cname_list.array[i]; + if (e->flags == CNAME_TYPE_MODULE) { + fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n", + e->name, e->name); + } else if (e->flags == CNAME_TYPE_JSON_MODULE) { + fprintf(fo, " js_std_eval_binary_json_module(ctx, %s, %s_size, (const char *)%s_module_name);\n", + e->name, e->name, e->name); + } + } + fprintf(fo, + " return ctx;\n" + "}\n\n"); + + fputs(main_c_template1, fo); + + if (stack_size != 0) { + fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n", + (unsigned int)stack_size); + } + + /* add the module loader if necessary */ + if (feature_bitmap & (1 << FE_MODULE_LOADER)) { + fprintf(fo, " JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);\n"); + } + + fprintf(fo, + " ctx = JS_NewCustomContext(rt);\n" + " js_std_add_helpers(ctx, argc, argv);\n"); + + for(i = 0; i < cname_list.count; i++) { + namelist_entry_t *e = &cname_list.array[i]; + if (e->flags == CNAME_TYPE_SCRIPT) { + fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n", + e->name, e->name); + } + } + fputs(main_c_template2, fo); + } + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + fclose(fo); + + if (output_type == OUTPUT_EXECUTABLE) { + return output_executable(out_filename, cfilename, use_lto, verbose, + argv[0]); + } + namelist_free(&cname_list); + namelist_free(&cmodule_list); + namelist_free(&init_module_list); + return 0; +} diff --git a/quickjs-ng/quickjs-atom.h b/quickjs/quickjs-atom.h similarity index 94% rename from quickjs-ng/quickjs-atom.h rename to quickjs/quickjs-atom.h index 2a12328..23c2ed0 100644 --- a/quickjs-ng/quickjs-atom.h +++ b/quickjs/quickjs-atom.h @@ -81,6 +81,9 @@ DEF(empty_string, "") DEF(keys, "keys") DEF(size, "size") DEF(length, "length") +DEF(fileName, "fileName") +DEF(lineNumber, "lineNumber") +DEF(columnNumber, "columnNumber") DEF(message, "message") DEF(cause, "cause") DEF(errors, "errors") @@ -154,7 +157,6 @@ DEF(brand, "") DEF(hash_constructor, "#constructor") DEF(as, "as") DEF(from, "from") -DEF(fromAsync, "fromAsync") DEF(meta, "meta") DEF(_default_, "*default*") DEF(_star_, "*") @@ -173,9 +175,21 @@ DEF(status, "status") DEF(reason, "reason") DEF(globalThis, "globalThis") DEF(bigint, "bigint") +DEF(minus_zero, "-0") +DEF(Infinity, "Infinity") +DEF(minus_Infinity, "-Infinity") +DEF(NaN, "NaN") +DEF(hasIndices, "hasIndices") +DEF(ignoreCase, "ignoreCase") +DEF(multiline, "multiline") +DEF(dotAll, "dotAll") +DEF(sticky, "sticky") +DEF(unicodeSets, "unicodeSets") +/* the following 3 atoms are only used with CONFIG_ATOMICS */ DEF(not_equal, "not-equal") DEF(timed_out, "timed-out") DEF(ok, "ok") +/* */ DEF(toJSON, "toJSON") DEF(maxByteLength, "maxByteLength") /* class names */ @@ -218,7 +232,6 @@ DEF(Set, "Set") /* Map + 1 */ DEF(WeakMap, "WeakMap") /* Map + 2 */ DEF(WeakSet, "WeakSet") /* Map + 3 */ DEF(Iterator, "Iterator") -DEF(IteratorConcat, "Iterator Concat") DEF(IteratorHelper, "Iterator Helper") DEF(IteratorWrap, "Iterator Wrap") DEF(Map_Iterator, "Map Iterator") @@ -243,8 +256,7 @@ DEF(SyntaxError, "SyntaxError") DEF(TypeError, "TypeError") DEF(URIError, "URIError") DEF(InternalError, "InternalError") -DEF(DOMException, "DOMException") -DEF(CallSite, "CallSite") +DEF(AggregateError, "AggregateError") /* private symbols */ DEF(Private_brand, "") /* symbols */ diff --git a/quickjs-ng/quickjs-libc.c b/quickjs/quickjs-libc.c similarity index 77% rename from quickjs-ng/quickjs-libc.c rename to quickjs/quickjs-libc.c index c1d3f80..54a7a15 100644 --- a/quickjs-ng/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -22,90 +22,62 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "quickjs.h" #include #include #include #include #include #include +#include #include #include -#if !defined(_MSC_VER) #include -#include -#endif #include #include #include #include -#if !defined(_MSC_VER) #include -#endif #if defined(_WIN32) #include -#include -#include #include -#include -#include -#include -#define popen _popen -#define pclose _pclose -#define rmdir _rmdir -#define getcwd _getcwd -#define chdir _chdir +#include #else -#include -#include -#if !defined(__wasi__) #include #include -#include +#include #include -#include + +#if defined(__FreeBSD__) +extern char **environ; #endif -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__FreeBSD__) typedef sig_t sighandler_t; +#endif + +#if defined(__APPLE__) +#if !defined(environ) #include #define environ (*_NSGetEnviron()) #endif +#endif /* __APPLE__ */ -#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) -typedef sig_t sighandler_t; -extern char **environ; #endif -#endif /* _WIN32 */ +/* enable the os.Worker API. It relies on POSIX threads */ +#define USE_WORKER + +#ifdef USE_WORKER +#include +#include +#endif #include "cutils.h" #include "list.h" #include "quickjs-libc.h" -#if JS_HAVE_THREADS -#include "quickjs-c-atomics.h" -#define USE_WORKER // enable os.Worker -#endif - -#ifndef S_IFBLK -#define S_IFBLK 0 -#endif - -#ifndef S_IFIFO -#define S_IFIFO 0 -#endif - -#ifndef MAX_SAFE_INTEGER // already defined in amalgamation builds -#define MAX_SAFE_INTEGER (((int64_t) 1 << 53) - 1) -#endif - -#ifndef QJS_NATIVE_MODULE_SUFFIX -#ifdef _WIN32 -#define QJS_NATIVE_MODULE_SUFFIX ".dll" -#else -#define QJS_NATIVE_MODULE_SUFFIX ".so" -#endif +#if !defined(PATH_MAX) +#define PATH_MAX 4096 #endif /* TODO: @@ -126,21 +98,11 @@ typedef struct { typedef struct { struct list_head link; - int64_t timer_id; - uint8_t repeats:1; + int timer_id; int64_t timeout; - int64_t delay; JSValue func; } JSOSTimer; -typedef struct { - struct list_head link; - JSValue promise; - JSValue reason; -} JSRejectedPromiseEntry; - -#ifdef USE_WORKER - typedef struct { struct list_head link; uint8_t *data; @@ -161,7 +123,9 @@ typedef struct JSWaker { typedef struct { int ref_count; - js_mutex_t mutex; +#ifdef USE_WORKER + pthread_mutex_t mutex; +#endif struct list_head msg_queue; /* list of JSWorkerMessage.link */ JSWaker waker; } JSWorkerMessagePipe; @@ -172,7 +136,11 @@ typedef struct { JSValue on_message_func; } JSWorkerMessageHandler; -#endif // USE_WORKER +typedef struct { + struct list_head link; + JSValue promise; + JSValue reason; +} JSRejectedPromiseEntry; typedef struct JSThreadState { struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */ @@ -181,50 +149,25 @@ typedef struct JSThreadState { struct list_head port_list; /* list of JSWorkerMessageHandler.link */ struct list_head rejected_promise_list; /* list of JSRejectedPromiseEntry.link */ int eval_script_recurse; /* only used in the main thread */ - int64_t next_timer_id; /* for setTimeout / setInterval */ - bool can_js_os_poll; + int next_timer_id; /* for setTimeout() */ /* not used in the main thread */ -#ifdef USE_WORKER JSWorkerMessagePipe *recv_pipe, *send_pipe; -#else - void *recv_pipe; -#endif // USE_WORKER - JSClassID std_file_class_id; - JSClassID worker_class_id; } JSThreadState; static uint64_t os_pending_signals; - -static void *js_std_dbuf_realloc(void *opaque, void *ptr, size_t size) -{ - JSRuntime *rt = opaque; - return js_realloc_rt(rt, ptr, size); -} +static int (*os_poll_func)(JSContext *ctx); static void js_std_dbuf_init(JSContext *ctx, DynBuf *s) { - dbuf_init2(s, JS_GetRuntime(ctx), js_std_dbuf_realloc); + dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt); } -static bool my_isdigit(int c) +static BOOL my_isdigit(int c) { return (c >= '0' && c <= '9'); } -static JSThreadState *js_get_thread_state(JSRuntime *rt) -{ - return (JSThreadState *)js_std_cmd(/*GetOpaque*/0, rt); -} - -static void js_set_thread_state(JSRuntime *rt, JSThreadState *ts) -{ - js_std_cmd(/*SetOpaque*/1, rt, ts); -} - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif // __GNUC__ +/* XXX: use 'o' and 'O' for object using JS_PrintValue() ? */ static JSValue js_printf_internal(JSContext *ctx, int argc, JSValueConst *argv, FILE *fp) { @@ -242,6 +185,8 @@ static JSValue js_printf_internal(JSContext *ctx, int64_t int64_arg; double double_arg; const char *string_arg; + /* Use indirect call to dbuf_printf to prevent gcc warning */ + int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf; js_std_dbuf_init(ctx, &dbuf); @@ -328,21 +273,20 @@ static JSValue js_printf_internal(JSContext *ctx, if (i >= argc) goto missing; if (JS_IsString(argv[i])) { - // TODO(chqrlie) need an API to wrap charCodeAt and codePointAt */ string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; - int32_arg = utf8_decode((const uint8_t *)string_arg, &p); + int32_arg = unicode_from_utf8((const uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); JS_FreeCString(ctx, string_arg); } else { if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; } - // XXX: throw an exception? + /* handle utf-8 encoding explicitly */ if ((unsigned)int32_arg > 0x10FFFF) int32_arg = 0xFFFD; /* ignore conversion flags, width and precision */ - len = utf8_encode(cbuf, int32_arg); + len = unicode_to_utf8(cbuf, int32_arg); dbuf_put(&dbuf, cbuf, len); break; @@ -366,17 +310,17 @@ static JSValue js_printf_internal(JSContext *ctx, q[0] = '6'; q[1] = '4'; q[3] = '\0'; - dbuf_printf(&dbuf, fmtbuf, (int64_t)int64_arg); + dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg); #else if (q >= fmtbuf + sizeof(fmtbuf) - 2) goto invalid; q[1] = q[-1]; q[-1] = q[0] = 'l'; q[2] = '\0'; - dbuf_printf(&dbuf, fmtbuf, (long long)int64_arg); + dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg); #endif } else { - dbuf_printf(&dbuf, fmtbuf, (int)int64_arg); + dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg); } break; @@ -387,7 +331,7 @@ static JSValue js_printf_internal(JSContext *ctx, string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; - dbuf_printf(&dbuf, fmtbuf, string_arg); + dbuf_printf_fun(&dbuf, fmtbuf, string_arg); JS_FreeCString(ctx, string_arg); break; @@ -403,7 +347,7 @@ static JSValue js_printf_internal(JSContext *ctx, goto missing; if (JS_ToFloat64(ctx, &double_arg, argv[i++])) goto fail; - dbuf_printf(&dbuf, fmtbuf, double_arg); + dbuf_printf_fun(&dbuf, fmtbuf, double_arg); break; case '%': @@ -440,44 +384,49 @@ static JSValue js_printf_internal(JSContext *ctx, dbuf_free(&dbuf); return JS_EXCEPTION; } -#ifdef __GNUC__ -#pragma GCC diagnostic pop // ignored "-Wformat-nonliteral" -#endif // __GNUC__ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) { FILE *f; - size_t n, len; - uint8_t *p, *buf, tmp[8192]; + uint8_t *buf; + size_t buf_len; + long lret; f = fopen(filename, "rb"); if (!f) return NULL; - buf = NULL; - len = 0; - do { - n = fread(tmp, 1, sizeof(tmp), f); - if (ctx) { - p = js_realloc(ctx, buf, len + n + 1); - } else { - p = realloc(buf, len + n + 1); - } - if (!p) { - if (ctx) { - js_free(ctx, buf); - } else { - free(buf); - } - fclose(f); - return NULL; - } - memcpy(&p[len], tmp, n); - buf = p; - len += n; - buf[len] = '\0'; - } while (n == sizeof(tmp)); + if (fseek(f, 0, SEEK_END) < 0) + goto fail; + lret = ftell(f); + if (lret < 0) + goto fail; + /* XXX: on Linux, ftell() return LONG_MAX for directories */ + if (lret == LONG_MAX) { + errno = EISDIR; + goto fail; + } + buf_len = lret; + if (fseek(f, 0, SEEK_SET) < 0) + goto fail; + if (ctx) + buf = js_malloc(ctx, buf_len + 1); + else + buf = malloc(buf_len + 1); + if (!buf) + goto fail; + if (fread(buf, 1, buf_len, f) != buf_len) { + errno = EIO; + if (ctx) + js_free(ctx, buf); + else + free(buf); + fail: + fclose(f); + return NULL; + } + buf[buf_len] = '\0'; fclose(f); - *pbuf_len = len; + *pbuf_len = buf_len; return buf; } @@ -506,42 +455,14 @@ static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, return ret; } -static int get_bool_option(JSContext *ctx, bool *pbool, - JSValueConst obj, - const char *option) -{ - JSValue val; - val = JS_GetPropertyStr(ctx, obj, option); - if (JS_IsException(val)) - return -1; - if (!JS_IsUndefined(val)) { - *pbool = JS_ToBool(ctx, val); - } - JS_FreeValue(ctx, val); - return 0; -} - -static void free_buf(JSRuntime *rt, void *opaque, void *ptr) { - js_free_rt(rt, ptr); -} - -/* load a file as a UTF-8 encoded string or Uint8Array */ +/* load a file as a UTF-8 encoded string */ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { uint8_t *buf; const char *filename; - JSValueConst options_obj; JSValue ret; size_t buf_len; - bool binary = false; - - if (argc >= 2) { - options_obj = argv[1]; - if (get_bool_option(ctx, &binary, options_obj, - "binary")) - return JS_EXCEPTION; - } filename = JS_ToCString(ctx, argv[0]); if (!filename) @@ -550,74 +471,8 @@ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, filename); if (!buf) return JS_NULL; - if (binary) { - ret = JS_NewUint8Array(ctx, buf, buf_len, free_buf, NULL, false); - } else { - ret = JS_NewStringLen(ctx, (char *)buf, buf_len); - js_free(ctx, buf); - } - - return ret; -} - -static JSValue js_std_writeFile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *filename; - const char *mode; - const void *buf; - size_t len, n; - JSValueConst data; - JSValue val, ret, unref; - bool release; - FILE *fp; - - ret = JS_EXCEPTION; - len = 0; - buf = ""; - mode = "w"; - data = argv[1]; - unref = JS_UNDEFINED; - release = false; - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - return JS_EXCEPTION; - if (JS_IsObject(data)) { - val = JS_GetPropertyStr(ctx, data, "buffer"); - if (JS_IsException(val)) - goto exception; - if (JS_IsArrayBuffer(val)) { - data = unref = val; - } else { - JS_FreeValue(ctx, val); - } - } - if (JS_IsArrayBuffer(data)) { - buf = JS_GetArrayBuffer(ctx, &len, data); - mode = "wb"; - } else if (!JS_IsUndefined(data)) { - buf = JS_ToCStringLen(ctx, &len, data); - release = true; - } - if (!buf) - goto exception; - fp = fopen(filename, mode); - if (!fp) { - JS_ThrowPlainError(ctx, "error opening %s for writing", filename); - goto exception; - } - n = fwrite(buf, len, 1, fp); - fclose(fp); - if (n != 1) { - JS_ThrowPlainError(ctx, "error writing to %s", filename); - goto exception; - } - ret = JS_UNDEFINED; -exception: - JS_FreeCString(ctx, filename); - if (release) - JS_FreeCString(ctx, buf); - JS_FreeValue(ctx, unref); + ret = JS_NewStringLen(ctx, (char *)buf, buf_len); + js_free(ctx, buf); return ret; } @@ -626,52 +481,6 @@ typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, #if defined(_WIN32) -static JSModuleDef *js_module_loader_so(JSContext *ctx, - const char *module_name) -{ - JSModuleDef *m; - HINSTANCE hd; - JSInitModuleFunc *init; - char *filename = NULL; - size_t len = strlen(module_name); - bool is_absolute = len > 2 && ((module_name[0] >= 'A' && module_name[0] <= 'Z') || - (module_name[0] >= 'a' && module_name[0] <= 'z')) && module_name[1] == ':'; - bool is_relative = len > 2 && module_name[0] == '.' && (module_name[1] == '/' || module_name[1] == '\\'); - if (is_absolute || is_relative) { - filename = (char *)module_name; - } else { - filename = js_malloc(ctx, len + 2 + 1); - if (!filename) - return NULL; - strcpy(filename, "./"); - strcpy(filename + 2, module_name); - } - hd = LoadLibraryA(filename); - if (filename != module_name) - js_free(ctx, filename); - if (hd == NULL) { - JS_ThrowReferenceError(ctx, "js_load_module '%s' error: %lu", - module_name, GetLastError()); - goto fail; - } - init = (JSInitModuleFunc *)(uintptr_t)GetProcAddress(hd, "js_init_module"); - if (!init) { - JS_ThrowReferenceError(ctx, "js_init_module '%s' not found: %lu", - module_name, GetLastError()); - goto fail; - } - m = init(ctx, module_name); - if (!m) { - JS_ThrowReferenceError(ctx, "js_call_module '%s' initialization error", - module_name); - fail: - if (hd != NULL) - FreeLibrary(hd); - return NULL; - } - return m; -} -#elif defined(__wasi__) static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name) { @@ -704,12 +513,12 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, if (filename != module_name) js_free(ctx, filename); if (!hd) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library: %s", - module_name, dlerror()); + JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library", + module_name); goto fail; } - *(void **) (&init) = dlsym(hd, "js_init_module"); + init = dlsym(hd, "js_init_module"); if (!init) { JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found", module_name); @@ -730,10 +539,10 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, #endif /* !_WIN32 */ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, - bool use_realpath, bool is_main) + JS_BOOL use_realpath, JS_BOOL is_main) { JSModuleDef *m; - char buf[JS__PATH_MAX + 16]; + char buf[PATH_MAX + 16]; JSValue meta_obj; JSAtom module_name_atom; const char *module_name; @@ -748,7 +557,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, return -1; if (!strchr(module_name, ':')) { strcpy(buf, "file://"); -#if !defined(_WIN32) && !defined(__wasi__) +#if !defined(_WIN32) /* realpath() cannot be used with modules compiled with qjsc because the corresponding module source code is not necessarily present */ @@ -762,10 +571,10 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, } else #endif { - js__pstrcat(buf, sizeof(buf), module_name); + pstrcat(buf, sizeof(buf), module_name); } } else { - js__pstrcpy(buf, sizeof(buf), module_name); + pstrcpy(buf, sizeof(buf), module_name); } JS_FreeCString(ctx, module_name); @@ -782,17 +591,101 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, return 0; } -JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque) +static int json_module_init(JSContext *ctx, JSModuleDef *m) +{ + JSValue val; + val = JS_GetModulePrivateValue(ctx, m); + JS_SetModuleExport(ctx, m, "default", val); + return 0; +} + +static JSModuleDef *create_json_module(JSContext *ctx, const char *module_name, JSValue val) { JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, json_module_init); + if (!m) { + JS_FreeValue(ctx, val); + return NULL; + } + /* only export the "default" symbol which will contain the JSON object */ + JS_AddModuleExport(ctx, m, "default"); + JS_SetModulePrivateValue(ctx, m, val); + return m; +} + +/* in order to conform with the specification, only the keys should be + tested and not the associated values. */ +int js_module_check_attributes(JSContext *ctx, void *opaque, + JSValueConst attributes) +{ + JSPropertyEnum *tab; + uint32_t i, len; + int ret; + const char *cstr; + size_t cstr_len; + + if (JS_GetOwnPropertyNames(ctx, &tab, &len, attributes, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK)) + return -1; + ret = 0; + for(i = 0; i < len; i++) { + cstr = JS_AtomToCStringLen(ctx, &cstr_len, tab[i].atom); + if (!cstr) { + ret = -1; + break; + } + if (!(cstr_len == 4 && !memcmp(cstr, "type", cstr_len))) { + JS_ThrowTypeError(ctx, "import attribute '%s' is not supported", cstr); + ret = -1; + } + JS_FreeCString(ctx, cstr); + if (ret) + break; + } + JS_FreePropertyEnum(ctx, tab, len); + return ret; +} - if (js__has_suffix(module_name, QJS_NATIVE_MODULE_SUFFIX)) { +/* return > 0 if the attributes indicate a JSON module */ +int js_module_test_json(JSContext *ctx, JSValueConst attributes) +{ + JSValue str; + const char *cstr; + size_t len; + BOOL res; + + if (JS_IsUndefined(attributes)) + return FALSE; + str = JS_GetPropertyStr(ctx, attributes, "type"); + if (!JS_IsString(str)) + return FALSE; + cstr = JS_ToCStringLen(ctx, &len, str); + JS_FreeValue(ctx, str); + if (!cstr) + return FALSE; + /* XXX: raise an error if unknown type ? */ + if (len == 4 && !memcmp(cstr, "json", len)) { + res = 1; + } else if (len == 5 && !memcmp(cstr, "json5", len)) { + res = 2; + } else { + res = 0; + } + JS_FreeCString(ctx, cstr); + return res; +} + +JSModuleDef *js_module_loader(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes) +{ + JSModuleDef *m; + int res; + + if (has_suffix(module_name, ".so")) { m = js_module_loader_so(ctx, module_name); } else { size_t buf_len; uint8_t *buf; - JSValue func_val; buf = js_load_file(ctx, &buf_len, module_name); if (!buf) { @@ -800,20 +693,36 @@ JSModuleDef *js_module_loader(JSContext *ctx, module_name); return NULL; } - - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - if (js_module_set_import_meta(ctx, func_val, true, false) < 0) { + res = js_module_test_json(ctx, attributes); + if (has_suffix(module_name, ".json") || res > 0) { + /* compile as JSON or JSON5 depending on "type" */ + JSValue val; + int flags; + if (res == 2) + flags = JS_PARSE_JSON_EXT; + else + flags = 0; + val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags); + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + m = create_json_module(ctx, module_name, val); + if (!m) + return NULL; + } else { + JSValue func_val; + /* compile the module */ + func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + js_free(ctx, buf); + if (JS_IsException(func_val)) + return NULL; + /* XXX: could propagate the exception */ + js_module_set_import_meta(ctx, func_val, TRUE, FALSE); + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(func_val); JS_FreeValue(ctx, func_val); - return NULL; } - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); } return m; } @@ -829,7 +738,7 @@ static JSValue js_std_exit(JSContext *ctx, JSValueConst this_val, } static JSValue js_std_getenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { const char *name, *str; name = JS_ToCString(ctx, argv[0]); @@ -861,12 +770,12 @@ static void setenv(const char *name, const char *value, int overwrite) static void unsetenv(const char *name) { - setenv(name, "", true); + setenv(name, "", TRUE); } #endif /* _WIN32 */ static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { const char *name, *value; name = JS_ToCString(ctx, argv[0]); @@ -877,7 +786,7 @@ static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, name); return JS_EXCEPTION; } - setenv(name, value, true); + setenv(name, value, TRUE); JS_FreeCString(ctx, name); JS_FreeCString(ctx, value); return JS_UNDEFINED; @@ -946,21 +855,32 @@ static int interrupt_handler(JSRuntime *rt, void *opaque) return (os_pending_signals >> SIGINT) & 1; } +static int get_bool_option(JSContext *ctx, BOOL *pbool, + JSValueConst obj, + const char *option) +{ + JSValue val; + val = JS_GetPropertyStr(ctx, obj, option); + if (JS_IsException(val)) + return -1; + if (!JS_IsUndefined(val)) { + *pbool = JS_ToBool(ctx, val); + } + JS_FreeValue(ctx, val); + return 0; +} + static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - const char *str = NULL; + JSThreadState *ts = JS_GetRuntimeOpaque(rt); + const char *str; size_t len; - JSValue ret, obj; - JSValueConst options_obj, arg; - bool backtrace_barrier = false; - bool eval_function = false; - bool eval_module = false; - bool compile_only = false; - bool compile_module = false; - bool is_async = false; + JSValue ret; + JSValueConst options_obj; + BOOL backtrace_barrier = FALSE; + BOOL is_async = FALSE; int flags; if (argc >= 2) { @@ -968,59 +888,24 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, if (get_bool_option(ctx, &backtrace_barrier, options_obj, "backtrace_barrier")) return JS_EXCEPTION; - if (get_bool_option(ctx, &eval_function, options_obj, - "eval_function")) - return JS_EXCEPTION; - if (get_bool_option(ctx, &eval_module, options_obj, - "eval_module")) - return JS_EXCEPTION; - if (get_bool_option(ctx, &compile_only, options_obj, - "compile_only")) - return JS_EXCEPTION; - if (get_bool_option(ctx, &compile_module, options_obj, - "compile_module")) - return JS_EXCEPTION; if (get_bool_option(ctx, &is_async, options_obj, "async")) return JS_EXCEPTION; } - if (eval_module) { - arg = argv[0]; - if (JS_VALUE_GET_TAG(arg) != JS_TAG_MODULE) - return JS_ThrowTypeError(ctx, "not a module"); - - if (JS_ResolveModule(ctx, arg) < 0) - return JS_EXCEPTION; - - if (js_module_set_import_meta(ctx, arg, false, false) < 0) - return JS_EXCEPTION; - - return JS_EvalFunction(ctx, JS_DupValue(ctx, arg)); - } - - if (!eval_function) { - str = JS_ToCStringLen(ctx, &len, argv[0]); - if (!str) - return JS_EXCEPTION; - } + str = JS_ToCStringLen(ctx, &len, argv[0]); + if (!str) + return JS_EXCEPTION; if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) { /* install the interrupt handler */ JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL); } - flags = compile_module ? JS_EVAL_TYPE_MODULE : JS_EVAL_TYPE_GLOBAL; + flags = JS_EVAL_TYPE_GLOBAL; if (backtrace_barrier) flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER; - if (compile_only) - flags |= JS_EVAL_FLAG_COMPILE_ONLY; if (is_async) flags |= JS_EVAL_FLAG_ASYNC; - if (eval_function) { - obj = JS_DupValue(ctx, argv[0]); - ret = JS_EvalFunction(ctx, obj); // takes ownership of |obj| - } else { - ret = JS_Eval(ctx, str, len, "", flags); - } + ret = JS_Eval(ctx, str, len, "", flags); JS_FreeCString(ctx, str); if (!ts->recv_pipe && --ts->eval_script_recurse == 0) { /* remove the interrupt handler */ @@ -1029,32 +914,27 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, /* convert the uncatchable "interrupted" error into a normal error so that it can be caught by the REPL */ if (JS_IsException(ret)) - JS_ResetUncatchableError(ctx); + JS_SetUncatchableException(ctx, FALSE); } return ret; } +static JSClassID js_std_file_class_id; + typedef struct { FILE *f; - bool is_popen; + BOOL close_in_finalizer; + BOOL is_popen; } JSSTDFile; -static bool is_stdio(FILE *f) +static void js_std_file_finalizer(JSRuntime *rt, JSValue val) { - return f == stdin || f == stdout || f == stderr; -} - -static void js_std_file_finalizer(JSRuntime *rt, JSValueConst val) -{ - JSThreadState *ts = js_get_thread_state(rt); - JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id); + JSSTDFile *s = JS_GetOpaque(val, js_std_file_class_id); if (s) { - if (s->f && !is_stdio(s->f)) { -#if !defined(__wasi__) + if (s->f && s->close_in_finalizer) { if (s->is_popen) pclose(s->f); else -#endif fclose(s->f); } js_free_rt(rt, s); @@ -1069,7 +949,7 @@ static ssize_t js_get_errno(ssize_t ret) } static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { int err; if (JS_ToInt32(ctx, &err, argv[0])) @@ -1077,13 +957,28 @@ static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, return JS_NewString(ctx, strerror(err)); } -static JSValue js_new_std_file(JSContext *ctx, FILE *f, bool is_popen) +static JSValue js_std_parseExtJSON(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue obj; + const char *str; + size_t len; + + str = JS_ToCStringLen(ctx, &len, argv[0]); + if (!str) + return JS_EXCEPTION; + obj = JS_ParseJSON2(ctx, str, len, "", JS_PARSE_JSON_EXT); + JS_FreeCString(ctx, str); + return obj; +} + +static JSValue js_new_std_file(JSContext *ctx, FILE *f, + BOOL close_in_finalizer, + BOOL is_popen) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s; JSValue obj; - obj = JS_NewObjectClass(ctx, ts->std_file_class_id); + obj = JS_NewObjectClass(ctx, js_std_file_class_id); if (JS_IsException(obj)) return obj; s = js_mallocz(ctx, sizeof(*s)); @@ -1091,13 +986,14 @@ static JSValue js_new_std_file(JSContext *ctx, FILE *f, bool is_popen) JS_FreeValue(ctx, obj); return JS_EXCEPTION; } + s->close_in_finalizer = close_in_finalizer; s->is_popen = is_popen; s->f = f; JS_SetOpaque(obj, s); return obj; } -static void js_set_error_object(JSContext *ctx, JSValueConst obj, int err) +static void js_set_error_object(JSContext *ctx, JSValue obj, int err) { if (!JS_IsUndefined(obj)) { JS_SetPropertyStr(ctx, obj, "errno", JS_NewInt32(ctx, err)); @@ -1117,7 +1013,7 @@ static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, mode = JS_ToCString(ctx, argv[1]); if (!mode) goto fail; - if (mode[strspn(mode, "rwa+bx")] != '\0') { + if (mode[strspn(mode, "rwa+b")] != '\0') { JS_ThrowTypeError(ctx, "invalid file mode"); goto fail; } @@ -1133,14 +1029,13 @@ static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, mode); if (!f) return JS_NULL; - return js_new_std_file(ctx, f, false); + return js_new_std_file(ctx, f, TRUE, FALSE); fail: JS_FreeCString(ctx, filename); JS_FreeCString(ctx, mode); return JS_EXCEPTION; } -#if !defined(__wasi__) static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1154,7 +1049,7 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, mode = JS_ToCString(ctx, argv[1]); if (!mode) goto fail; - if (strcmp(mode, "r") && strcmp(mode, "w")) { + if (mode[strspn(mode, "rw")] != '\0') { JS_ThrowTypeError(ctx, "invalid file mode"); goto fail; } @@ -1170,13 +1065,12 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, mode); if (!f) return JS_NULL; - return js_new_std_file(ctx, f, true); + return js_new_std_file(ctx, f, TRUE, TRUE); fail: JS_FreeCString(ctx, filename); JS_FreeCString(ctx, mode); return JS_EXCEPTION; } -#endif // !defined(__wasi__) static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -1205,13 +1099,12 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, mode); if (!f) return JS_NULL; - return js_new_std_file(ctx, f, false); + return js_new_std_file(ctx, f, TRUE, FALSE); fail: JS_FreeCString(ctx, mode); return JS_EXCEPTION; } -#if !defined(__wasi__) static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1221,12 +1114,11 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, js_set_error_object(ctx, argv[0], f ? 0 : errno); if (!f) return JS_NULL; - return js_new_std_file(ctx, f, false); + return js_new_std_file(ctx, f, TRUE, FALSE); } -#endif static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { return js_printf_internal(ctx, argc, argv, NULL); } @@ -1239,9 +1131,7 @@ static JSValue js_std_printf(JSContext *ctx, JSValueConst this_val, static FILE *js_std_file_get(JSContext *ctx, JSValueConst obj) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSSTDFile *s = JS_GetOpaque2(ctx, obj, ts->std_file_class_id); + JSSTDFile *s = JS_GetOpaque2(ctx, obj, js_std_file_class_id); if (!s) return NULL; if (!s->f) { @@ -1280,21 +1170,15 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val, static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSSTDFile *s = JS_GetOpaque2(ctx, this_val, ts->std_file_class_id); + JSSTDFile *s = JS_GetOpaque2(ctx, this_val, js_std_file_class_id); int err; if (!s) return JS_EXCEPTION; if (!s->f) return JS_ThrowTypeError(ctx, "invalid file handle"); - if (is_stdio(s->f)) - return JS_ThrowTypeError(ctx, "cannot close stdio"); -#if !defined(__wasi__) if (s->is_popen) err = js_get_errno(pclose(s->f)); else -#endif err = js_get_errno(fclose(s->f)); s->f = NULL; return JS_NewInt32(ctx, err); @@ -1309,6 +1193,19 @@ static JSValue js_std_file_printf(JSContext *ctx, JSValueConst this_val, return js_printf_internal(ctx, argc, argv, f); } +static void js_print_value_write(void *opaque, const char *buf, size_t len) +{ + FILE *fo = opaque; + fwrite(buf, 1, len, fo); +} + +static JSValue js_std_file_printObject(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JS_PrintValue(ctx, js_print_value_write, stdout, argv[0], NULL); + return JS_UNDEFINED; +} + static JSValue js_std_file_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1369,7 +1266,7 @@ static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val, } static JSValue js_std_file_error(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1459,8 +1356,8 @@ static JSValue js_std_file_getline(JSContext *ctx, JSValueConst this_val, } /* XXX: could use less memory and go faster */ -static JSValue js_std_file_readAs(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_std_file_readAsString(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) { FILE *f = js_std_file_get(ctx, this_val); int c; @@ -1496,11 +1393,7 @@ static JSValue js_std_file_readAs(JSContext *ctx, JSValueConst this_val, } max_size--; } - if (magic) { - obj = JS_NewStringLen(ctx, (const char *)dbuf.buf, dbuf.size); - } else { - obj = JS_NewArrayBufferCopy(ctx, dbuf.buf, dbuf.size); - } + obj = JS_NewStringLen(ctx, (const char *)dbuf.buf, dbuf.size); dbuf_free(&dbuf); return obj; } @@ -1528,7 +1421,6 @@ static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, } /* urlGet */ -#if !defined(__wasi__) #define URL_GET_PROGRAM "curl -s -i --" #define URL_GET_BUF_SIZE 4096 @@ -1580,14 +1472,14 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, JSValue response = JS_UNDEFINED, ret_obj; JSValueConst options_obj; FILE *f; - bool binary_flag, full_flag; + BOOL binary_flag, full_flag; url = JS_ToCString(ctx, argv[0]); if (!url) return JS_EXCEPTION; - binary_flag = false; - full_flag = false; + binary_flag = FALSE; + full_flag = FALSE; if (argc >= 2) { options_obj = argv[1]; @@ -1722,7 +1614,6 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, response); return JS_EXCEPTION; } -#endif // !defined(__wasi__) static JSClassDef js_std_file_class = { "FILE", @@ -1755,20 +1646,16 @@ static const JSCFunctionListEntry js_std_funcs[] = { JS_CFUNC_DEF("setenv", 1, js_std_setenv ), JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ), JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ), -#if !defined(__wasi__) JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ), -#endif JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ), - JS_CFUNC_DEF("writeFile", 2, js_std_writeFile ), JS_CFUNC_DEF("strerror", 1, js_std_strerror ), + JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ), /* FILE I/O */ JS_CFUNC_DEF("open", 2, js_std_open ), -#if !defined(__wasi__) JS_CFUNC_DEF("popen", 2, js_std_popen ), - JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), -#endif JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ), + JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ), JS_CFUNC_DEF("printf", 1, js_std_printf ), JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ), @@ -1776,6 +1663,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ), JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ), JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE), + JS_CFUNC_DEF("__printObject", 1, js_std_file_printObject ), }; static const JSCFunctionListEntry js_std_file_proto_funcs[] = { @@ -1793,8 +1681,7 @@ static const JSCFunctionListEntry js_std_file_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("read", 3, js_std_file_read_write, 0 ), JS_CFUNC_MAGIC_DEF("write", 3, js_std_file_read_write, 1 ), JS_CFUNC_DEF("getline", 0, js_std_file_getline ), - JS_CFUNC_MAGIC_DEF("readAsArrayBuffer", 0, js_std_file_readAs, 0 ), - JS_CFUNC_MAGIC_DEF("readAsString", 0, js_std_file_readAs, 1 ), + JS_CFUNC_DEF("readAsString", 0, js_std_file_readAsString ), JS_CFUNC_DEF("getByte", 0, js_std_file_getByte ), JS_CFUNC_DEF("putByte", 1, js_std_file_putByte ), /* setvbuf, ... */ @@ -1803,24 +1690,22 @@ static const JSCFunctionListEntry js_std_file_proto_funcs[] = { static int js_std_init(JSContext *ctx, JSModuleDef *m) { JSValue proto; - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); /* FILE class */ /* the class ID is created once */ - JS_NewClassID(rt, &ts->std_file_class_id); + JS_NewClassID(&js_std_file_class_id); /* the class is created once per runtime */ - JS_NewClass(rt, ts->std_file_class_id, &js_std_file_class); + JS_NewClass(JS_GetRuntime(ctx), js_std_file_class_id, &js_std_file_class); proto = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, proto, js_std_file_proto_funcs, countof(js_std_file_proto_funcs)); - JS_SetClassProto(ctx, ts->std_file_class_id, proto); + JS_SetClassProto(ctx, js_std_file_class_id, proto); JS_SetModuleExportList(ctx, m, js_std_funcs, countof(js_std_funcs)); - JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, false)); - JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, false)); - JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, false)); + JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE, FALSE)); + JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE, FALSE)); + JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE, FALSE)); return 0; } @@ -1885,11 +1770,11 @@ static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val, { int fd, whence; int64_t pos, ret; - bool is_bigint; + BOOL is_bigint; if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; - is_bigint = JS_IsBigInt(argv[1]); + is_bigint = JS_IsBigInt(ctx, argv[1]); if (JS_ToInt64Ext(ctx, &pos, argv[1])) return JS_EXCEPTION; if (JS_ToInt32(ctx, &whence, argv[2])) @@ -1936,7 +1821,7 @@ static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, int fd; if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; - return JS_NewBool(ctx, (isatty(fd) != 0)); + return JS_NewBool(ctx, isatty(fd)); } #if defined(_WIN32) @@ -1983,7 +1868,7 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, } return JS_UNDEFINED; } -#elif !defined(__wasi__) +#else static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -2042,10 +1927,10 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -#endif /* !_WIN32 && !__wasi__ */ +#endif /* !_WIN32 */ static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { const char *filename; int ret; @@ -2056,7 +1941,7 @@ static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, #if defined(_WIN32) { struct stat st; - if (stat(filename, &st) == 0 && (st.st_mode & _S_IFDIR)) { + if (stat(filename, &st) == 0 && S_ISDIR(st.st_mode)) { ret = rmdir(filename); } else { ret = unlink(filename); @@ -2090,9 +1975,9 @@ static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, ret); } -static bool is_main_thread(JSRuntime *rt) +static BOOL is_main_thread(JSRuntime *rt) { - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); return !ts->recv_pipe; } @@ -2123,7 +2008,7 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); JSOSRWHandler *rh; int fd; JSValueConst func; @@ -2193,7 +2078,7 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); JSOSSignalHandler *sh; uint32_t sig_num; JSValueConst func; @@ -2236,40 +2121,41 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -#if !defined(_WIN32) && !defined(__wasi__) -static JSValue js_os_cputime(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#if defined(__linux__) || defined(__APPLE__) +static int64_t get_time_ms(void) { - struct rusage ru; - int64_t cputime; - - cputime = 0; - if (!getrusage(RUSAGE_SELF, &ru)) - cputime = (int64_t)ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; - - return JS_NewInt64(ctx, cputime); + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000); } -#endif -static JSValue js_os_exepath(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static int64_t get_time_ns(void) { - char buf[JS__PATH_MAX]; - size_t len = sizeof(buf); - if (js_exepath(buf, &len)) - return JS_UNDEFINED; - return JS_NewStringLen(ctx, buf, len); + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec; +} +#else +/* more portable, but does not work if the date is updated */ +static int64_t get_time_ms(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000); } -static JSValue js_os_now(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static int64_t get_time_ns(void) { - return JS_NewInt64(ctx, js__hrtime_ns() / 1000); + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec * 1000000000 + (tv.tv_usec * 1000); } +#endif -static uint64_t js__hrtime_ms(void) +static JSValue js_os_now(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - return js__hrtime_ns() / (1000 * 1000); + return JS_NewFloat64(ctx, (double)get_time_ns() / 1e6); } static void free_timer(JSRuntime *rt, JSOSTimer *th) @@ -2279,13 +2165,11 @@ static void free_timer(JSRuntime *rt, JSOSTimer *th) js_free_rt(rt, th); } -// TODO(bnoordhuis) accept string as first arg and eval at timer expiry -// TODO(bnoordhuis) retain argv[2..] as args for callback if argc > 2 static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) + int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); int64_t delay; JSValueConst func; JSOSTimer *th; @@ -2295,20 +2179,18 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeError(ctx, "not a function"); if (JS_ToInt64(ctx, &delay, argv[1])) return JS_EXCEPTION; - if (delay < 1) - delay = 1; th = js_mallocz(ctx, sizeof(*th)); if (!th) return JS_EXCEPTION; - th->timer_id = ts->next_timer_id++; - if (ts->next_timer_id > MAX_SAFE_INTEGER) + th->timer_id = ts->next_timer_id; + if (ts->next_timer_id == INT32_MAX) ts->next_timer_id = 1; - th->repeats = (magic > 0); - th->timeout = js__hrtime_ms() + delay; - th->delay = delay; + else + ts->next_timer_id++; + th->timeout = get_time_ms() + delay; th->func = JS_DupValue(ctx, func); list_add_tail(&th->link, &ts->os_timers); - return JS_NewInt64(ctx, th->timer_id); + return JS_NewInt32(ctx, th->timer_id); } static JSOSTimer *find_timer_by_id(JSThreadState *ts, int timer_id) @@ -2328,11 +2210,11 @@ static JSValue js_os_clearTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); JSOSTimer *th; - int64_t timer_id; + int timer_id; - if (JS_ToInt64(ctx, &timer_id, argv[0])) + if (JS_ToInt32(ctx, &timer_id, argv[0])) return JS_EXCEPTION; th = find_timer_by_id(ts, timer_id); if (!th) @@ -2346,7 +2228,7 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); int64_t delay; JSOSTimer *th; JSValue promise, resolving_funcs[2]; @@ -2365,7 +2247,7 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } th->timer_id = -1; - th->timeout = js__hrtime_ms() + delay; + th->timeout = get_time_ms() + delay; th->func = JS_DupValue(ctx, resolving_funcs[0]); list_add_tail(&th->link, &ts->os_timers); JS_FreeValue(ctx, resolving_funcs[0]); @@ -2373,57 +2255,17 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, return promise; } -static int call_handler(JSContext *ctx, JSValue func) +static void call_handler(JSContext *ctx, JSValueConst func) { - int r; JSValue ret, func1; /* 'func' might be destroyed when calling itself (if it frees the - handler), so must take extra care */ - func1 = JS_DupValue(ctx, func); - ret = JS_Call(ctx, func1, JS_UNDEFINED, 0, NULL); - JS_FreeValue(ctx, func1); - r = 0; - if (JS_IsException(ret)) - r = -1; - JS_FreeValue(ctx, ret); - return r; -} - -static int js_os_run_timers(JSRuntime *rt, JSContext *ctx, JSThreadState *ts, int *min_delay) -{ - JSValue func; - JSOSTimer *th; - int64_t cur_time, delay; - struct list_head *el; - int r; - - if (list_empty(&ts->os_timers)) { - *min_delay = -1; - return 0; - } - - cur_time = js__hrtime_ms(); - *min_delay = INT32_MAX; - - list_for_each(el, &ts->os_timers) { - th = list_entry(el, JSOSTimer, link); - delay = th->timeout - cur_time; - if (delay > 0) { - *min_delay = min_int(*min_delay, delay); - } else { - *min_delay = 0; - func = JS_DupValueRT(rt, th->func); - if (th->repeats) - th->timeout = cur_time + th->delay; - else - free_timer(rt, th); - r = call_handler(ctx, func); - JS_FreeValueRT(rt, func); - return r; - } - } - - return 0; + handler), so must take extra care */ + func1 = JS_DupValue(ctx, func); + ret = JS_Call(ctx, func1, JS_UNDEFINED, 0, NULL); + JS_FreeValue(ctx, func1); + if (JS_IsException(ret)) + js_std_dump_error(ctx); + JS_FreeValue(ctx, ret); } #ifdef USE_WORKER @@ -2514,7 +2356,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, JSWorkerMessage *msg; JSValue obj, data_obj, func, retval; - js_mutex_lock(&ps->mutex); + pthread_mutex_lock(&ps->mutex); if (!list_empty(&ps->msg_queue)) { el = ps->msg_queue.next; msg = list_entry(el, JSWorkerMessage, link); @@ -2522,11 +2364,10 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, /* remove the message from the queue */ list_del(&msg->link); - // drain read end of pipe if (list_empty(&ps->msg_queue)) js_waker_clear(&ps->waker); - js_mutex_unlock(&ps->mutex); + pthread_mutex_unlock(&ps->mutex); data_obj = JS_ReadObject(ctx, msg->data, msg->data_len, JS_READ_OBJ_SAB | JS_READ_OBJ_REFERENCE); @@ -2556,41 +2397,69 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, } ret = 1; } else { - js_mutex_unlock(&ps->mutex); + pthread_mutex_unlock(&ps->mutex); ret = 0; } return ret; } - -#endif // USE_WORKER +#else +static int handle_posted_message(JSRuntime *rt, JSContext *ctx, + JSWorkerMessageHandler *port) +{ + return 0; +} +#endif /* !USE_WORKER */ #if defined(_WIN32) + static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); int min_delay, count; + int64_t cur_time, delay; JSOSRWHandler *rh; struct list_head *el; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; // 64 /* XXX: handle signals if useful */ - if (js_os_run_timers(rt, ctx, ts, &min_delay)) - return -1; - if (min_delay == 0) - return 0; // expired timer - if (min_delay < 0) - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) - return -1; /* no more events */ + if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) && + list_empty(&ts->port_list)) { + return -1; /* no more events */ + } + + if (!list_empty(&ts->os_timers)) { + cur_time = get_time_ms(); + min_delay = 10000; + list_for_each(el, &ts->os_timers) { + JSOSTimer *th = list_entry(el, JSOSTimer, link); + delay = th->timeout - cur_time; + if (delay <= 0) { + JSValue func; + /* the timer expired */ + func = th->func; + th->func = JS_UNDEFINED; + free_timer(rt, th); + call_handler(ctx, func); + JS_FreeValue(ctx, func); + return 0; + } else if (delay < min_delay) { + min_delay = delay; + } + } + } else { + min_delay = -1; + } count = 0; list_for_each(el, &ts->os_rw_handlers) { rh = list_entry(el, JSOSRWHandler, link); - if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) + if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) { handles[count++] = (HANDLE)_get_osfhandle(rh->fd); // stdin - if (count == (int)countof(handles)) - break; + if (count == (int)countof(handles)) + break; + } } list_for_each(el, &ts->port_list) { @@ -2607,12 +2476,14 @@ static int js_os_poll(JSContext *ctx) if (min_delay != -1) timeout = min_delay; ret = WaitForMultipleObjects(count, handles, FALSE, timeout); + if (ret < count) { list_for_each(el, &ts->os_rw_handlers) { rh = list_entry(el, JSOSRWHandler, link); if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) { - return call_handler(ctx, rh->rw_func[0]); + call_handler(ctx, rh->rw_func[0]); /* must stop because the list may have been modified */ + goto done; } } @@ -2630,18 +2501,22 @@ static int js_os_poll(JSContext *ctx) } else { Sleep(min_delay); } -done: + done: return 0; } -#else // !defined(_WIN32) + +#else + static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - int r, w, ret, nfds, min_delay; + JSThreadState *ts = JS_GetRuntimeOpaque(rt); + int ret, fd_max, min_delay; + int64_t cur_time, delay; + fd_set rfds, wfds; JSOSRWHandler *rh; struct list_head *el; - struct pollfd *pfd, *pfds, pfds_local[64]; + struct timeval tv, *tvp; /* only check signals in the main thread */ if (!ts->recv_pipe && @@ -2654,99 +2529,96 @@ static int js_os_poll(JSContext *ctx) mask = (uint64_t)1 << sh->sig_num; if (os_pending_signals & mask) { os_pending_signals &= ~mask; - return call_handler(ctx, sh->func); + call_handler(ctx, sh->func); + return 0; } } } - if (js_os_run_timers(rt, ctx, ts, &min_delay)) - return -1; - if (min_delay == 0) - return 0; // expired timer - if (min_delay < 0) - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) - return -1; /* no more events */ - - nfds = 0; - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - nfds += (!JS_IsNull(rh->rw_func[0]) || !JS_IsNull(rh->rw_func[1])); - } - -#ifdef USE_WORKER - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - nfds += !JS_IsNull(port->on_message_func); - } -#endif // USE_WORKER - - pfd = pfds = pfds_local; - if (nfds > (int)countof(pfds_local)) { - pfd = pfds = js_malloc(ctx, nfds * sizeof(*pfd)); - if (!pfd) - return -1; + if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) && + list_empty(&ts->port_list)) + return -1; /* no more events */ + + if (!list_empty(&ts->os_timers)) { + cur_time = get_time_ms(); + min_delay = 10000; + list_for_each(el, &ts->os_timers) { + JSOSTimer *th = list_entry(el, JSOSTimer, link); + delay = th->timeout - cur_time; + if (delay <= 0) { + JSValue func; + /* the timer expired */ + func = th->func; + th->func = JS_UNDEFINED; + free_timer(rt, th); + call_handler(ctx, func); + JS_FreeValue(ctx, func); + return 0; + } else if (delay < min_delay) { + min_delay = delay; + } + } + tv.tv_sec = min_delay / 1000; + tv.tv_usec = (min_delay % 1000) * 1000; + tvp = &tv; + } else { + tvp = NULL; } + FD_ZERO(&rfds); + FD_ZERO(&wfds); + fd_max = -1; list_for_each(el, &ts->os_rw_handlers) { rh = list_entry(el, JSOSRWHandler, link); - r = POLLIN * !JS_IsNull(rh->rw_func[0]); - w = POLLOUT * !JS_IsNull(rh->rw_func[1]); - if (r || w) - *pfd++ = (struct pollfd){rh->fd, r|w, 0}; + fd_max = max_int(fd_max, rh->fd); + if (!JS_IsNull(rh->rw_func[0])) + FD_SET(rh->fd, &rfds); + if (!JS_IsNull(rh->rw_func[1])) + FD_SET(rh->fd, &wfds); } -#ifdef USE_WORKER list_for_each(el, &ts->port_list) { JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); if (!JS_IsNull(port->on_message_func)) { JSWorkerMessagePipe *ps = port->recv_pipe; - *pfd++ = (struct pollfd){ps->waker.read_fd, POLLIN, 0}; + fd_max = max_int(fd_max, ps->waker.read_fd); + FD_SET(ps->waker.read_fd, &rfds); } } -#endif // USE_WORKER - // FIXME(bnoordhuis) the loop below is quadratic in theory but - // linear-ish in practice because we bail out on the first hit, - // i.e., it's probably good enough for now - ret = 0; - nfds = poll(pfds, nfds, min_delay); - for (pfd = pfds; nfds-- > 0; pfd++) { - rh = find_rh(ts, pfd->fd); - if (rh) { - r = (POLLERR|POLLHUP|POLLNVAL|POLLIN) * !JS_IsNull(rh->rw_func[0]); - w = (POLLERR|POLLHUP|POLLNVAL|POLLOUT) * !JS_IsNull(rh->rw_func[1]); - if (r & pfd->revents) { - ret = call_handler(ctx, rh->rw_func[0]); - goto done; + ret = select(fd_max + 1, &rfds, &wfds, NULL, tvp); + if (ret > 0) { + list_for_each(el, &ts->os_rw_handlers) { + rh = list_entry(el, JSOSRWHandler, link); + if (!JS_IsNull(rh->rw_func[0]) && + FD_ISSET(rh->fd, &rfds)) { + call_handler(ctx, rh->rw_func[0]); /* must stop because the list may have been modified */ - } - if (w & pfd->revents) { - ret = call_handler(ctx, rh->rw_func[1]); goto done; + } + if (!JS_IsNull(rh->rw_func[1]) && + FD_ISSET(rh->fd, &wfds)) { + call_handler(ctx, rh->rw_func[1]); /* must stop because the list may have been modified */ + goto done; } - } else { -#ifdef USE_WORKER - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (!JS_IsNull(port->on_message_func)) { - JSWorkerMessagePipe *ps = port->recv_pipe; - if (pfd->fd == ps->waker.read_fd) { - if (handle_posted_message(rt, ctx, port)) - goto done; - } + } + + list_for_each(el, &ts->port_list) { + JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); + if (!JS_IsNull(port->on_message_func)) { + JSWorkerMessagePipe *ps = port->recv_pipe; + if (FD_ISSET(ps->waker.read_fd, &rfds)) { + if (handle_posted_message(rt, ctx, port)) + goto done; } } -#endif // USE_WORKER } } -done: - if (pfds != pfds_local) - js_free(ctx, pfds); - return ret; + done: + return 0; } -#endif // defined(_WIN32) - +#endif /* !_WIN32 */ static JSValue make_obj_error(JSContext *ctx, JSValue obj, @@ -2776,7 +2648,7 @@ static JSValue make_string_error(JSContext *ctx, static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - char buf[JS__PATH_MAX]; + char buf[PATH_MAX]; int err; if (!getcwd(buf, sizeof(buf))) { @@ -2831,42 +2703,6 @@ static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { -#ifdef _WIN32 - const char *path; - JSValue obj; - int err; - uint32_t len; - HANDLE h; - WIN32_FIND_DATAA d; - char s[1024]; - - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) { - JS_FreeCString(ctx, path); - return JS_EXCEPTION; - } - snprintf(s, sizeof(s), "%s/*", path); - JS_FreeCString(ctx, path); - err = 0; - h = FindFirstFileA(s, &d); - if (h == INVALID_HANDLE_VALUE) - err = GetLastError(); - if (err) - goto done; - JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewString(ctx, "."), - JS_PROP_C_W_E); - for (len = 1; FindNextFileA(h, &d); len++) { - JS_DefinePropertyValueUint32(ctx, obj, len, - JS_NewString(ctx, d.cFileName), - JS_PROP_C_W_E); - } - FindClose(h); -done: - return make_obj_error(ctx, obj, err); -#else const char *path; DIR *f; struct dirent *d; @@ -2905,7 +2741,6 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, closedir(f); done: return make_obj_error(ctx, obj, err); -#endif } #if !defined(_WIN32) @@ -2935,7 +2770,10 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, else res = stat(path, &st); #endif - err = (res < 0) ? errno : 0; + if (res < 0) + err = errno; + else + err = 0; JS_FreeCString(ctx, path); if (res < 0) { obj = JS_NULL; @@ -3050,7 +2888,7 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val, /* sleep(delay_ms) */ static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { int64_t delay; int ret; @@ -3081,7 +2919,7 @@ static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val, #if defined(_WIN32) static char *realpath(const char *path, char *buf) { - if (!_fullpath(buf, path, JS__PATH_MAX)) { + if (!_fullpath(buf, path, PATH_MAX)) { errno = ENOENT; return NULL; } else { @@ -3090,13 +2928,12 @@ static char *realpath(const char *path, char *buf) } #endif -#if !defined(__wasi__) /* return [path, errorcode] */ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *path; - char buf[JS__PATH_MAX], *res; + char buf[PATH_MAX], *res; int err; path = JS_ToCString(ctx, argv[0]); @@ -3112,11 +2949,10 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, } return make_string_error(ctx, buf, err); } -#endif -#if !defined(_WIN32) && !defined(__wasi__) +#if !defined(_WIN32) static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv) { const char *target, *linkpath; int err; @@ -3140,7 +2976,7 @@ static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *path; - char buf[JS__PATH_MAX]; + char buf[PATH_MAX]; int err; ssize_t res; @@ -3159,7 +2995,7 @@ static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, return make_string_error(ctx, buf, err); } -static char **build_envp(JSContext *ctx, JSValue obj) +static char **build_envp(JSContext *ctx, JSValueConst obj) { uint32_t len, i; JSPropertyEnum *tab; @@ -3204,9 +3040,7 @@ static char **build_envp(JSContext *ctx, JSValue obj) JS_FreeCString(ctx, str); } done: - for(i = 0; i < len; i++) - JS_FreeAtom(ctx, tab[i].atom); - js_free(ctx, tab); + JS_FreePropertyEnum(ctx, tab, len); return envp; fail: if (envp) { @@ -3222,9 +3056,9 @@ static char **build_envp(JSContext *ctx, JSValue obj) static int my_execvpe(const char *filename, char **argv, char **envp) { char *path, *p, *p_next, *p1; - char buf[JS__PATH_MAX]; + char buf[PATH_MAX]; size_t filename_len, path_len; - bool eacces_error; + BOOL eacces_error; filename_len = strlen(filename); if (filename_len == 0) { @@ -3237,7 +3071,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) path = getenv("PATH"); if (!path) path = (char *)"/bin:/usr/bin"; - eacces_error = false; + eacces_error = FALSE; p = path; for(p = path; p != NULL; p = p_next) { p1 = strchr(p, ':'); @@ -3249,7 +3083,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) path_len = p1 - p; } /* path too long */ - if ((path_len + 1 + filename_len + 1) > JS__PATH_MAX) + if ((path_len + 1 + filename_len + 1) > PATH_MAX) continue; memcpy(buf, p, path_len); buf[path_len] = '/'; @@ -3260,7 +3094,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) switch(errno) { case EACCES: - eacces_error = true; + eacces_error = TRUE; break; case ENOENT: case ENOTDIR: @@ -3274,19 +3108,6 @@ static int my_execvpe(const char *filename, char **argv, char **envp) return -1; } -static void (*js_os_exec_closefrom)(int); - -#if !defined(EMSCRIPTEN) && !defined(__wasi__) - -static js_once_t js_os_exec_once = JS_ONCE_INIT; - -static void js_os_exec_once_init(void) -{ - *(void **) (&js_os_exec_closefrom) = dlsym(RTLD_DEFAULT, "closefrom"); -} - -#endif - /* exec(args[, options]) -> exitcode */ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -3297,12 +3118,10 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, char **envp = environ; uint32_t exec_argc, i; int ret, pid, status; - bool block_flag = true, use_path = true; + BOOL block_flag = TRUE, use_path = TRUE; static const char *std_name[3] = { "stdin", "stdout", "stderr" }; int std_fds[3]; uint32_t uid = -1, gid = -1; - int ngroups = -1; - gid_t groups[64]; val = JS_GetPropertyStr(ctx, args, "length"); if (JS_IsException(val)) @@ -3406,48 +3225,8 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, if (ret) goto exception; } - - val = JS_GetPropertyStr(ctx, options, "groups"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - int64_t idx, len; - JSValue prop; - uint32_t id; - ngroups = 0; - if (JS_GetLength(ctx, val, &len)) { - JS_FreeValue(ctx, val); - goto exception; - } - for (idx = 0; idx < len; idx++) { - prop = JS_GetPropertyInt64(ctx, val, idx); - if (JS_IsException(prop)) - break; - if (JS_IsUndefined(prop)) - continue; - ret = JS_ToUint32(ctx, &id, prop); - JS_FreeValue(ctx, prop); - if (ret) - break; - if (ngroups == countof(groups)) { - JS_ThrowRangeError(ctx, "too many groups"); - break; - } - groups[ngroups++] = id; - } - JS_FreeValue(ctx, val); - if (idx < len) - goto exception; - } - } -#if !defined(EMSCRIPTEN) && !defined(__wasi__) - // should happen pre-fork because it calls dlsym() - // and that's not an async-signal-safe function - js_once(&js_os_exec_once, js_os_exec_once_init); -#endif - pid = fork(); if (pid < 0) { JS_ThrowTypeError(ctx, "fork error"); @@ -3455,6 +3234,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, } if (pid == 0) { /* child */ + /* remap the stdin/stdout/stderr handles if necessary */ for(i = 0; i < 3; i++) { if (std_fds[i] != i) { @@ -3462,23 +3242,32 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, _exit(127); } } - - if (js_os_exec_closefrom) { - js_os_exec_closefrom(3); - } else { - int fd_max = sysconf(_SC_OPEN_MAX); +#if defined(HAVE_CLOSEFROM) + /* closefrom() is available on many recent unix systems: + Linux with glibc 2.34+, Solaris 9+, FreeBSD 7.3+, + NetBSD 3.0+, OpenBSD 3.5+. + Linux with the musl libc and macOS don't have it. + */ + + closefrom(3); +#else + { + /* Close the file handles manually, limit to 1024 to avoid + costly loop on linux Alpine where sysconf(_SC_OPEN_MAX) + returns a huge value 1048576. + Patch inspired by nicolas-duteil-nova. See also: + https://stackoverflow.com/questions/73229353/ + https://stackoverflow.com/questions/899038/#918469 + */ + int fd_max = min_int(sysconf(_SC_OPEN_MAX), 1024); for(i = 3; i < fd_max; i++) close(i); } - +#endif if (cwd) { if (chdir(cwd) < 0) _exit(127); } - if (ngroups != -1) { - if (setgroups(ngroups, groups) < 0) - _exit(127); - } if (uid != -1) { if (setuid(uid) < 0) _exit(127); @@ -3646,18 +3435,20 @@ typedef struct { char *filename; /* module filename */ char *basename; /* module base name */ JSWorkerMessagePipe *recv_pipe, *send_pipe; + int strip_flags; } WorkerFuncArgs; typedef struct { int ref_count; - uint64_t buf[]; + uint64_t buf[0]; } JSSABHeader; +static JSClassID js_worker_class_id; static JSContext *(*js_worker_new_context_func)(JSRuntime *rt); static int atomic_add_int(int *ptr, int v) { - return atomic_fetch_add((_Atomic uint32_t*)ptr, v) + v; + return atomic_fetch_add((_Atomic(uint32_t) *)ptr, v) + v; } /* shared array buffer allocator */ @@ -3703,7 +3494,7 @@ static JSWorkerMessagePipe *js_new_message_pipe(void) } ps->ref_count = 1; init_list_head(&ps->msg_queue); - js_mutex_init(&ps->mutex); + pthread_mutex_init(&ps->mutex, NULL); return ps; } @@ -3741,7 +3532,7 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps) msg = list_entry(el, JSWorkerMessage, link); js_free_message(msg); } - js_mutex_destroy(&ps->mutex); + pthread_mutex_destroy(&ps->mutex); js_waker_close(&ps->waker); free(ps); } @@ -3757,10 +3548,9 @@ static void js_free_port(JSRuntime *rt, JSWorkerMessageHandler *port) } } -static void js_worker_finalizer(JSRuntime *rt, JSValueConst val) +static void js_worker_finalizer(JSRuntime *rt, JSValue val) { - JSThreadState *ts = js_get_thread_state(rt); - JSWorkerData *worker = JS_GetOpaque(val, ts->worker_class_id); + JSWorkerData *worker = JS_GetOpaque(val, js_worker_class_id); if (worker) { js_free_message_pipe(worker->recv_pipe); js_free_message_pipe(worker->send_pipe); @@ -3774,7 +3564,7 @@ static JSClassDef js_worker_class = { .finalizer = js_worker_finalizer, }; -static void worker_func(void *opaque) +static void *worker_func(void *opaque) { WorkerFuncArgs *args = opaque; JSRuntime *rt; @@ -3787,12 +3577,13 @@ static void worker_func(void *opaque) fprintf(stderr, "JS_NewRuntime failure"); exit(1); } + JS_SetStripInfo(rt, args->strip_flags); js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); /* set the pipe to communicate with the parent */ - ts = js_get_thread_state(rt); + ts = JS_GetRuntimeOpaque(rt); ts->recv_pipe = args->recv_pipe; ts->send_pipe = args->send_pipe; @@ -3803,7 +3594,7 @@ static void worker_func(void *opaque) fprintf(stderr, "JS_NewContext failure"); } - JS_SetCanBlock(rt, true); + JS_SetCanBlock(rt, TRUE); js_std_add_helpers(ctx, -1, NULL); @@ -3818,29 +3609,28 @@ static void worker_func(void *opaque) js_std_loop(ctx); - js_std_free_handlers(rt); JS_FreeContext(ctx); + js_std_free_handlers(rt); JS_FreeRuntime(rt); + return NULL; } static JSValue js_worker_ctor_internal(JSContext *ctx, JSValueConst new_target, JSWorkerMessagePipe *recv_pipe, JSWorkerMessagePipe *send_pipe) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); JSValue obj = JS_UNDEFINED, proto; JSWorkerData *s; /* create the object */ if (JS_IsUndefined(new_target)) { - proto = JS_GetClassProto(ctx, ts->worker_class_id); + proto = JS_GetClassProto(ctx, js_worker_class_id); } else { proto = JS_GetPropertyStr(ctx, new_target, "prototype"); if (JS_IsException(proto)) goto fail; } - obj = JS_NewObjectProtoClass(ctx, proto, ts->worker_class_id); + obj = JS_NewObjectProtoClass(ctx, proto, js_worker_class_id); JS_FreeValue(ctx, proto); if (JS_IsException(obj)) goto fail; @@ -3862,7 +3652,8 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, { JSRuntime *rt = JS_GetRuntime(ctx); WorkerFuncArgs *args = NULL; - js_thread_t thr; + pthread_t tid; + pthread_attr_t attr; JSValue obj = JS_UNDEFINED; int ret; const char *filename = NULL, *basename; @@ -3904,12 +3695,18 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, if (!args->send_pipe) goto oom_fail; + args->strip_flags = JS_GetStripInfo(rt); + obj = js_worker_ctor_internal(ctx, new_target, args->send_pipe, args->recv_pipe); if (JS_IsException(obj)) goto fail; - ret = js_thread_create(&thr, worker_func, args, JS_THREAD_CREATE_DETACHED); + pthread_attr_init(&attr); + /* no join at the end */ + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&tid, &attr, worker_func, args); + pthread_attr_destroy(&attr); if (ret != 0) { JS_ThrowTypeError(ctx, "could not create worker"); goto fail; @@ -3936,21 +3733,19 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); JSWorkerMessagePipe *ps; - size_t data_len, i; + size_t data_len, sab_tab_len, i; uint8_t *data; JSWorkerMessage *msg; - JSSABTab sab_tab; + uint8_t **sab_tab; if (!worker) return JS_EXCEPTION; data = JS_WriteObject2(ctx, &data_len, argv[0], JS_WRITE_OBJ_SAB | JS_WRITE_OBJ_REFERENCE, - &sab_tab); + &sab_tab, &sab_tab_len); if (!data) return JS_EXCEPTION; @@ -3967,16 +3762,16 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, memcpy(msg->data, data, data_len); msg->data_len = data_len; - if (sab_tab.len > 0) { - msg->sab_tab = malloc(sizeof(msg->sab_tab[0]) * sab_tab.len); + if (sab_tab_len > 0) { + msg->sab_tab = malloc(sizeof(msg->sab_tab[0]) * sab_tab_len); if (!msg->sab_tab) goto fail; - memcpy(msg->sab_tab, sab_tab.tab, sizeof(msg->sab_tab[0]) * sab_tab.len); + memcpy(msg->sab_tab, sab_tab, sizeof(msg->sab_tab[0]) * sab_tab_len); } - msg->sab_tab_len = sab_tab.len; + msg->sab_tab_len = sab_tab_len; js_free(ctx, data); - js_free(ctx, sab_tab.tab); + js_free(ctx, sab_tab); /* increment the SAB reference counts */ for(i = 0; i < msg->sab_tab_len; i++) { @@ -3984,12 +3779,12 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, } ps = worker->send_pipe; - js_mutex_lock(&ps->mutex); + pthread_mutex_lock(&ps->mutex); /* indicate that data is present */ if (list_empty(&ps->msg_queue)) js_waker_signal(&ps->waker); list_add_tail(&msg->link, &ps->msg_queue); - js_mutex_unlock(&ps->mutex); + pthread_mutex_unlock(&ps->mutex); return JS_UNDEFINED; fail: if (msg) { @@ -3998,17 +3793,17 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, free(msg); } js_free(ctx, data); - js_free(ctx, sab_tab.tab); + js_free(ctx, sab_tab); return JS_EXCEPTION; } static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val, - JSValueConst func) + JSValueConst func) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); JSWorkerMessageHandler *port; if (!worker) @@ -4040,9 +3835,7 @@ static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val, static JSValue js_worker_get_onmessage(JSContext *ctx, JSValueConst this_val) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); JSWorkerMessageHandler *port; if (!worker) return JS_EXCEPTION; @@ -4074,22 +3867,8 @@ void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)) #define OS_PLATFORM "darwin" #elif defined(EMSCRIPTEN) #define OS_PLATFORM "js" -#elif defined(__CYGWIN__) -#define OS_PLATFORM "cygwin" -#elif defined(__linux__) -#define OS_PLATFORM "linux" -#elif defined(__OpenBSD__) -#define OS_PLATFORM "openbsd" -#elif defined(__NetBSD__) -#define OS_PLATFORM "netbsd" -#elif defined(__FreeBSD__) -#define OS_PLATFORM "freebsd" -#elif defined(__wasi__) -#define OS_PLATFORM "wasi" -#elif defined(__GNU__) -#define OS_PLATFORM "hurd" #else -#define OS_PLATFORM "unknown" +#define OS_PLATFORM "linux" #endif #define OS_FLAG(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE ) @@ -4112,10 +3891,8 @@ static const JSCFunctionListEntry js_os_funcs[] = { JS_CFUNC_MAGIC_DEF("read", 4, js_os_read_write, 0 ), JS_CFUNC_MAGIC_DEF("write", 4, js_os_read_write, 1 ), JS_CFUNC_DEF("isatty", 1, js_os_isatty ), -#if !defined(__wasi__) JS_CFUNC_DEF("ttyGetWinSize", 1, js_os_ttyGetWinSize ), JS_CFUNC_DEF("ttySetRaw", 1, js_os_ttySetRaw ), -#endif JS_CFUNC_DEF("remove", 1, js_os_remove ), JS_CFUNC_DEF("rename", 2, js_os_rename ), JS_CFUNC_MAGIC_DEF("setReadHandler", 2, js_os_setReadHandler, 0 ), @@ -4127,7 +3904,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { OS_FLAG(SIGILL), OS_FLAG(SIGSEGV), OS_FLAG(SIGTERM), -#if !defined(_WIN32) && !defined(__wasi__) +#if !defined(_WIN32) OS_FLAG(SIGQUIT), OS_FLAG(SIGPIPE), OS_FLAG(SIGALRM), @@ -4139,15 +3916,10 @@ static const JSCFunctionListEntry js_os_funcs[] = { OS_FLAG(SIGTSTP), OS_FLAG(SIGTTIN), OS_FLAG(SIGTTOU), - JS_CFUNC_DEF("cputime", 0, js_os_cputime ), #endif - JS_CFUNC_DEF("exePath", 0, js_os_exepath ), JS_CFUNC_DEF("now", 0, js_os_now ), - JS_CFUNC_MAGIC_DEF("setTimeout", 2, js_os_setTimeout, 0 ), - JS_CFUNC_MAGIC_DEF("setInterval", 2, js_os_setTimeout, 1 ), - // per spec: both functions can cancel timeouts and intervals + JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ), JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ), - JS_CFUNC_DEF("clearInterval", 1, js_os_clearTimeout ), JS_CFUNC_DEF("sleepAsync", 1, js_os_sleepAsync ), JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ), JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ), @@ -4170,10 +3942,8 @@ static const JSCFunctionListEntry js_os_funcs[] = { JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ), JS_CFUNC_DEF("utimes", 3, js_os_utimes ), JS_CFUNC_DEF("sleep", 1, js_os_sleep ), -#if !defined(__wasi__) JS_CFUNC_DEF("realpath", 1, js_os_realpath ), -#endif -#if !defined(_WIN32) && !defined(__wasi__) +#if !defined(_WIN32) JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ), JS_CFUNC_DEF("symlink", 2, js_os_symlink ), JS_CFUNC_DEF("readlink", 1, js_os_readlink ), @@ -4190,17 +3960,16 @@ static const JSCFunctionListEntry js_os_funcs[] = { static int js_os_init(JSContext *ctx, JSModuleDef *m) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - - ts->can_js_os_poll = true; + os_poll_func = js_os_poll; #ifdef USE_WORKER { + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); JSValue proto, obj; /* Worker class */ - JS_NewClassID(rt, &ts->worker_class_id); - JS_NewClass(rt, ts->worker_class_id, &js_worker_class); + JS_NewClassID(&js_worker_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_worker_class_id, &js_worker_class); proto = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, proto, js_worker_proto_funcs, countof(js_worker_proto_funcs)); @@ -4208,7 +3977,7 @@ static int js_os_init(JSContext *ctx, JSModuleDef *m) JS_CFUNC_constructor, 0); JS_SetConstructor(ctx, obj, proto); - JS_SetClassProto(ctx, ts->worker_class_id, proto); + JS_SetClassProto(ctx, js_worker_class_id, proto); /* set 'Worker.parent' if necessary */ if (ts->recv_pipe && ts->send_pipe) { @@ -4221,7 +3990,8 @@ static int js_os_init(JSContext *ctx, JSModuleDef *m) } #endif /* USE_WORKER */ - return JS_SetModuleExportList(ctx, m, js_os_funcs, countof(js_os_funcs)); + return JS_SetModuleExportList(ctx, m, js_os_funcs, + countof(js_os_funcs)); } JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) @@ -4242,65 +4012,41 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) static JSValue js_print(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { -#ifdef _WIN32 - HANDLE handle; - DWORD mode; -#endif - const char *s; - JSValueConst v; - DynBuf b; int i; - - dbuf_init(&b); + JSValueConst v; + for(i = 0; i < argc; i++) { + if (i != 0) + putchar(' '); v = argv[i]; - s = JS_ToCString(ctx, v); - if (!s && JS_IsObject(v)) { - JS_FreeValue(ctx, JS_GetException(ctx)); - JSValue t = JS_ToObjectString(ctx, v); - s = JS_ToCString(ctx, t); - JS_FreeValue(ctx, t); - } - if (s) { - dbuf_printf(&b, "%s%s", &" "[!i], s); - JS_FreeCString(ctx, s); + if (JS_IsString(v)) { + const char *str; + size_t len; + str = JS_ToCStringLen(ctx, &len, v); + if (!str) + return JS_EXCEPTION; + fwrite(str, 1, len, stdout); + JS_FreeCString(ctx, str); } else { - dbuf_printf(&b, "%s", &" "[!i]); - JS_FreeValue(ctx, JS_GetException(ctx)); + JS_PrintValue(ctx, js_print_value_write, stdout, v, NULL); } } - dbuf_putc(&b, '\n'); -#ifdef _WIN32 - // use WriteConsoleA with CP_UTF8 for better Unicode handling vis-a-vis - // the mangling that happens when going through msvcrt's stdio layer, - // *except* when stdout is redirected to something that is not a console - handle = (HANDLE)_get_osfhandle(/*STDOUT_FILENO*/1); // don't CloseHandle - if (GetFileType(handle) != FILE_TYPE_CHAR) - goto fallback; - if (!GetConsoleMode(handle, &mode)) - goto fallback; - handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle == INVALID_HANDLE_VALUE) - goto fallback; - mode = GetConsoleOutputCP(); - SetConsoleOutputCP(CP_UTF8); - WriteConsoleA(handle, b.buf, b.size, NULL, NULL); - SetConsoleOutputCP(mode); - FlushFileBuffers(handle); - goto done; -fallback: -#endif - fwrite(b.buf, 1, b.size, stdout); - fflush(stdout); - goto done; // avoid unused label warning -done: - dbuf_free(&b); + putchar('\n'); return JS_UNDEFINED; } +static JSValue js_console_log(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue ret; + ret = js_print(ctx, this_val, argc, argv); + fflush(stdout); + return ret; +} + void js_std_add_helpers(JSContext *ctx, int argc, char **argv) { - JSValue global_obj, console, args; + JSValue global_obj, console, args, performance; int i; /* XXX: should these global definitions be enumerable? */ @@ -4308,9 +4054,14 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) console = JS_NewObject(ctx); JS_SetPropertyStr(ctx, console, "log", - JS_NewCFunction(ctx, js_print, "log", 1)); + JS_NewCFunction(ctx, js_console_log, "log", 1)); JS_SetPropertyStr(ctx, global_obj, "console", console); + performance = JS_NewObject(ctx); + JS_SetPropertyStr(ctx, performance, "now", + JS_NewCFunction(ctx, js_os_now, "now", 0)); + JS_SetPropertyStr(ctx, global_obj, "performance", performance); + /* same methods as the mozilla JS shell */ if (argc >= 0) { args = JS_NewArray(ctx); @@ -4322,36 +4073,30 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) JS_SetPropertyStr(ctx, global_obj, "print", JS_NewCFunction(ctx, js_print, "print", 1)); + JS_SetPropertyStr(ctx, global_obj, "__loadScript", + JS_NewCFunction(ctx, js_loadScript, "__loadScript", 1)); JS_FreeValue(ctx, global_obj); } -static void js_std_finalize(JSRuntime *rt, void *arg) -{ - JSThreadState *ts = arg; - js_set_thread_state(rt, NULL); - js_free_rt(rt, ts); -} - void js_std_init_handlers(JSRuntime *rt) { JSThreadState *ts; - ts = js_mallocz_rt(rt, sizeof(*ts)); + ts = malloc(sizeof(*ts)); if (!ts) { fprintf(stderr, "Could not allocate memory for the worker"); exit(1); } + memset(ts, 0, sizeof(*ts)); init_list_head(&ts->os_rw_handlers); init_list_head(&ts->os_signal_handlers); init_list_head(&ts->os_timers); init_list_head(&ts->port_list); init_list_head(&ts->rejected_promise_list); - ts->next_timer_id = 1; - js_set_thread_state(rt, ts); - JS_AddRuntimeFinalizer(rt, js_std_finalize, ts); + JS_SetRuntimeOpaque(rt, ts); #ifdef USE_WORKER /* set the SharedArrayBuffer memory handlers */ @@ -4366,17 +4111,9 @@ void js_std_init_handlers(JSRuntime *rt) #endif } -static void free_rp(JSRuntime *rt, JSRejectedPromiseEntry *rp) -{ - list_del(&rp->link); - JS_FreeValueRT(rt, rp->promise); - JS_FreeValueRT(rt, rp->reason); - js_free_rt(rt, rp); -} - void js_std_free_handlers(JSRuntime *rt) { - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); struct list_head *el, *el1; list_for_each_safe(el, el1, &ts->os_rw_handlers) { @@ -4396,7 +4133,9 @@ void js_std_free_handlers(JSRuntime *rt) list_for_each_safe(el, el1, &ts->rejected_promise_list) { JSRejectedPromiseEntry *rp = list_entry(el, JSRejectedPromiseEntry, link); - free_rp(rt, rp); + JS_FreeValueRT(rt, rp->promise); + JS_FreeValueRT(rt, rp->reason); + free(rp); } #ifdef USE_WORKER @@ -4404,37 +4143,15 @@ void js_std_free_handlers(JSRuntime *rt) js_free_message_pipe(ts->recv_pipe); js_free_message_pipe(ts->send_pipe); #endif -} - -static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val) -{ - const char *str; - str = JS_ToCString(ctx, val); - if (str) { - fprintf(f, "%s\n", str); - JS_FreeCString(ctx, str); - } else { - fprintf(f, "[exception]\n"); - } + free(ts); + JS_SetRuntimeOpaque(rt, NULL); /* fail safe */ } static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val) { - JSValue val; - bool is_error; - - is_error = JS_IsError(ctx, exception_val); - js_dump_obj(ctx, stderr, exception_val); - if (is_error) { - val = JS_GetPropertyStr(ctx, exception_val, "stack"); - } else { - js_std_cmd(/*ErrorBackTrace*/2, ctx, &val); - } - if (!JS_IsUndefined(val)) { - js_dump_obj(ctx, stderr, val); - JS_FreeValue(ctx, val); - } + JS_PrintValue(ctx, js_print_value_write, stderr, exception_val, NULL); + fputc('\n', stderr); } void js_std_dump_error(JSContext *ctx) @@ -4453,7 +4170,7 @@ static JSRejectedPromiseEntry *find_rejected_promise(JSContext *ctx, JSThreadSta list_for_each(el, &ts->rejected_promise_list) { JSRejectedPromiseEntry *rp = list_entry(el, JSRejectedPromiseEntry, link); - if (JS_IsSameValue(ctx, rp->promise, promise)) + if (JS_SameValue(ctx, rp->promise, promise)) return rp; } return NULL; @@ -4461,27 +4178,32 @@ static JSRejectedPromiseEntry *find_rejected_promise(JSContext *ctx, JSThreadSta void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, JSValueConst reason, - bool is_handled, void *opaque) + BOOL is_handled, void *opaque) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSRejectedPromiseEntry *rp = find_rejected_promise(ctx, ts, promise); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSRejectedPromiseEntry *rp; - if (is_handled) { - /* the rejection is handled, so the entry can be removed if present */ - if (rp) - free_rp(rt, rp); - } else { + if (!is_handled) { /* add a new entry if needed */ + rp = find_rejected_promise(ctx, ts, promise); if (!rp) { - rp = js_malloc_rt(rt, sizeof(*rp)); + rp = malloc(sizeof(*rp)); if (rp) { rp->promise = JS_DupValue(ctx, promise); rp->reason = JS_DupValue(ctx, reason); list_add_tail(&rp->link, &ts->rejected_promise_list); } } + } else { + /* the rejection is handled, so the entry can be removed if present */ + rp = find_rejected_promise(ctx, ts, promise); + if (rp) { + JS_FreeValue(ctx, rp->promise); + JS_FreeValue(ctx, rp->reason); + list_del(&rp->link); + free(rp); + } } } @@ -4492,7 +4214,7 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, static void js_std_promise_rejection_check(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); + JSThreadState *ts = JS_GetRuntimeOpaque(rt); struct list_head *el; if (unlikely(!list_empty(&ts->rejected_promise_list))) { @@ -4500,38 +4222,32 @@ static void js_std_promise_rejection_check(JSContext *ctx) JSRejectedPromiseEntry *rp = list_entry(el, JSRejectedPromiseEntry, link); fprintf(stderr, "Possibly unhandled promise rejection: "); js_std_dump_error1(ctx, rp->reason); - fflush(stderr); } exit(1); } } /* main loop which calls the user JS callbacks */ -int js_std_loop(JSContext *ctx) +void js_std_loop(JSContext *ctx) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); - JSContext *ctx1; int err; for(;;) { /* execute the pending jobs */ for(;;) { - err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL); if (err <= 0) { if (err < 0) - goto done; + js_std_dump_error(ctx); break; } } js_std_promise_rejection_check(ctx); - - if (!ts->can_js_os_poll || js_os_poll(ctx)) + + if (!os_poll_func || os_poll_func(ctx)) break; } -done: - return JS_HasException(ctx); } /* Wait for a promise and execute pending jobs while waiting for @@ -4539,8 +4255,6 @@ int js_std_loop(JSContext *ctx) rejection. */ JSValue js_std_await(JSContext *ctx, JSValue obj) { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = js_get_thread_state(rt); JSValue ret; int state; @@ -4555,16 +4269,17 @@ JSValue js_std_await(JSContext *ctx, JSValue obj) JS_FreeValue(ctx, obj); break; } else if (state == JS_PROMISE_PENDING) { - JSContext *ctx1; int err; - err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL); if (err < 0) { - js_std_dump_error(ctx1); + js_std_dump_error(ctx); } - if (err == 0) + if (err == 0) { js_std_promise_rejection_check(ctx); - if (ts->can_js_os_poll) - js_os_poll(ctx); + + if (os_poll_func) + os_poll_func(ctx); + } } else { /* not a promise */ ret = obj; @@ -4583,8 +4298,7 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, goto exception; if (load_only) { if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { - if (js_module_set_import_meta(ctx, obj, false, false) < 0) - goto exception; + js_module_set_import_meta(ctx, obj, FALSE, FALSE); } JS_FreeValue(ctx, obj); } else { @@ -4593,8 +4307,7 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, JS_FreeValue(ctx, obj); goto exception; } - if (js_module_set_import_meta(ctx, obj, false, true) < 0) - goto exception; + js_module_set_import_meta(ctx, obj, FALSE, TRUE); val = JS_EvalFunction(ctx, obj); val = js_std_await(ctx, val); } else { @@ -4609,76 +4322,21 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, } } -static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +void js_std_eval_binary_json_module(JSContext *ctx, + const uint8_t *buf, size_t buf_len, + const char *module_name) { - uint8_t *buf; - uint64_t pos, len; JSValue obj; - size_t size; - int flags; - - if (JS_ToIndex(ctx, &pos, argv[1])) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &len, argv[2])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &flags, argv[3])) - return JS_EXCEPTION; - buf = JS_GetArrayBuffer(ctx, &size, argv[0]); - if (!buf) - return JS_EXCEPTION; - if (pos + len > size) - return JS_ThrowRangeError(ctx, "array buffer overflow"); - obj = JS_ReadObject(ctx, buf + pos, len, flags); - return obj; -} - -static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - size_t len; - uint8_t *buf; - JSValue array; - int flags; - - if (JS_ToInt32(ctx, &flags, argv[1])) - return JS_EXCEPTION; - buf = JS_WriteObject(ctx, &len, argv[0], flags); - if (!buf) - return JS_EXCEPTION; - array = JS_NewArrayBufferCopy(ctx, buf, len); - js_free(ctx, buf); - return array; -} - - -static const JSCFunctionListEntry js_bjson_funcs[] = { - JS_CFUNC_DEF("read", 4, js_bjson_read ), - JS_CFUNC_DEF("write", 2, js_bjson_write ), -#define DEF(x) JS_PROP_INT32_DEF(#x, JS_##x, JS_PROP_CONFIGURABLE) - DEF(READ_OBJ_BYTECODE), - DEF(READ_OBJ_REFERENCE), - DEF(READ_OBJ_SAB), - DEF(WRITE_OBJ_BYTECODE), - DEF(WRITE_OBJ_REFERENCE), - DEF(WRITE_OBJ_SAB), - DEF(WRITE_OBJ_STRIP_DEBUG), - DEF(WRITE_OBJ_STRIP_SOURCE), -#undef DEF -}; - -static int js_bjson_init(JSContext *ctx, JSModuleDef *m) -{ - return JS_SetModuleExportList(ctx, m, js_bjson_funcs, - countof(js_bjson_funcs)); -} - -JSModuleDef *js_init_module_bjson(JSContext *ctx, const char *module_name) -{ JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_bjson_init); - if (!m) - return NULL; - JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); - return m; + + obj = JS_ReadObject(ctx, buf, buf_len, 0); + if (JS_IsException(obj)) + goto exception; + m = create_json_module(ctx, module_name, obj); + if (!m) { + exception: + js_std_dump_error(ctx); + exit(1); + } } + diff --git a/quickjs/quickjs-libc.h b/quickjs/quickjs-libc.h new file mode 100644 index 0000000..5c8301b --- /dev/null +++ b/quickjs/quickjs-libc.h @@ -0,0 +1,66 @@ +/* + * QuickJS C library + * + * Copyright (c) 2017-2018 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QUICKJS_LIBC_H +#define QUICKJS_LIBC_H + +#include +#include + +#include "quickjs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); +JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); +void js_std_add_helpers(JSContext *ctx, int argc, char **argv); +void js_std_loop(JSContext *ctx); +JSValue js_std_await(JSContext *ctx, JSValue obj); +void js_std_init_handlers(JSRuntime *rt); +void js_std_free_handlers(JSRuntime *rt); +void js_std_dump_error(JSContext *ctx); +uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); +int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, + JS_BOOL use_realpath, JS_BOOL is_main); +int js_module_test_json(JSContext *ctx, JSValueConst attributes); +int js_module_check_attributes(JSContext *ctx, void *opaque, JSValueConst attributes); +JSModuleDef *js_module_loader(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes); +void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags); +void js_std_eval_binary_json_module(JSContext *ctx, + const uint8_t *buf, size_t buf_len, + const char *module_name); +void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, + JSValueConst reason, + JS_BOOL is_handled, void *opaque); +void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* QUICKJS_LIBC_H */ diff --git a/quickjs-ng/quickjs-opcode.h b/quickjs/quickjs-opcode.h similarity index 95% rename from quickjs-ng/quickjs-opcode.h rename to quickjs/quickjs-opcode.h index bd5be75..86c3ec4 100644 --- a/quickjs-ng/quickjs-opcode.h +++ b/quickjs/quickjs-opcode.h @@ -44,7 +44,6 @@ FMT(loc) FMT(arg) FMT(var_ref) FMT(u32) -FMT(u32x2) FMT(i32) FMT(const) FMT(label) @@ -122,14 +121,12 @@ DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a bytecode string */ DEF( get_super, 1, 1, 1, none) -DEF( import, 1, 1, 1, none) /* dynamic module import */ +DEF( import, 1, 2, 1, none) /* dynamic module import */ -DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */ DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */ DEF( put_var, 5, 1, 0, atom) /* must come after get_var */ DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */ -DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ DEF( get_ref_value, 1, 2, 3, none) DEF( put_ref_value, 1, 3, 0, none) @@ -137,17 +134,15 @@ DEF( put_ref_value, 1, 3, 0, none) DEF( define_var, 6, 0, 0, atom_u8) DEF(check_define_var, 6, 0, 0, atom_u8) DEF( define_func, 6, 1, 0, atom_u8) - -// order matters, see IC counterparts DEF( get_field, 5, 1, 1, atom) DEF( get_field2, 5, 1, 2, atom) DEF( put_field, 5, 2, 0, atom) - DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */ DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */ DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */ DEF( get_array_el, 1, 2, 1, none) DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ +DEF( get_array_el3, 1, 2, 3, none) /* obj prop -> obj prop1 value */ DEF( put_array_el, 1, 3, 0, none) DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */ DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */ @@ -177,6 +172,7 @@ DEF(set_loc_uninitialized, 3, 0, 0, loc) DEF( get_loc_check, 3, 0, 1, loc) DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */ DEF( put_loc_check_init, 3, 1, 0, loc) +DEF(get_loc_checkthis, 3, 0, 1, loc) DEF(get_var_ref_check, 3, 0, 1, var_ref) DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */ DEF(put_var_ref_check_init, 3, 1, 0, var_ref) @@ -192,14 +188,12 @@ DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */ DEF( to_object, 1, 1, 1, none) //DEF( to_string, 1, 1, 1, none) DEF( to_propkey, 1, 1, 1, none) -DEF( to_propkey2, 1, 2, 2, none) DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */ DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8) DEF( make_loc_ref, 7, 0, 2, atom_u16) DEF( make_arg_ref, 7, 0, 2, atom_u16) @@ -211,8 +205,9 @@ DEF( for_of_start, 1, 1, 3, none) DEF(for_await_of_start, 1, 1, 3, none) DEF( for_in_next, 1, 1, 3, none) DEF( for_of_next, 2, 3, 5, u8) +DEF(for_await_of_next, 1, 3, 4, none) /* iter next catch_offset -> iter next catch_offset obj */ DEF(iterator_check_object, 1, 1, 1, none) -DEF(iterator_get_value_done, 1, 1, 2, none) +DEF(iterator_get_value_done, 1, 2, 3, none) /* catch_offset obj -> catch_offset value done */ DEF( iterator_close, 1, 3, 0, none) DEF( iterator_next, 1, 4, 4, none) DEF( iterator_call, 2, 4, 5, u8) @@ -238,20 +233,15 @@ DEF( typeof, 1, 1, 1, none) DEF( delete, 1, 2, 1, none) DEF( delete_var, 5, 0, 1, atom) -/* warning: order matters (see js_parse_assign_expr) */ DEF( mul, 1, 2, 1, none) DEF( div, 1, 2, 1, none) DEF( mod, 1, 2, 1, none) DEF( add, 1, 2, 1, none) DEF( sub, 1, 2, 1, none) +DEF( pow, 1, 2, 1, none) DEF( shl, 1, 2, 1, none) DEF( sar, 1, 2, 1, none) DEF( shr, 1, 2, 1, none) -DEF( and, 1, 2, 1, none) -DEF( xor, 1, 2, 1, none) -DEF( or, 1, 2, 1, none) -DEF( pow, 1, 2, 1, none) - DEF( lt, 1, 2, 1, none) DEF( lte, 1, 2, 1, none) DEF( gt, 1, 2, 1, none) @@ -262,6 +252,9 @@ DEF( eq, 1, 2, 1, none) DEF( neq, 1, 2, 1, none) DEF( strict_eq, 1, 2, 1, none) DEF( strict_neq, 1, 2, 1, none) +DEF( and, 1, 2, 1, none) +DEF( xor, 1, 2, 1, none) +DEF( or, 1, 2, 1, none) DEF(is_undefined_or_null, 1, 1, 1, none) DEF( private_in, 1, 2, 1, none) DEF(push_bigint_i32, 5, 0, 1, i32) @@ -275,6 +268,8 @@ def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ +/* the following opcodes must be in the same order as the 'with_x' and + get_var_undef, get_var and put_var opcodes */ def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ @@ -282,6 +277,7 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */ def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */ def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */ def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */ @@ -290,8 +286,9 @@ def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */ def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */ -def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */ +def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ +#if SHORT_OPCODES DEF( push_minus1, 1, 0, 1, none_int) DEF( push_0, 1, 0, 1, none_int) DEF( push_1, 1, 0, 1, none_int) @@ -311,7 +308,6 @@ DEF( get_loc8, 2, 0, 1, loc8) DEF( put_loc8, 2, 1, 0, loc8) DEF( set_loc8, 2, 1, 1, loc8) -DEF( get_loc0_loc1, 1, 0, 2, none_loc) DEF( get_loc0, 1, 0, 1, none_loc) DEF( get_loc1, 1, 0, 1, none_loc) DEF( get_loc2, 1, 0, 1, none_loc) @@ -365,6 +361,7 @@ DEF( is_undefined, 1, 1, 1, none) DEF( is_null, 1, 1, 1, none) DEF(typeof_is_undefined, 1, 1, 1, none) DEF( typeof_is_function, 1, 1, 1, none) +#endif #undef DEF #undef def diff --git a/quickjs-ng/quickjs.c b/quickjs/quickjs.c similarity index 79% rename from quickjs-ng/quickjs.c rename to quickjs/quickjs.c index 1d85460..b8a08f4 100644 --- a/quickjs-ng/quickjs.c +++ b/quickjs/quickjs.c @@ -3,8 +3,6 @@ * * Copyright (c) 2017-2025 Fabrice Bellard * Copyright (c) 2017-2025 Charlie Gordon - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,25 +28,36 @@ #include #include #include -#if !defined(_MSC_VER) -#include -#if defined(_WIN32) -#include -#endif +#if !defined(QUICKJS_HAVE_SYS_TIME_H) + #if defined(__linux__) || defined(__APPLE__) + #define QUICKJS_HAVE_SYS_TIME_H + #endif #endif -#if defined(_WIN32) -#include +#if defined(QUICKJS_HAVE_SYS_TIME_H) +#include #endif #include #include #include +#if defined(__APPLE__) +#include +#elif defined(__linux__) || defined(__GLIBC__) || defined(__ANDROID__) +#include +#elif defined(__FreeBSD__) +#include +#elif defined(_WIN32) +#include +#endif #include "cutils.h" #include "list.h" #include "quickjs.h" #include "libregexp.h" +#include "libunicode.h" #include "dtoa.h" +#define OPTIMIZE 1 +#define SHORT_OPCODES 1 #if defined(EMSCRIPTEN) || defined(_MSC_VER) #define DIRECT_DISPATCH 0 #else @@ -61,65 +70,61 @@ #define MALLOC_OVERHEAD 8 #endif -#if defined(__NEWLIB__) -#define NO_TM_GMTOFF +#if !defined(_WIN32) +/* define it if printf uses the RNDN rounding mode instead of RNDNA */ +#define CONFIG_PRINTF_RNDN #endif -// atomic_store etc. are completely busted in recent versions of tcc; -// somehow the compiler forgets to load |ptr| into %rdi when calling -// the __atomic_*() helpers in its lib/stdatomic.c and lib/atomic.S -#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(QJS_DISABLE_ATOMICS) && !__STDC_NO_ATOMICS__ -#include "quickjs-c-atomics.h" +/* define to include Atomics.* operations which depend on the OS + threads */ +#if !defined(EMSCRIPTEN) && !defined(QJS_DISABLE_ATOMICS) #define CONFIG_ATOMICS #endif -#ifndef __GNUC__ -#define __extension__ -#endif - -#ifndef NDEBUG -#define ENABLE_DUMPS +#if !defined(EMSCRIPTEN) +/* enable stack limitation */ +#define CONFIG_STACK_CHECK #endif -//#define FORCE_GC_AT_MALLOC /* test the GC by forcing it before each object allocation */ - -#define check_dump_flag(rt, flag) ((rt->dump_flags & (flag +0)) == (flag +0)) - -#define STRINGIFY_(x) #x -#define STRINGIFY(x) STRINGIFY_(x) - -#define QJS_VERSION_STRING \ - STRINGIFY(QJS_VERSION_MAJOR) "." STRINGIFY(QJS_VERSION_MINOR) "." STRINGIFY(QJS_VERSION_PATCH) QJS_VERSION_SUFFIX - -const char* JS_GetVersion(void) { - return QJS_VERSION_STRING; -} - -#undef STRINFIGY_ -#undef STRINGIFY - -static inline JSValueConst *vc(JSValue *vals) -{ - return (JSValueConst *)vals; -} -static inline JSValue unsafe_unconst(JSValueConst v) -{ -#ifdef JS_CHECK_JSVALUE - return (JSValue)v; -#else - return v; -#endif -} +/* dump object free */ +//#define DUMP_FREE +//#define DUMP_CLOSURE +/* dump the bytecode of the compiled functions: combination of bits + 1: dump pass 3 final byte code + 2: dump pass 2 code + 4: dump pass 1 code + 8: dump stdlib functions + 16: dump bytecode in hex + 32: dump line number table + 64: dump compute_stack_size + */ +//#define DUMP_BYTECODE (1) +/* dump the occurence of the automatic GC */ +//#define DUMP_GC +/* dump objects freed by the garbage collector */ +//#define DUMP_GC_FREE +/* dump objects leaking when freeing the runtime */ +//#define DUMP_LEAKS 1 +/* dump memory usage before running the garbage collector */ +//#define DUMP_MEM +//#define DUMP_OBJECTS /* dump objects in JS_FreeContext */ +//#define DUMP_ATOMS /* dump atoms in JS_FreeContext */ +//#define DUMP_SHAPES /* dump shapes in JS_FreeContext */ +//#define DUMP_MODULE_RESOLVE +//#define DUMP_MODULE_EXEC +//#define DUMP_PROMISE +//#define DUMP_READ_OBJECT +//#define DUMP_ROPE_REBALANCE + +/* test the GC by forcing it before each object allocation */ +//#define FORCE_GC_AT_MALLOC -static inline JSValueConst safe_const(JSValue v) -{ -#ifdef JS_CHECK_JSVALUE - return (JSValueConst)v; -#else - return v; +#ifdef CONFIG_ATOMICS +#include +#include +#include #endif -} enum { /* classid tag */ /* union usage | properties */ @@ -161,8 +166,7 @@ enum { JS_CLASS_SET, /* u.map_state */ JS_CLASS_WEAKMAP, /* u.map_state */ JS_CLASS_WEAKSET, /* u.map_state */ - JS_CLASS_ITERATOR, - JS_CLASS_ITERATOR_CONCAT, /* u.iterator_concat_data */ + JS_CLASS_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ITERATOR_HELPER, /* u.iterator_helper_data */ JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */ JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ @@ -183,9 +187,7 @@ enum { JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ JS_CLASS_WEAK_REF, JS_CLASS_FINALIZATION_REGISTRY, - JS_CLASS_DOM_EXCEPTION, - JS_CLASS_CALL_SITE, - + JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; @@ -205,23 +207,32 @@ typedef enum JSErrorEnum { JS_AGGREGATE_ERROR, JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ - JS_PLAIN_ERROR = JS_NATIVE_ERROR_COUNT } JSErrorEnum; -#define JS_MAX_LOCAL_VARS 65535 +/* the variable and scope indexes must fit on 16 bits. The (-1) and + ARG_SCOPE_END values are reserved. */ +#define JS_MAX_LOCAL_VARS 65534 #define JS_STACK_SIZE_MAX 65534 #define JS_STRING_LEN_MAX ((1 << 30) - 1) -// 1,024 bytes is about the cutoff point where it starts getting -// more profitable to ref slice than to copy -#define JS_STRING_SLICE_LEN_MAX 1024 // in bytes + +/* strings <= this length are not concatenated using ropes. if too + small, the rope memory overhead becomes high. */ +#define JS_STRING_ROPE_SHORT_LEN 512 +/* specific threshold for initial rope use */ +#define JS_STRING_ROPE_SHORT2_LEN 8192 +/* rope depth at which we rebalance */ +#define JS_STRING_ROPE_MAX_DEPTH 60 #define __exception __attribute__((warn_unused_result)) typedef struct JSShape JSShape; typedef struct JSString JSString; typedef struct JSString JSAtomStruct; +typedef struct JSObject JSObject; +#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) +#define JS_VALUE_GET_STRING_ROPE(v) ((JSStringRope *)JS_VALUE_GET_PTR(v)) typedef enum { JS_GC_PHASE_NONE, @@ -229,23 +240,7 @@ typedef enum { JS_GC_PHASE_REMOVE_CYCLES, } JSGCPhaseEnum; -typedef struct JSMallocState { - size_t malloc_count; - size_t malloc_size; - size_t malloc_limit; - void *opaque; /* user opaque */ -} JSMallocState; - -typedef struct JSRuntimeFinalizerState { - struct JSRuntimeFinalizerState *next; - JSRuntimeFinalizer *finalizer; - void *arg; -} JSRuntimeFinalizerState; - -typedef struct JSValueLink { - struct JSValueLink *next; - JSValueConst value; -} JSValueLink; +typedef enum OPCodeEnum OPCodeEnum; struct JSRuntime { JSMallocFunctions mf; @@ -260,7 +255,6 @@ struct JSRuntime { JSAtomStruct **atom_array; int atom_free_index; /* 0 = none */ - JSClassID js_class_id_alloc; /* counter for user defined classes */ int class_count; /* size of class_array */ JSClass *class_array; @@ -273,7 +267,8 @@ struct JSRuntime { struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS + struct list_head weakref_list; /* list of JSWeakRefHeader.link */ +#ifdef DUMP_LEAKS struct list_head string_list; /* list of JSString.link */ #endif /* stack limitation */ @@ -282,49 +277,44 @@ struct JSRuntime { uintptr_t stack_limit; /* lower stack limit */ JSValue current_exception; + /* true if the current exception cannot be catched */ + BOOL current_exception_is_uncatchable : 8; /* true if inside an out of memory error, to avoid recursing */ - bool in_out_of_memory; - /* true if inside build_backtrace, to avoid recursing */ - bool in_build_stack_trace; - /* true if inside JS_FreeRuntime */ - bool in_free; + BOOL in_out_of_memory : 8; struct JSStackFrame *current_stack_frame; JSInterruptHandler *interrupt_handler; void *interrupt_opaque; - JSPromiseHook *promise_hook; - void *promise_hook_opaque; - // for smuggling the parent promise from js_promise_then - // to js_promise_constructor - JSValueLink *parent_promise; - JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; - JSModuleLoaderFunc *module_loader_func; + BOOL module_loader_has_attr; + union { + JSModuleLoaderFunc *module_loader_func; + JSModuleLoaderFunc2 *module_loader_func2; + } u; + JSModuleCheckSupportedImportAttributes *module_check_attrs; void *module_loader_opaque; /* timestamp for internal use in module evaluation */ int64_t module_async_evaluation_next_timestamp; + BOOL can_block : 8; /* TRUE if Atomics.wait can block */ /* used to allocate, free and clone SharedArrayBuffers */ JSSharedArrayBufferFunctions sab_funcs; - - bool can_block; /* true if Atomics.wait can block */ - uint32_t dump_flags : 24; - + /* see JS_SetStripInfo() */ + uint8_t strip_flags; + /* Shape hash table */ int shape_hash_bits; int shape_hash_size; int shape_hash_count; /* number of hashed shapes */ JSShape **shape_hash; void *user_opaque; - void *libc_opaque; - JSRuntimeFinalizerState *finalizers; }; struct JSClass { @@ -337,16 +327,20 @@ struct JSClass { const JSClassExoticMethods *exotic; }; +#define JS_MODE_STRICT (1 << 0) +#define JS_MODE_ASYNC (1 << 2) /* async function */ +#define JS_MODE_BACKTRACE_BARRIER (1 << 3) /* stop backtrace before this frame */ + typedef struct JSStackFrame { struct JSStackFrame *prev_frame; /* NULL if first stack frame */ JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue *arg_buf; /* arguments */ JSValue *var_buf; /* variables */ - struct list_head var_ref_list; /* list of JSVarRef.link */ - uint8_t *cur_pc; /* only used in bytecode functions : PC of the + struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */ + const uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ - uint32_t arg_count : 31; - uint32_t is_strict_mode : 1; + int arg_count; + int js_mode; /* not supported for C functions */ /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; @@ -359,6 +353,7 @@ typedef enum { JS_GC_OBJ_TYPE_VAR_REF, JS_GC_OBJ_TYPE_ASYNC_FUNCTION, JS_GC_OBJ_TYPE_JS_CONTEXT, + JS_GC_OBJ_TYPE_MODULE, } JSGCObjectTypeEnum; /* header for GC objects. GC objects are C data structures with a @@ -367,12 +362,24 @@ typedef enum { struct JSGCObjectHeader { int ref_count; /* must come first, 32-bit */ JSGCObjectTypeEnum gc_obj_type : 4; - uint8_t mark : 4; /* used by the GC */ + uint8_t mark : 1; /* used by the GC */ + uint8_t dummy0: 3; uint8_t dummy1; /* not used by the GC */ uint16_t dummy2; /* not used by the GC */ struct list_head link; }; +typedef enum { + JS_WEAKREF_TYPE_MAP, + JS_WEAKREF_TYPE_WEAKREF, + JS_WEAKREF_TYPE_FINREC, +} JSWeakRefHeaderTypeEnum; + +typedef struct { + struct list_head link; + JSWeakRefHeaderTypeEnum weakref_type; +} JSWeakRefHeader; + typedef struct JSVarRef { union { JSGCObjectHeader header; /* must come first */ @@ -384,14 +391,19 @@ typedef struct JSVarRef { }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ - JSValue value; /* used when the variable is no longer on the stack */ + union { + JSValue value; /* used when is_detached = TRUE */ + struct { + struct list_head var_ref_link; /* JSStackFrame.var_ref_list list */ + struct JSAsyncFunctionState *async_func; /* != NULL if async stack frame */ + }; /* used when is_detached = FALSE */ + }; } JSVarRef; -typedef struct JSRefCountHeader { - int ref_count; -} JSRefCountHeader; - /* bigint */ + +#if JS_LIMB_BITS == 32 + typedef int32_t js_slimb_t; typedef uint32_t js_limb_t; typedef int64_t js_sdlimb_t; @@ -399,13 +411,18 @@ typedef uint64_t js_dlimb_t; #define JS_LIMB_DIGITS 9 -/* Must match the size of short_big_int in JSValueUnion */ -#define JS_LIMB_BITS 32 -#define JS_SHORT_BIG_INT_BITS JS_LIMB_BITS -#define JS_BIGINT_MAX_SIZE ((1024 * 1024) / JS_LIMB_BITS) /* in limbs */ -#define JS_SHORT_BIG_INT_MIN INT32_MIN -#define JS_SHORT_BIG_INT_MAX INT32_MAX +#else + +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; +typedef int64_t js_slimb_t; +typedef uint64_t js_limb_t; +typedef int128_t js_sdlimb_t; +typedef uint128_t js_dlimb_t; +#define JS_LIMB_DIGITS 19 + +#endif typedef struct JSBigInt { JSRefCountHeader header; /* must come first, 32-bit */ @@ -421,18 +438,13 @@ typedef struct { /* must come just after */ js_limb_t tab[(64 + JS_LIMB_BITS - 1) / JS_LIMB_BITS]; } JSBigIntBuf; - + typedef enum { JS_AUTOINIT_ID_PROTOTYPE, JS_AUTOINIT_ID_MODULE_NS, JS_AUTOINIT_ID_PROP, - JS_AUTOINIT_ID_BYTECODE, } JSAutoInitIDEnum; -enum { - JS_BUILTIN_ARRAY_FROMASYNC = 1, -}; - /* must be large enough to have a negligible runtime cost and small enough to call the interrupt callback often. */ #define JS_INTERRUPT_COUNTER_INIT 10000 @@ -444,7 +456,14 @@ struct JSContext { uint16_t binary_object_count; int binary_object_size; - + /* TRUE if the array prototype is "normal": + - no small index properties which are get/set or non writable + - its prototype is Object.prototype + - Object.prototype has no small index properties which are get/set or non writable + - the prototype of Object.prototype is null (always true as it is immutable) + */ + uint8_t std_array_prototype; + JSShape *array_shape; /* initial shape for Array objects */ JSValue *class_proto; @@ -454,13 +473,7 @@ struct JSContext { JSValue regexp_ctor; JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; - JSValue error_ctor; - JSValue error_back_trace; - JSValue error_prepare_stack; - JSValue error_stack_trace_limit; JSValue iterator_ctor; - JSValue iterator_ctor_getset; - JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; JSValue throw_type_error; @@ -469,8 +482,6 @@ struct JSContext { JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ - double time_origin; - uint64_t random_state; /* when the counter reaches zero, JSRutime.interrupt_handler is called */ @@ -484,7 +495,7 @@ struct JSContext { /* if NULL, eval is not supported */ JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, - const char *filename, int line, int flags, int scope_idx); + const char *filename, int flags, int scope_idx); void *user_opaque; }; @@ -494,42 +505,6 @@ typedef union JSFloat64Union { uint32_t u32[2]; } JSFloat64Union; -typedef enum { - JS_WEAK_REF_KIND_MAP, - JS_WEAK_REF_KIND_WEAK_REF, - JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY, -} JSWeakRefKindEnum; - -typedef struct JSWeakRefRecord { - JSWeakRefKindEnum kind; - struct JSWeakRefRecord *next_weak_ref; - union { - struct JSMapRecord *map_record; - struct JSWeakRefData *weak_ref_data; - struct JSFinRecEntry *fin_rec_entry; - } u; -} JSWeakRefRecord; - -typedef struct JSMapRecord { - int ref_count; /* used during enumeration to avoid freeing the record */ - bool empty; /* true if the record is deleted */ - struct JSMapState *map; - struct list_head link; - struct list_head hash_link; - JSValue key; - JSValue value; -} JSMapRecord; - -typedef struct JSMapState { - bool is_weak; /* true if WeakSet/WeakMap */ - struct list_head records; /* list of JSMapRecord.link */ - uint32_t record_count; - struct list_head *hash_table; - uint32_t hash_size; /* must be a power of two */ - uint32_t record_count_threshold; /* count at which a hash table - resize is needed */ -} JSMapState; - enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, @@ -537,75 +512,44 @@ enum { JS_ATOM_TYPE_PRIVATE, }; -enum { - JS_ATOM_HASH_SYMBOL, - JS_ATOM_HASH_PRIVATE, -}; - typedef enum { JS_ATOM_KIND_STRING, JS_ATOM_KIND_SYMBOL, JS_ATOM_KIND_PRIVATE, } JSAtomKindEnum; -typedef enum { - JS_STRING_KIND_NORMAL, - JS_STRING_KIND_SLICE, -} JSStringKind; - -#define JS_ATOM_HASH_MASK ((1 << 29) - 1) +#define JS_ATOM_HASH_MASK ((1 << 30) - 1) +#define JS_ATOM_HASH_PRIVATE JS_ATOM_HASH_MASK struct JSString { JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len : 31; uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ - /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, - for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 + /* for JS_ATOM_TYPE_SYMBOL: hash = weakref_count, atom_type = 3, + for JS_ATOM_TYPE_PRIVATE: hash = JS_ATOM_HASH_PRIVATE, atom_type = 3 XXX: could change encoding to have one more bit in hash */ - uint32_t hash : 29; - uint8_t kind : 1; + uint32_t hash : 30; uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ - JSWeakRefRecord *first_weak_ref; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS struct list_head link; /* string list */ #endif + union { + uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */ + uint16_t str16[0]; + } u; }; -typedef struct JSStringSlice { - JSString *parent; - uint32_t start; // in characters, not bytes -} JSStringSlice; - -static inline uint8_t *str8(JSString *p) -{ - JSStringSlice *slice; - - switch (p->kind) { - case JS_STRING_KIND_NORMAL: - return (void *)&p[1]; - case JS_STRING_KIND_SLICE: - slice = (void *)&p[1]; - return str8(slice->parent) + slice->start; - } - abort(); - return NULL; -} - -static inline uint16_t *str16(JSString *p) -{ - JSStringSlice *slice; - - switch (p->kind) { - case JS_STRING_KIND_NORMAL: - return (void *)&p[1]; - case JS_STRING_KIND_SLICE: - slice = (void *)&p[1]; - return str16(slice->parent) + slice->start; - } - abort(); - return NULL; -} +typedef struct JSStringRope { + JSRefCountHeader header; /* must come first, 32-bit */ + uint32_t len; + uint8_t is_wide_char; /* 0 = 8 bits, 1 = 16 bits characters */ + uint8_t depth; /* max depth of the rope tree */ + /* XXX: could reduce memory usage by using a direct pointer with + bit 0 to select rope or string */ + JSValue left; + JSValue right; /* might be the empty string */ +} JSStringRope; typedef struct JSClosureVar { uint8_t is_local : 1; @@ -614,7 +558,7 @@ typedef struct JSClosureVar { uint8_t is_lexical : 1; uint8_t var_kind : 4; /* see JSVarKindEnum */ /* 8 bits available */ - uint16_t var_idx; /* is_local = true: index to a normal variable of the + uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the parent function. otherwise: index to a closure variable of the parent function */ JSAtom var_name; @@ -688,7 +632,7 @@ typedef enum JSFunctionKindEnum { typedef struct JSFunctionBytecode { JSGCObjectHeader header; /* must come first */ - uint8_t is_strict_mode : 1; + uint8_t js_mode; uint8_t has_prototype : 1; /* true if a prototype field is necessary */ uint8_t has_simple_parameter_list : 1; uint8_t is_derived_class_constructor : 1; @@ -699,8 +643,10 @@ typedef struct JSFunctionBytecode { uint8_t super_call_allowed : 1; uint8_t super_allowed : 1; uint8_t arguments_allowed : 1; - uint8_t backtrace_barrier : 1; /* stop backtrace on this function */ - /* XXX: 5 bits available */ + uint8_t has_debug : 1; + uint8_t read_only_bytecode : 1; + uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */ + /* XXX: 10 bits available */ uint8_t *byte_code_buf; /* (self pointer) */ int byte_code_len; JSAtom func_name; @@ -714,20 +660,21 @@ typedef struct JSFunctionBytecode { JSValue *cpool; /* constant pool (self pointer) */ int cpool_count; int closure_var_count; - JSAtom filename; - int line_num; - int col_num; - int source_len; - int pc2line_len; - uint8_t *pc2line_buf; - char *source; + struct { + /* debug info, move to separate structure to save memory? */ + JSAtom filename; + int source_len; + int pc2line_len; + uint8_t *pc2line_buf; + char *source; + } debug; } JSFunctionBytecode; typedef struct JSBoundFunction { JSValue func_obj; JSValue this_val; int argc; - JSValue argv[]; + JSValue argv[0]; } JSBoundFunction; typedef enum JSIteratorKindEnum { @@ -736,23 +683,13 @@ typedef enum JSIteratorKindEnum { JS_ITERATOR_KIND_KEY_AND_VALUE, } JSIteratorKindEnum; -typedef enum JSIteratorHelperKindEnum { - JS_ITERATOR_HELPER_KIND_DROP, - JS_ITERATOR_HELPER_KIND_EVERY, - JS_ITERATOR_HELPER_KIND_FILTER, - JS_ITERATOR_HELPER_KIND_FIND, - JS_ITERATOR_HELPER_KIND_FLAT_MAP, - JS_ITERATOR_HELPER_KIND_FOR_EACH, - JS_ITERATOR_HELPER_KIND_MAP, - JS_ITERATOR_HELPER_KIND_SOME, - JS_ITERATOR_HELPER_KIND_TAKE, -} JSIteratorHelperKindEnum; - typedef struct JSForInIterator { JSValue obj; - bool is_array; - uint32_t array_length; uint32_t idx; + uint32_t atom_count; + uint8_t in_prototype_chain; + uint8_t is_array; + JSPropertyEnum *tab_atom; /* is_array = FALSE */ } JSForInIterator; typedef struct JSRegExp { @@ -784,28 +721,71 @@ typedef struct JSTypedArray { JSObject *buffer; /* based array buffer */ uint32_t offset; /* byte offset in the array buffer */ uint32_t length; /* byte length in the array buffer */ - bool track_rab; /* auto-track length of backing array buffer */ + BOOL track_rab; /* auto-track length of backing array buffer */ } JSTypedArray; typedef struct JSAsyncFunctionState { - JSValue this_val; /* 'this' generator argument */ + JSGCObjectHeader header; + JSValue this_val; /* 'this' argument */ int argc; /* number of function arguments */ - bool throw_flag; /* used to throw an exception in JS_CallInternal() */ + BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */ + BOOL is_completed; /* TRUE if the function has returned. The stack + frame is no longer valid */ + JSValue resolving_funcs[2]; /* only used in JS async functions */ JSStackFrame frame; } JSAsyncFunctionState; -/* XXX: could use an object instead to avoid the - JS_TAG_ASYNC_FUNCTION tag for the GC */ -typedef struct JSAsyncFunctionData { - JSGCObjectHeader header; /* must come first */ - JSValue resolving_funcs[2]; - bool is_active; /* true if the async function state is valid */ - JSAsyncFunctionState func_state; -} JSAsyncFunctionData; +typedef enum { + /* binary operators */ + JS_OVOP_ADD, + JS_OVOP_SUB, + JS_OVOP_MUL, + JS_OVOP_DIV, + JS_OVOP_MOD, + JS_OVOP_POW, + JS_OVOP_OR, + JS_OVOP_AND, + JS_OVOP_XOR, + JS_OVOP_SHL, + JS_OVOP_SAR, + JS_OVOP_SHR, + JS_OVOP_EQ, + JS_OVOP_LESS, + + JS_OVOP_BINARY_COUNT, + /* unary operators */ + JS_OVOP_POS = JS_OVOP_BINARY_COUNT, + JS_OVOP_NEG, + JS_OVOP_INC, + JS_OVOP_DEC, + JS_OVOP_NOT, + + JS_OVOP_COUNT, +} JSOverloadableOperatorEnum; + +typedef struct { + uint32_t operator_index; + JSObject *ops[JS_OVOP_BINARY_COUNT]; /* self operators */ +} JSBinaryOperatorDefEntry; + +typedef struct { + int count; + JSBinaryOperatorDefEntry *tab; +} JSBinaryOperatorDef; + +typedef struct { + uint32_t operator_counter; + BOOL is_primitive; /* OperatorSet for a primitive type */ + /* NULL if no operator is defined */ + JSObject *self_ops[JS_OVOP_COUNT]; /* self operators */ + JSBinaryOperatorDef left; + JSBinaryOperatorDef right; +} JSOperatorSetData; typedef struct JSReqModuleEntry { JSAtom module_name; JSModuleDef *module; /* used using resolution */ + JSValue attributes; /* JS_UNDEFINED or an object contains the attributes as key/value */ } JSReqModuleEntry; typedef enum JSExportTypeEnum { @@ -833,6 +813,7 @@ typedef struct JSStarExportEntry { typedef struct JSImportEntry { int var_idx; /* closure variable index */ + BOOL is_star; /* import_name = '*' is a valid import name, so need a flag */ JSAtom import_name; int req_module_idx; /* in req_module_entries */ } JSImportEntry; @@ -847,7 +828,7 @@ typedef enum { } JSModuleStatus; struct JSModuleDef { - JSRefCountHeader header; /* must come first, 32-bit */ + JSGCObjectHeader header; /* must come first */ JSAtom module_name; struct list_head link; @@ -870,9 +851,9 @@ struct JSModuleDef { JSValue module_ns; JSValue func_obj; /* only used for JS modules */ JSModuleInitFunc *init_func; /* only used for C modules */ - bool has_tla; /* true if func_obj contains await */ - bool resolved; - bool func_created; + BOOL has_tla : 8; /* true if func_obj contains await */ + BOOL resolved : 8; + BOOL func_created : 8; JSModuleStatus status : 8; /* temp use during js_module_link() & js_module_evaluate() */ int dfs_index, dfs_ancestor_index; @@ -882,24 +863,27 @@ struct JSModuleDef { int async_parent_modules_count; int async_parent_modules_size; int pending_async_dependencies; - bool async_evaluation; + BOOL async_evaluation; /* true: async_evaluation_timestamp corresponds to [[AsyncEvaluationOrder]] + false: [[AsyncEvaluationOrder]] is UNSET or DONE */ int64_t async_evaluation_timestamp; JSModuleDef *cycle_root; JSValue promise; /* corresponds to spec field: capability */ JSValue resolving_funcs[2]; /* corresponds to spec field: capability */ + /* true if evaluation yielded an exception. It is saved in eval_exception */ - bool eval_has_exception; + BOOL eval_has_exception : 8; JSValue eval_exception; JSValue meta_obj; /* for import.meta */ + JSValue private_value; /* private value for C modules */ }; typedef struct JSJobEntry { struct list_head link; - JSContext *ctx; + JSContext *realm; JSJobFunc *job_func; int argc; - JSValue argv[]; + JSValue argv[0]; } JSJobEntry; typedef struct JSProperty { @@ -922,7 +906,6 @@ typedef struct JSProperty { #define JS_PROP_INITIAL_SIZE 2 #define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */ -#define JS_ARRAY_INITIAL_SIZE 2 typedef struct JSShapeProperty { uint32_t hash_next : 26; /* 0 if last in list */ @@ -937,10 +920,6 @@ struct JSShape { /* true if the shape is inserted in the shape hash table. If not, JSShape.hash is not valid */ uint8_t is_hashed; - /* If true, the shape may have small array index properties 'n' with 0 - <= n <= 2^31-1. If false, the shape is guaranteed not to have - small array index properties */ - uint8_t has_small_array_index; uint32_t hash; /* current hash value */ uint32_t prop_hash_mask; int prop_size; /* allocated properties */ @@ -948,7 +927,7 @@ struct JSShape { int deleted_prop_count; JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ JSObject *proto; - JSShapeProperty prop[]; /* prop_size elements */ + JSShapeProperty prop[0]; /* prop_size elements */ }; struct JSObject { @@ -956,25 +935,26 @@ struct JSObject { JSGCObjectHeader header; struct { int __gc_ref_count; /* corresponds to header.ref_count */ - uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ + uint8_t __gc_mark : 7; /* corresponds to header.mark/gc_obj_type */ + uint8_t is_prototype : 1; /* object may be used as prototype */ uint8_t extensible : 1; uint8_t free_mark : 1; /* only used when freeing objects with cycles */ - uint8_t is_exotic : 1; /* true if object has exotic property handlers */ - uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */ - uint8_t is_constructor : 1; /* true if object is a constructor function */ - uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */ + uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */ + uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */ + uint8_t is_constructor : 1; /* TRUE if object is a constructor function */ + uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */ uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */ uint16_t class_id; /* see JS_CLASS_x */ }; }; - /* byte offsets: 16/24 */ + /* count the number of weak references to this object. The object + structure is freed only if header.ref_count = 0 and + weakref_count = 0 */ + uint32_t weakref_count; JSShape *shape; /* prototype and property names + flag */ JSProperty *prop; /* array of properties */ - /* byte offsets: 24/40 */ - JSWeakRefRecord *first_weak_ref; - /* byte offsets: 28/48 */ union { void *opaque; struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ @@ -987,13 +967,12 @@ struct JSObject { struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */ struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */ struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */ - struct JSIteratorConcatData *iterator_concat_data; /* JS_CLASS_ITERATOR_CONCAT */ struct JSIteratorHelperData *iterator_helper_data; /* JS_CLASS_ITERATOR_HELPER */ struct JSIteratorWrapData *iterator_wrap_data; /* JS_CLASS_ITERATOR_WRAP */ struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */ struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */ struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */ - struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */ + struct JSAsyncFunctionState *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */ struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */ struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */ struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */ @@ -1035,17 +1014,28 @@ struct JSObject { JSRegExp regexp; /* JS_CLASS_REGEXP: 8/16 bytes */ JSValue object_data; /* for JS_SetObjectData(): 8/16/16 bytes */ } u; - /* byte sizes: 40/48/72 */ }; -typedef struct JSCallSiteData { - JSValue filename; - JSValue func; - JSValue func_name; - bool native; - int line_num; - int col_num; -} JSCallSiteData; +typedef struct JSMapRecord { + int ref_count; /* used during enumeration to avoid freeing the record */ + BOOL empty : 8; /* TRUE if the record is deleted */ + struct list_head link; + struct JSMapRecord *hash_next; + JSValue key; + JSValue value; +} JSMapRecord; + +typedef struct JSMapState { + BOOL is_weak; /* TRUE if WeakSet/WeakMap */ + struct list_head records; /* list of JSMapRecord.link */ + uint32_t record_count; + JSMapRecord **hash_table; + int hash_bits; + uint32_t hash_size; /* = 2 ^ hash_bits */ + uint32_t record_count_threshold; /* count at which a hash table + resize is needed */ + JSWeakRefHeader weakref_header; /* only used if is_weak = TRUE */ +} JSMapState; enum { __JS_ATOM_NULL = JS_ATOM_NULL, @@ -1071,7 +1061,7 @@ typedef enum OPCodeFormat { #undef FMT } OPCodeFormat; -typedef enum OPCodeEnum { +enum OPCodeEnum { #define FMT(f) #define DEF(id, size, n_pop, n_push, f) OP_ ## id, #define def(id, size, n_pop, n_push, f) @@ -1091,7 +1081,7 @@ typedef enum OPCodeEnum { #undef DEF #undef FMT OP_TEMP_END, -} OPCodeEnum; +}; static int JS_InitAtoms(JSRuntime *rt); static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, @@ -1106,86 +1096,79 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, int argc, JSValueConst *argv, int flags); static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, JSValueConst new_target, - int argc, JSValueConst *argv, int flags); + int argc, JSValue *argv, int flags); static JSValue JS_CallConstructorInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, - int argc, JSValueConst *argv, int flags); + int argc, JSValue *argv, int flags); static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj, int argc, JSValueConst *argv); static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, int argc, JSValueConst *argv); static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, - JSValue val, bool is_array_ctor); + JSValue val, BOOL is_array_ctor); static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, JSValueConst val, int flags, int scope_idx); -JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); - -static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p); +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); +static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); +static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p); static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt); static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p); static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p); -static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val); -static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); +static __maybe_unused void JS_DumpValueRT(JSRuntime *rt, const char *str, JSValueConst val); +static __maybe_unused void JS_DumpValue(JSContext *ctx, const char *str, JSValueConst val); static __maybe_unused void JS_DumpShapes(JSRuntime *rt); - +static void js_dump_value_write(void *opaque, const char *buf, size_t len); static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); -static void js_array_finalizer(JSRuntime *rt, JSValueConst val); -static void js_array_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -static void js_object_data_finalizer(JSRuntime *rt, JSValueConst val); -static void js_object_data_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -static void js_c_function_finalizer(JSRuntime *rt, JSValueConst val); -static void js_c_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -static void js_bytecode_function_finalizer(JSRuntime *rt, JSValueConst val); +static void js_array_finalizer(JSRuntime *rt, JSValue val); +static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_object_data_finalizer(JSRuntime *rt, JSValue val); +static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_c_function_finalizer(JSRuntime *rt, JSValue val); +static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val); static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_bound_function_finalizer(JSRuntime *rt, JSValueConst val); +static void js_bound_function_finalizer(JSRuntime *rt, JSValue val); static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValueConst val); +static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_regexp_finalizer(JSRuntime *rt, JSValueConst val); -static void js_array_buffer_finalizer(JSRuntime *rt, JSValueConst val); -static void js_typed_array_finalizer(JSRuntime *rt, JSValueConst val); +static void js_regexp_finalizer(JSRuntime *rt, JSValue val); +static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val); +static void js_typed_array_finalizer(JSRuntime *rt, JSValue val); static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_proxy_finalizer(JSRuntime *rt, JSValueConst val); +static void js_proxy_finalizer(JSRuntime *rt, JSValue val); static void js_proxy_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_map_finalizer(JSRuntime *rt, JSValueConst val); +static void js_map_finalizer(JSRuntime *rt, JSValue val); static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_map_iterator_finalizer(JSRuntime *rt, JSValueConst val); +static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_array_iterator_finalizer(JSRuntime *rt, JSValueConst val); +static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_iterator_concat_finalizer(JSRuntime *rt, JSValueConst val); -static void js_iterator_concat_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -static void js_iterator_helper_finalizer(JSRuntime *rt, JSValueConst val); +static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val); static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValueConst val); +static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val); static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_regexp_string_iterator_finalizer(JSRuntime *rt, - JSValueConst val); +static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_generator_finalizer(JSRuntime *rt, JSValueConst val); +static void js_generator_finalizer(JSRuntime *rt, JSValue obj); static void js_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_promise_finalizer(JSRuntime *rt, JSValueConst val); +static void js_promise_finalizer(JSRuntime *rt, JSValue val); static void js_promise_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValueConst val); +static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val); static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -1207,14 +1190,6 @@ static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, static void gc_decref(JSRuntime *rt); static int JS_NewClass1(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, JSAtom name); -static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int unshift); -static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv); -static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv, int magic); -static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic); typedef enum JSStrictEqModeEnum { JS_EQ_STRICT, @@ -1222,42 +1197,36 @@ typedef enum JSStrictEqModeEnum { JS_EQ_SAME_VALUE_ZERO, } JSStrictEqModeEnum; -static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, +static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode); -static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2); -static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2); -static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2); +static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2); +static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2); +static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2); +static JSValue JS_ToObject(JSContext *ctx, JSValueConst val); static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); JSValue JS_ThrowOutOfMemory(JSContext *ctx); static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); -static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); -static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, - JSValueConst proto_val, bool throw_flag); -static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); -static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj); -static int js_proxy_isArray(JSContext *ctx, JSValueConst obj); + +static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception); static int JS_CreateProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags); -static int js_string_memcmp(JSString *p1, JSString *p2, int len); -static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref); -static bool is_valid_weakref_target(JSValueConst val); -static void insert_weakref_record(JSValueConst target, - struct JSWeakRefRecord *wr); +static int js_string_memcmp(const JSString *p1, int pos1, const JSString *p2, + int pos2, int len); static JSValue js_array_buffer_constructor3(JSContext *ctx, JSValueConst new_target, uint64_t len, uint64_t *max_len, JSClassID class_id, uint8_t *buf, JSFreeArrayBufferDataFunc *free_func, - void *opaque, bool alloc_flag); + void *opaque, BOOL alloc_flag); static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr); static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); -static bool array_buffer_is_resizable(const JSArrayBuffer *abuf); +static BOOL array_buffer_is_resizable(const JSArrayBuffer *abuf); static JSValue js_typed_array_constructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, @@ -1266,29 +1235,29 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, JSValueConst new_target, JSValueConst src_obj, int classid, uint32_t len); -static bool is_typed_array(JSClassID class_id); -static bool typed_array_is_oob(JSObject *p); -static uint32_t typed_array_length(JSObject *p); +static BOOL typed_array_is_oob(JSObject *p); +static int js_typed_array_get_length_unsafe(JSContext *ctx, JSValueConst obj); static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx); static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, - bool is_arg); + BOOL is_arg); +static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s); +static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s); static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags); -static void js_async_function_resolve_finalizer(JSRuntime *rt, - JSValueConst val); +static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val); static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, - const char *filename, int line, int flags, int scope_idx); -static void js_free_module_def(JSContext *ctx, JSModuleDef *m); + const char *filename, int flags, int scope_idx); +static void js_free_module_def(JSRuntime *rt, JSModuleDef *m); static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkFunc *mark_func); static JSValue js_import_meta(JSContext *ctx); -static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, @@ -1301,21 +1270,18 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); -static JSValue js_promise_resolve_thenable_job(JSContext *ctx, - int argc, JSValueConst *argv); -static bool js_string_eq(JSString *p1, JSString *p2); -static int js_string_compare(JSString *p1, JSString *p2); +static int js_string_compare(JSContext *ctx, + const JSString *p1, const JSString *p2); +static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val); static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop, JSValue val, int flags); static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val); -static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val); +static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val); static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop); static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc); -static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, - JS_MarkFunc *mark_func); -static void JS_AddIntrinsicBasicObjects(JSContext *ctx); +static int JS_AddIntrinsicBasicObjects(JSContext *ctx); static void js_free_shape(JSRuntime *rt, JSShape *sh); static void js_free_shape_null(JSRuntime *rt, JSShape *sh); static int js_shape_prepare_update(JSContext *ctx, JSObject *p, @@ -1325,150 +1291,63 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, JSValueConst obj); static __exception int js_get_length64(JSContext *ctx, int64_t *pres, JSValueConst obj); -static __exception int js_set_length64(JSContext *ctx, JSValueConst obj, - int64_t len); static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len); static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, JSValueConst array_arg); -static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab); -static bool js_get_fast_array(JSContext *ctx, JSValue obj, +static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp); -static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len); static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, - JSValue sync_iter); -static void js_c_function_data_finalizer(JSRuntime *rt, JSValueConst val); + JSValueConst sync_iter); +static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val); static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags); -static JSAtom js_symbol_to_atom(JSContext *ctx, JSValueConst val); +static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val); static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type); static void remove_gc_object(JSGCObjectHeader *h); -static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s); static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); - -static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, - bool flag); - -static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd); -static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf); -static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num); -static void _JS_AddIntrinsicCallSite(JSContext *ctx); - -static void JS_SetOpaqueInternal(JSValueConst obj, void *opaque); +static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int is_map); +static void map_delete_weakrefs(JSRuntime *rt, JSWeakRefHeader *wh); +static void weakref_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh); +static void finrec_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh); +static void JS_RunGCInternal(JSRuntime *rt, BOOL remove_weak_objects); +static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen, + JSValueConst obj, JSValueConst method); +static int js_string_find_invalid_codepoint(JSString *p); +static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv); +static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int magic); +static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv); static const JSClassExoticMethods js_arguments_exotic_methods; static const JSClassExoticMethods js_string_exotic_methods; static const JSClassExoticMethods js_proxy_exotic_methods; static const JSClassExoticMethods js_module_ns_exotic_methods; - -static inline bool double_is_int32(double d) -{ - uint64_t u, e; - JSFloat64Union t; - - t.d = d; - u = t.u64; - - e = ((u >> 52) & 0x7FF) - 1023; - if (e > 30) { - // accept 0, INT32_MIN, reject too large, too small, nan, inf, -0 - return !u || (u == 0xc1e0000000000000); - } else { - // shift out sign, exponent and whole part bits - // value is fractional if remaining low bits are non-zero - return !(u << 12 << e); - } -} - -static JSValue js_float64(double d) -{ - return __JS_NewFloat64(d); -} - -static int compare_u32(uint32_t a, uint32_t b) -{ - return -(a < b) + (b < a); // -1, 0 or 1 -} - -static JSValue js_int32(int32_t v) -{ - return JS_MKVAL(JS_TAG_INT, v); -} - -static JSValue js_uint32(uint32_t v) -{ - if (v <= INT32_MAX) - return js_int32(v); - else - return js_float64(v); -} - -static JSValue js_int64(int64_t v) -{ - if (v >= INT32_MIN && v <= INT32_MAX) - return js_int32(v); - else - return js_float64(v); -} - -static JSValue js_number(double d) -{ - if (double_is_int32(d)) - return js_int32((int32_t)d); - else - return js_float64(d); -} - -JSValue JS_NewNumber(JSContext *ctx, double d) -{ - return js_number(d); -} - -static JSValue js_bool(bool v) -{ - return JS_MKVAL(JS_TAG_BOOL, (v != 0)); -} - -static JSValue js_dup(JSValueConst v) -{ - if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - p->ref_count++; - } - return unsafe_unconst(v); -} - -JSValue JS_DupValue(JSContext *ctx, JSValueConst v) -{ - return js_dup(v); -} - -JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) -{ - return js_dup(v); -} +static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT; static void js_trigger_gc(JSRuntime *rt, size_t size) { - bool force_gc; + BOOL force_gc; #ifdef FORCE_GC_AT_MALLOC - force_gc = true; + force_gc = TRUE; #else force_gc = ((rt->malloc_state.malloc_size + size) > rt->malloc_gc_threshold); #endif if (force_gc) { -#ifdef ENABLE_DUMPS // JS_DUMP_GC - if (check_dump_flag(rt, JS_DUMP_GC)) { - printf("GC: size=%zd\n", rt->malloc_state.malloc_size); - } +#ifdef DUMP_GC + printf("GC: size=%" PRIu64 "\n", + (uint64_t)rt->malloc_state.malloc_size); #endif JS_RunGC(rt); rt->malloc_gc_threshold = rt->malloc_state.malloc_size + @@ -1481,93 +1360,19 @@ static size_t js_malloc_usable_size_unknown(const void *ptr) return 0; } -void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size) -{ - void *ptr; - JSMallocState *s; - - /* Do not allocate zero bytes: behavior is platform dependent */ - assert(count != 0 && size != 0); - - if (size > 0) - if (unlikely(count != (count * size) / size)) - return NULL; - - s = &rt->malloc_state; - /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ - if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1)) - return NULL; - - ptr = rt->mf.js_calloc(s->opaque, count, size); - if (!ptr) - return NULL; - - s->malloc_count++; - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - return ptr; -} - void *js_malloc_rt(JSRuntime *rt, size_t size) { - void *ptr; - JSMallocState *s; - - /* Do not allocate zero bytes: behavior is platform dependent */ - assert(size != 0); - - s = &rt->malloc_state; - /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ - if (unlikely(s->malloc_size + size > s->malloc_limit - 1)) - return NULL; - - ptr = rt->mf.js_malloc(s->opaque, size); - if (!ptr) - return NULL; - - s->malloc_count++; - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - return ptr; + return rt->mf.js_malloc(&rt->malloc_state, size); } void js_free_rt(JSRuntime *rt, void *ptr) { - JSMallocState *s; - - if (!ptr) - return; - - s = &rt->malloc_state; - s->malloc_count--; - s->malloc_size -= rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - rt->mf.js_free(s->opaque, ptr); + rt->mf.js_free(&rt->malloc_state, ptr); } void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size) { - size_t old_size; - JSMallocState *s; - - if (!ptr) { - if (size == 0) - return NULL; - return js_malloc_rt(rt, size); - } - if (unlikely(size == 0)) { - js_free_rt(rt, ptr); - return NULL; - } - old_size = rt->mf.js_malloc_usable_size(ptr); - s = &rt->malloc_state; - /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ - if (s->malloc_size + size - old_size > s->malloc_limit - 1) - return NULL; - - ptr = rt->mf.js_realloc(s->opaque, ptr, size); - if (!ptr) - return NULL; - - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) - old_size; - return ptr; + return rt->mf.js_realloc(&rt->malloc_state, ptr, size); } size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr) @@ -1575,28 +1380,13 @@ size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr) return rt->mf.js_malloc_usable_size(ptr); } -/** - * This used to be implemented as malloc + memset, but using calloc - * yields better performance in initial, bursty allocations, something useful - * for QuickJS. - * - * More information: https://github.com/quickjs-ng/quickjs/pull/519 - */ void *js_mallocz_rt(JSRuntime *rt, size_t size) -{ - return js_calloc_rt(rt, 1, size); -} - -/* Throw out of memory in case of error */ -void *js_calloc(JSContext *ctx, size_t count, size_t size) { void *ptr; - ptr = js_calloc_rt(ctx->rt, count, size); - if (unlikely(!ptr)) { - JS_ThrowOutOfMemory(ctx); + ptr = js_malloc_rt(rt, size); + if (!ptr) return NULL; - } - return ptr; + return memset(ptr, 0, size); } /* Throw out of memory in case of error */ @@ -1705,22 +1495,34 @@ static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size, return 0; } -static void *js_dbuf_realloc(void *ctx, void *ptr, size_t size) +static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) { - return js_realloc(ctx, ptr, size); + dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt); } -static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) +static void *js_realloc_bytecode_rt(void *opaque, void *ptr, size_t size) { - dbuf_init2(s, ctx, js_dbuf_realloc); + JSRuntime *rt = opaque; + if (size > (INT32_MAX / 2)) { + /* the bytecode cannot be larger than 2G. Leave some slack to + avoid some overflows. */ + return NULL; + } else { + return rt->mf.js_realloc(&rt->malloc_state, ptr, size); + } +} + +static inline void js_dbuf_bytecode_init(JSContext *ctx, DynBuf *s) +{ + dbuf_init2(s, ctx->rt, js_realloc_bytecode_rt); } static inline int is_digit(int c) { return c >= '0' && c <= '9'; } -static inline int string_get(JSString *p, int idx) { - return p->is_wide_char ? str16(p)[idx] : str8(p)[idx]; +static inline int string_get(const JSString *p, int idx) { + return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx]; } typedef struct JSClassShortDef { @@ -1766,10 +1568,9 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */ { JS_ATOM_Map, js_map_finalizer, js_map_mark }, /* JS_CLASS_MAP */ { JS_ATOM_Set, js_map_finalizer, js_map_mark }, /* JS_CLASS_SET */ - { JS_ATOM_WeakMap, js_map_finalizer, NULL }, /* JS_CLASS_WEAKMAP */ - { JS_ATOM_WeakSet, js_map_finalizer, NULL }, /* JS_CLASS_WEAKSET */ + { JS_ATOM_WeakMap, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKMAP */ + { JS_ATOM_WeakSet, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKSET */ { JS_ATOM_Iterator, NULL, NULL }, /* JS_CLASS_ITERATOR */ - { JS_ATOM_IteratorConcat, js_iterator_concat_finalizer, js_iterator_concat_mark }, /* JS_CLASS_ITERATOR_CONCAT */ { JS_ATOM_IteratorHelper, js_iterator_helper_finalizer, js_iterator_helper_mark }, /* JS_CLASS_ITERATOR_HELPER */ { JS_ATOM_IteratorWrap, js_iterator_wrap_finalizer, js_iterator_wrap_mark }, /* JS_CLASS_ITERATOR_WRAP */ { JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */ @@ -1797,31 +1598,53 @@ static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab, return 0; } -/* Uses code from LLVM project. */ +#if !defined(CONFIG_STACK_CHECK) +/* no stack limitation */ +static inline uintptr_t js_get_stack_pointer(void) +{ + return 0; +} + +static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) +{ + return FALSE; +} +#else + +#if !defined(__has_builtin) + #define __has_builtin(x) 0 +#endif + +#if defined(__GNUC__) || defined(__clang__) || __has_builtin(__builtin_frame_address) +/* Note: OS and CPU dependent */ static inline uintptr_t js_get_stack_pointer(void) { -#if defined(__clang__) || defined(__GNUC__) return (uintptr_t)__builtin_frame_address(0); -#elif defined(_MSC_VER) +} +#elif defined(_MSC_VER) && !defined(__clang__) +static inline uintptr_t js_get_stack_pointer(void) +{ return (uintptr_t)_AddressOfReturnAddress(); +} #else - char CharOnStack = 0; - // The volatile store here is intended to escape the local variable, to - // prevent the compiler from optimizing CharOnStack into anything other - // than a char on the stack. - // - // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19. - char *volatile Ptr = &CharOnStack; - return (uintptr_t) Ptr; -#endif +static inline uintptr_t js_get_stack_pointer(void) +{ + return 0; } +#define NO_VALID_STACK_POINTER +#endif -static inline bool js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) +static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) { +#if defined(NO_VALID_STACK_POINTER) + return FALSE; +#else uintptr_t sp; sp = js_get_stack_pointer() - alloca_size; return unlikely(sp < rt->stack_limit); +#endif } +#endif JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) { @@ -1830,19 +1653,17 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) memset(&ms, 0, sizeof(ms)); ms.opaque = opaque; - ms.malloc_limit = 0; + ms.malloc_limit = -1; - rt = mf->js_calloc(opaque, 1, sizeof(JSRuntime)); + rt = mf->js_malloc(&ms, sizeof(JSRuntime)); if (!rt) return NULL; + memset(rt, 0, sizeof(*rt)); rt->mf = *mf; if (!rt->mf.js_malloc_usable_size) { /* use dummy function if none provided */ rt->mf.js_malloc_usable_size = js_malloc_usable_size_unknown; } - /* Inline what js_malloc_rt does since we cannot use it here. */ - ms.malloc_count++; - ms.malloc_size += rt->mf.js_malloc_usable_size(rt) + MALLOC_OVERHEAD; rt->malloc_state = ms; rt->malloc_gc_threshold = 256 * 1024; @@ -1850,8 +1671,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) init_list_head(&rt->gc_obj_list); init_list_head(&rt->gc_zero_ref_count_list); rt->gc_phase = JS_GC_PHASE_NONE; + init_list_head(&rt->weakref_list); -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS init_list_head(&rt->string_list); #endif init_list_head(&rt->job_list); @@ -1874,13 +1696,7 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) if (init_shape_hash(rt)) goto fail; - rt->js_class_id_alloc = JS_CLASS_INIT_COUNT; - rt->stack_size = JS_DEFAULT_STACK_SIZE; -#ifdef __wasi__ - rt->stack_size = 0; -#endif - JS_UpdateStackTop(rt); rt->current_exception = JS_UNINITIALIZED; @@ -1901,45 +1717,84 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque) rt->user_opaque = opaque; } -int JS_AddRuntimeFinalizer(JSRuntime *rt, JSRuntimeFinalizer *finalizer, - void *arg) +/* default memory allocation functions with memory limitation */ +static size_t js_def_malloc_usable_size(const void *ptr) { - JSRuntimeFinalizerState *fs = js_malloc_rt(rt, sizeof(*fs)); - if (!fs) - return -1; - fs->next = rt->finalizers; - fs->finalizer = finalizer; - fs->arg = arg; - rt->finalizers = fs; +#if defined(__APPLE__) + return malloc_size(ptr); +#elif defined(_WIN32) + return _msize((void *)ptr); +#elif defined(EMSCRIPTEN) || defined(__OpenBSD__) || defined(__NetBSD__) return 0; +#elif defined(__linux__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__GLIBC__) + return malloc_usable_size((void *)ptr); +#else + /* change this to `return 0;` if compilation fails */ + return malloc_usable_size((void *)ptr); +#endif } -static void *js_def_calloc(void *opaque, size_t count, size_t size) +static void *js_def_malloc(JSMallocState *s, size_t size) { - return calloc(count, size); -} + void *ptr; -static void *js_def_malloc(void *opaque, size_t size) -{ - return malloc(size); + /* Do not allocate zero bytes: behavior is platform dependent */ + assert(size != 0); + + if (unlikely(s->malloc_size + size > s->malloc_limit)) + return NULL; + + ptr = malloc(size); + if (!ptr) + return NULL; + + s->malloc_count++; + s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + return ptr; } -static void js_def_free(void *opaque, void *ptr) +static void js_def_free(JSMallocState *s, void *ptr) { + if (!ptr) + return; + + s->malloc_count--; + s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; free(ptr); } -static void *js_def_realloc(void *opaque, void *ptr, size_t size) +static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size) { - return realloc(ptr, size); + size_t old_size; + + if (!ptr) { + if (size == 0) + return NULL; + return js_def_malloc(s, size); + } + old_size = js_def_malloc_usable_size(ptr); + if (size == 0) { + s->malloc_count--; + s->malloc_size -= old_size + MALLOC_OVERHEAD; + free(ptr); + return NULL; + } + if (s->malloc_size + size - old_size > s->malloc_limit) + return NULL; + + ptr = realloc(ptr, size); + if (!ptr) + return NULL; + + s->malloc_size += js_def_malloc_usable_size(ptr) - old_size; + return ptr; } static const JSMallocFunctions def_malloc_funcs = { - js_def_calloc, js_def_malloc, js_def_free, js_def_realloc, - js__malloc_usable_size + js_def_malloc_usable_size, }; JSRuntime *JS_NewRuntime(void) @@ -1952,26 +1807,6 @@ void JS_SetMemoryLimit(JSRuntime *rt, size_t limit) rt->malloc_state.malloc_limit = limit; } -void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags) -{ -#ifdef ENABLE_DUMPS - rt->dump_flags = flags; -#endif -} - -uint64_t JS_GetDumpFlags(JSRuntime *rt) -{ -#ifdef ENABLE_DUMPS - return rt->dump_flags; -#else - return 0; -#endif -} - -size_t JS_GetGCThreshold(JSRuntime *rt) { - return rt->malloc_gc_threshold; -} - /* use -1 to disable automatic GC */ void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold) { @@ -1988,7 +1823,7 @@ void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque) rt->interrupt_opaque = opaque; } -void JS_SetCanBlock(JSRuntime *rt, bool can_block) +void JS_SetCanBlock(JSRuntime *rt, BOOL can_block) { rt->can_block = can_block; } @@ -1999,6 +1834,16 @@ void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, rt->sab_funcs = *sf; } +void JS_SetStripInfo(JSRuntime *rt, int flags) +{ + rt->strip_flags = flags; +} + +int JS_GetStripInfo(JSRuntime *rt) +{ + return rt->strip_flags; +} + /* return 0 if OK, < 0 if exception */ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv) @@ -2007,28 +1852,29 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, JSJobEntry *e; int i; - assert(!rt->in_free); - e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue)); if (!e) return -1; - e->ctx = ctx; + e->realm = JS_DupContext(ctx); e->job_func = job_func; e->argc = argc; for(i = 0; i < argc; i++) { - e->argv[i] = js_dup(argv[i]); + e->argv[i] = JS_DupValue(ctx, argv[i]); } list_add_tail(&e->link, &rt->job_list); return 0; } -bool JS_IsJobPending(JSRuntime *rt) +BOOL JS_IsJobPending(JSRuntime *rt) { return !list_empty(&rt->job_list); } /* return < 0 if exception, 0 if no job pending, 1 if a job was - executed successfully. the context of the job is stored in '*pctx' */ + executed successfully. The context of the job is stored in '*pctx' + if pctx != NULL. It may be NULL if the context was already + destroyed or if no job was pending. The 'pctx' parameter is now + absolete. */ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) { JSContext *ctx; @@ -2037,15 +1883,16 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) int i, ret; if (list_empty(&rt->job_list)) { - *pctx = NULL; + if (pctx) + *pctx = NULL; return 0; } /* get the first pending job and execute it */ e = list_entry(rt->job_list.next, JSJobEntry, link); list_del(&e->link); - ctx = e->ctx; - res = e->job_func(e->ctx, e->argc, vc(e->argv)); + ctx = e->realm; + res = e->job_func(ctx, e->argc, (JSValueConst *)e->argv); for(i = 0; i < e->argc; i++) JS_FreeValue(ctx, e->argv[i]); if (JS_IsException(res)) @@ -2054,7 +1901,13 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) ret = 1; JS_FreeValue(ctx, res); js_free(ctx, e); - *pctx = ctx; + if (pctx) { + if (ctx->header.ref_count > 1) + *pctx = ctx; + else + *pctx = NULL; + } + JS_FreeContext(ctx); return ret; } @@ -2063,7 +1916,7 @@ static inline uint32_t atom_get_free(const JSAtomStruct *p) return (uintptr_t)p >> 1; } -static inline bool atom_is_free(const JSAtomStruct *p) +static inline BOOL atom_is_free(const JSAtomStruct *p) { return (uintptr_t)p & 1; } @@ -2083,11 +1936,10 @@ static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char str->header.ref_count = 1; str->is_wide_char = is_wide_char; str->len = max_len; - str->kind = JS_STRING_KIND_NORMAL; str->atom_type = 0; str->hash = 0; /* optional but costless */ str->hash_next = 0; /* optional */ -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_add_tail(&str->link, &rt->string_list); #endif return str; @@ -2104,28 +1956,18 @@ static JSString *js_alloc_string(JSContext *ctx, int max_len, int is_wide_char) return p; } -static inline void js_free_string0(JSRuntime *rt, JSString *str); - /* same as JS_FreeValueRT() but faster */ static inline void js_free_string(JSRuntime *rt, JSString *str) { - if (--str->header.ref_count <= 0) - js_free_string0(rt, str); -} - -static inline void js_free_string0(JSRuntime *rt, JSString *str) -{ - if (str->atom_type) { - JS_FreeAtomStruct(rt, str); - } else { -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS - list_del(&str->link); + if (--str->header.ref_count <= 0) { + if (str->atom_type) { + JS_FreeAtomStruct(rt, str); + } else { +#ifdef DUMP_LEAKS + list_del(&str->link); #endif - if (str->kind == JS_STRING_KIND_SLICE) { - JSStringSlice *slice = (void *)&str[1]; - js_free_string(rt, slice->parent); // safe, recurses only 1 level + js_free_rt(rt, str); } - js_free_rt(rt, str); } } @@ -2145,23 +1987,25 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) struct list_head *el, *el1; int i; - rt->in_free = true; JS_FreeValueRT(rt, rt->current_exception); list_for_each_safe(el, el1, &rt->job_list) { JSJobEntry *e = list_entry(el, JSJobEntry, link); for(i = 0; i < e->argc; i++) JS_FreeValueRT(rt, e->argv[i]); + JS_FreeContext(e->realm); js_free_rt(rt, e); } init_list_head(&rt->job_list); - JS_RunGC(rt); + /* don't remove the weak objects to avoid create new jobs with + FinalizationRegistry */ + JS_RunGCInternal(rt, FALSE); -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS /* leaking objects */ - if (check_dump_flag(rt, JS_DUMP_LEAKS)) { - bool header_done; + { + BOOL header_done; JSGCObjectHeader *p; int count; @@ -2173,14 +2017,14 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) } gc_decref(rt); - header_done = false; + header_done = FALSE; list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); if (p->ref_count != 0) { if (!header_done) { printf("Object leaks:\n"); JS_DumpObjectHeader(rt); - header_done = true; + header_done = TRUE; } JS_DumpGCObject(rt, p); } @@ -2197,12 +2041,16 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) printf("Secondary object leaks: %d\n", count); } #endif - if (!list_empty(&rt->gc_obj_list)) { if (gc_leak_handler != NULL) { gc_leak_handler("gc_obj_list is not empty"); } } + if (!list_empty(&rt->weakref_list)) { + if (gc_leak_handler != NULL) { + gc_leak_handler("weakref_list is not empty"); + } + } /* free the classes */ for(i = 0; i < rt->class_count; i++) { @@ -2213,17 +2061,17 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) } js_free_rt(rt, rt->class_array); -#ifdef ENABLE_DUMPS // JS_DUMP_ATOM_LEAKS +#ifdef DUMP_LEAKS /* only the atoms defined in JS_InitAtoms() should be left */ - if (check_dump_flag(rt, JS_DUMP_ATOM_LEAKS)) { - bool header_done = false; + { + BOOL header_done = FALSE; for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p) /* && p->str*/) { if (i >= JS_ATOM_END || p->header.ref_count != 1) { if (!header_done) { - header_done = true; + header_done = TRUE; if (rt->rt_info) { printf("%s:1: atom leakage:", rt->rt_info); } else { @@ -2247,7 +2095,7 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) printf(")"); break; case JS_ATOM_TYPE_SYMBOL: - if (p->hash == JS_ATOM_HASH_SYMBOL) { + if (p->hash != JS_ATOM_HASH_PRIVATE) { printf("Symbol("); JS_DumpString(rt, p); printf(")"); @@ -2275,7 +2123,7 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p)) { -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_del(&p->link); #endif js_free_rt(rt, p); @@ -2284,8 +2132,8 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) js_free_rt(rt, rt->atom_array); js_free_rt(rt, rt->atom_hash); js_free_rt(rt, rt->shape_hash); -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS - if (check_dump_flag(rt, JS_DUMP_LEAKS) && !list_empty(&rt->string_list)) { +#ifdef DUMP_LEAKS + if (!list_empty(&rt->string_list)) { if (rt->rt_info) { printf("%s:1: string leakage:", rt->rt_info); } else { @@ -2312,31 +2160,21 @@ void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)) if (rt->rt_info) printf("\n"); } -#endif - - while (rt->finalizers) { - JSRuntimeFinalizerState *fs = rt->finalizers; - rt->finalizers = fs->next; - fs->finalizer(rt, fs->arg); - js_free_rt(rt, fs); - } - -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS - if (check_dump_flag(rt, JS_DUMP_LEAKS)) { + { JSMallocState *s = &rt->malloc_state; if (s->malloc_count > 1) { if (rt->rt_info) printf("%s:1: ", rt->rt_info); - printf("Memory leak: %zd bytes lost in %zd block%s\n", - s->malloc_size - sizeof(JSRuntime), - s->malloc_count - 1, &"s"[s->malloc_count == 2]); + printf("Memory leak: %"PRIu64" bytes lost in %"PRIu64" block%s\n", + (uint64_t)(s->malloc_size - sizeof(JSRuntime)), + (uint64_t)(s->malloc_count - 1), &"s"[s->malloc_count == 2]); } } #endif { - JSMallocState *ms = &rt->malloc_state; - rt->mf.js_free(ms->opaque, rt); + JSMallocState ms = rt->malloc_state; + rt->mf.js_free(&ms, rt); } } @@ -2363,16 +2201,14 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->class_proto[i] = JS_NULL; ctx->array_ctor = JS_NULL; ctx->iterator_ctor = JS_NULL; - ctx->iterator_ctor_getset = JS_NULL; ctx->regexp_ctor = JS_NULL; ctx->promise_ctor = JS_NULL; - ctx->error_ctor = JS_NULL; - ctx->error_back_trace = JS_UNDEFINED; - ctx->error_prepare_stack = JS_UNDEFINED; - ctx->error_stack_trace_limit = js_int32(10); init_list_head(&ctx->loaded_modules); - JS_AddIntrinsicBasicObjects(ctx); + if (JS_AddIntrinsicBasicObjects(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } @@ -2384,21 +2220,20 @@ JSContext *JS_NewContext(JSRuntime *rt) if (!ctx) return NULL; - JS_AddIntrinsicBaseObjects(ctx); - JS_AddIntrinsicDate(ctx); - JS_AddIntrinsicEval(ctx); - JS_AddIntrinsicRegExp(ctx); - JS_AddIntrinsicJSON(ctx); - JS_AddIntrinsicProxy(ctx); - JS_AddIntrinsicMapSet(ctx); - JS_AddIntrinsicTypedArrays(ctx); - JS_AddIntrinsicPromise(ctx); - JS_AddIntrinsicBigInt(ctx); - JS_AddIntrinsicWeakRef(ctx); - JS_AddIntrinsicDOMException(ctx); - - JS_AddPerformance(ctx); - + if (JS_AddIntrinsicBaseObjects(ctx) || + JS_AddIntrinsicDate(ctx) || + JS_AddIntrinsicEval(ctx) || + JS_AddIntrinsicStringNormalize(ctx) || + JS_AddIntrinsicRegExp(ctx) || + JS_AddIntrinsicJSON(ctx) || + JS_AddIntrinsicProxy(ctx) || + JS_AddIntrinsicMapSet(ctx) || + JS_AddIntrinsicTypedArrays(ctx) || + JS_AddIntrinsicPromise(ctx) || + JS_AddIntrinsicWeakRef(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } @@ -2424,19 +2259,16 @@ static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val) void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj) { - assert(class_id < ctx->rt->class_count); + JSRuntime *rt = ctx->rt; + assert(class_id < rt->class_count); set_value(ctx, &ctx->class_proto[class_id], obj); } JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id) { - assert(class_id < ctx->rt->class_count); - return js_dup(ctx->class_proto[class_id]); -} - -JSValue JS_GetFunctionProto(JSContext *ctx) -{ - return js_dup(ctx->function_proto); + JSRuntime *rt = ctx->rt; + assert(class_id < rt->class_count); + return JS_DupValue(ctx, ctx->class_proto[class_id]); } typedef enum JSFreeModuleEnum { @@ -2452,7 +2284,13 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag) JSModuleDef *m = list_entry(el, JSModuleDef, link); if (flag == JS_FREE_MODULE_ALL || (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) { - js_free_module_def(ctx, m); + /* warning: the module may be referenced elsewhere. It + could be simpler to use an array instead of a list for + 'ctx->loaded_modules' */ + list_del(&m->link); + m->link.prev = NULL; + m->link.next = NULL; + JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); } } } @@ -2470,11 +2308,9 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx, int i; struct list_head *el; - /* modules are not seen by the GC, so we directly mark the objects - referenced by each module */ list_for_each(el, &ctx->loaded_modules) { JSModuleDef *m = list_entry(el, JSModuleDef, link); - js_mark_module_def(rt, m, mark_func); + JS_MarkValue(rt, JS_MKPTR(JS_TAG_MODULE, m), mark_func); } JS_MarkValue(rt, ctx->global_obj, mark_func); @@ -2487,15 +2323,10 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx, for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { JS_MarkValue(rt, ctx->native_error_proto[i], mark_func); } - JS_MarkValue(rt, ctx->error_ctor, mark_func); - JS_MarkValue(rt, ctx->error_back_trace, mark_func); - JS_MarkValue(rt, ctx->error_prepare_stack, mark_func); - JS_MarkValue(rt, ctx->error_stack_trace_limit, mark_func); for(i = 0; i < rt->class_count; i++) { JS_MarkValue(rt, ctx->class_proto[i], mark_func); } JS_MarkValue(rt, ctx->iterator_ctor, mark_func); - JS_MarkValue(rt, ctx->iterator_ctor_getset, mark_func); JS_MarkValue(rt, ctx->async_iterator_proto, mark_func); JS_MarkValue(rt, ctx->promise_ctor, mark_func); JS_MarkValue(rt, ctx->array_ctor, mark_func); @@ -2516,16 +2347,14 @@ void JS_FreeContext(JSContext *ctx) return; assert(ctx->header.ref_count == 0); -#ifdef ENABLE_DUMPS // JS_DUMP_ATOMS - if (check_dump_flag(rt, JS_DUMP_ATOMS)) - JS_DumpAtoms(ctx->rt); +#ifdef DUMP_ATOMS + JS_DumpAtoms(ctx->rt); #endif -#ifdef ENABLE_DUMPS // JS_DUMP_SHAPES - if (check_dump_flag(rt, JS_DUMP_SHAPES)) - JS_DumpShapes(ctx->rt); +#ifdef DUMP_SHAPES + JS_DumpShapes(ctx->rt); #endif -#ifdef ENABLE_DUMPS // JS_DUMP_OBJECTS - if (check_dump_flag(rt, JS_DUMP_OBJECTS)) { +#ifdef DUMP_OBJECTS + { struct list_head *el; JSGCObjectHeader *p; printf("JSObjects: {\n"); @@ -2537,8 +2366,8 @@ void JS_FreeContext(JSContext *ctx) printf("}\n"); } #endif -#ifdef ENABLE_DUMPS // JS_DUMP_MEM - if (check_dump_flag(rt, JS_DUMP_MEM)) { +#ifdef DUMP_MEM + { JSMemoryUsage stats; JS_ComputeMemoryUsage(rt, &stats); JS_DumpMemoryUsage(stdout, &stats, rt); @@ -2557,16 +2386,11 @@ void JS_FreeContext(JSContext *ctx) for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { JS_FreeValue(ctx, ctx->native_error_proto[i]); } - JS_FreeValue(ctx, ctx->error_ctor); - JS_FreeValue(ctx, ctx->error_back_trace); - JS_FreeValue(ctx, ctx->error_prepare_stack); - JS_FreeValue(ctx, ctx->error_stack_trace_limit); for(i = 0; i < rt->class_count; i++) { JS_FreeValue(ctx, ctx->class_proto[i]); } js_free_rt(rt, ctx->class_proto); JS_FreeValue(ctx, ctx->iterator_ctor); - JS_FreeValue(ctx, ctx->iterator_ctor_getset); JS_FreeValue(ctx, ctx->async_iterator_proto); JS_FreeValue(ctx, ctx->promise_ctor); JS_FreeValue(ctx, ctx->array_ctor); @@ -2588,15 +2412,11 @@ JSRuntime *JS_GetRuntime(JSContext *ctx) static void update_stack_limit(JSRuntime *rt) { -#if defined(__wasi__) - rt->stack_limit = 0; /* no limit */ -#else if (rt->stack_size == 0) { rt->stack_limit = 0; /* no limit */ } else { rt->stack_limit = rt->stack_top - rt->stack_size; } -#endif } void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size) @@ -2611,10 +2431,10 @@ void JS_UpdateStackTop(JSRuntime *rt) update_stack_limit(rt); } -static inline bool is_strict_mode(JSContext *ctx) +static inline BOOL is_strict_mode(JSContext *ctx) { JSStackFrame *sf = ctx->rt->current_stack_frame; - return sf && sf->is_strict_mode; + return (sf && (sf->js_mode & JS_MODE_STRICT)); } /* JSAtom support */ @@ -2626,12 +2446,16 @@ static inline bool is_strict_mode(JSContext *ctx) /* return the max count from the hash size */ #define JS_ATOM_COUNT_RESIZE(n) ((n) * 2) -static inline bool __JS_AtomIsConst(JSAtom v) +static inline BOOL __JS_AtomIsConst(JSAtom v) { - return (int32_t)v < JS_ATOM_END; +#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1 + return (int32_t)v <= 0; +#else + return (int32_t)v < JS_ATOM_END; +#endif } -static inline bool __JS_AtomIsTaggedInt(JSAtom v) +static inline BOOL __JS_AtomIsTaggedInt(JSAtom v) { return (v & JS_ATOM_TAG_INT) != 0; } @@ -2651,8 +2475,8 @@ static inline int is_num(int c) return c >= '0' && c <= '9'; } -/* return true if the string is a number n with 0 <= n <= 2^32-1 */ -static inline bool is_num_string(uint32_t *pval, JSString *p) +/* return TRUE if the string is a number n with 0 <= n <= 2^32-1 */ +static inline BOOL is_num_string(uint32_t *pval, const JSString *p) { uint32_t n; uint64_t n64; @@ -2660,29 +2484,29 @@ static inline bool is_num_string(uint32_t *pval, JSString *p) len = p->len; if (len == 0 || len > 10) - return false; + return FALSE; c = string_get(p, 0); if (is_num(c)) { if (c == '0') { if (len != 1) - return false; + return FALSE; n = 0; } else { n = c - '0'; for(i = 1; i < len; i++) { c = string_get(p, i); if (!is_num(c)) - return false; + return FALSE; n64 = (uint64_t)n * 10 + (c - '0'); if ((n64 >> 32) != 0) - return false; + return FALSE; n = n64; } } *pval = n; - return true; + return TRUE; } else { - return false; + return FALSE; } } @@ -2706,42 +2530,54 @@ static inline uint32_t hash_string16(const uint16_t *str, return h; } -static uint32_t hash_string(JSString *str, uint32_t h) +static uint32_t hash_string(const JSString *str, uint32_t h) { if (str->is_wide_char) - h = hash_string16(str16(str), str->len, h); + h = hash_string16(str->u.str16, str->len, h); else - h = hash_string8(str8(str), str->len, h); + h = hash_string8(str->u.str8, str->len, h); return h; } -static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p) +static uint32_t hash_string_rope(JSValueConst val, uint32_t h) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + return hash_string(JS_VALUE_GET_STRING(val), h); + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + h = hash_string_rope(r->left, h); + return hash_string_rope(r->right, h); + } +} + +static __maybe_unused void JS_DumpChar(FILE *fo, int c, int sep) { - int i, c, sep; + if (c == sep || c == '\\') { + fputc('\\', fo); + fputc(c, fo); + } else if (c >= ' ' && c <= 126) { + fputc(c, fo); + } else if (c == '\n') { + fputc('\\', fo); + fputc('n', fo); + } else { + fprintf(fo, "\\u%04x", c); + } +} + +static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p) +{ + int i, sep; if (p == NULL) { printf(""); return; } - if (p->header.ref_count != 1) - printf("%d", p->header.ref_count); - if (p->is_wide_char) - putchar('L'); - sep = '\"'; + printf("%d", p->header.ref_count); + sep = (p->header.ref_count == 1) ? '\"' : '\''; putchar(sep); for(i = 0; i < p->len; i++) { - c = string_get(p, i); - if (c == sep || c == '\\') { - putchar('\\'); - putchar(c); - } else if (c >= ' ' && c <= 126) { - putchar(c); - } else if (c == '\n') { - putchar('\\'); - putchar('n'); - } else { - printf("\\u%04x", c); - } + JS_DumpChar(stdout, string_get(p, i), sep); } putchar(sep); } @@ -2821,7 +2657,7 @@ static int JS_InitAtoms(JSRuntime *rt) rt->atom_count = 0; rt->atom_size = 0; rt->atom_free_index = 0; - if (JS_ResizeAtomHash(rt, 256)) /* there are at least 195 predefined atoms */ + if (JS_ResizeAtomHash(rt, 512)) /* there are at least 504 predefined atoms */ return -1; p = js_atom_init; @@ -2879,18 +2715,18 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v) case JS_ATOM_TYPE_GLOBAL_SYMBOL: return JS_ATOM_KIND_SYMBOL; case JS_ATOM_TYPE_SYMBOL: - switch(p->hash) { - case JS_ATOM_HASH_SYMBOL: - return JS_ATOM_KIND_SYMBOL; - case JS_ATOM_HASH_PRIVATE: + if (p->hash == JS_ATOM_HASH_PRIVATE) return JS_ATOM_KIND_PRIVATE; - default: - abort(); - } + else + return JS_ATOM_KIND_SYMBOL; default: abort(); } - return (JSAtomKindEnum){-1}; // pacify compiler +} + +static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v) +{ + return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING; } static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p) @@ -2918,6 +2754,9 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) JSAtomStruct *p; int len; +#if 0 + printf("__JS_NewAtom: "); JS_DumpString(rt, str); printf("\n"); +#endif if (atom_type < JS_ATOM_TYPE_SYMBOL) { /* str is not NULL */ if (str->atom_type == atom_type) { @@ -2939,7 +2778,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) if (p->hash == h && p->atom_type == atom_type && p->len == len && - js_string_memcmp(p, str, len) == 0) { + js_string_memcmp(p, 0, str, 0, len) == 0) { if (!__JS_AtomIsConst(i)) p->header.ref_count++; goto done; @@ -2949,7 +2788,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) } else { h1 = 0; /* avoid warning */ if (atom_type == JS_ATOM_TYPE_SYMBOL) { - h = JS_ATOM_HASH_SYMBOL; + h = 0; } else { h = JS_ATOM_HASH_PRIVATE; atom_type = JS_ATOM_TYPE_SYMBOL; @@ -2963,9 +2802,9 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) /* alloc new with size progression 3/2: 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092 - preallocating space for predefined atoms (at least 195). + preallocating space for predefined atoms (at least 504). */ - new_size = max_int(211, rt->atom_size * 3 / 2); + new_size = max_int(711, rt->atom_size * 3 / 2); if (new_size > JS_ATOM_MAX) goto fail; /* XXX: should use realloc2 to use slack space */ @@ -2983,7 +2822,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) } p->header.ref_count = 1; /* not refcounted */ p->atom_type = JS_ATOM_TYPE_SYMBOL; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif new_array[0] = p; @@ -3016,11 +2855,10 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) p->header.ref_count = 1; p->is_wide_char = str->is_wide_char; p->len = str->len; - p->kind = JS_STRING_KIND_NORMAL; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif - memcpy(str8(p), str8(str), (str->len << str->is_wide_char) + + memcpy(p->u.str8, str->u.str8, (str->len << str->is_wide_char) + 1 - str->is_wide_char); js_free_string(rt, str); } @@ -3031,8 +2869,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) p->header.ref_count = 1; p->is_wide_char = 1; /* Hack to represent NULL as a JSString */ p->len = 0; - p->kind = JS_STRING_KIND_NORMAL; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); #endif } @@ -3045,7 +2882,6 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) p->hash = h; p->hash_next = i; /* atom_index */ p->atom_type = atom_type; - p->first_weak_ref = NULL; rt->atom_count++; @@ -3067,8 +2903,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) return i; } -// XXX: `str` must be pure ASCII. No UTF-8 encoded strings -// XXX: `str` must not be the string representation of a small integer +/* only works with zero terminated 8 bit strings */ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, int atom_type) { @@ -3076,12 +2911,12 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, p = js_alloc_string_rt(rt, len, 0); if (!p) return JS_ATOM_NULL; - memcpy(str8(p), str, len); - str8(p)[len] = '\0'; + memcpy(p->u.str8, str, len); + p->u.str8[len] = '\0'; return __JS_NewAtom(rt, p, atom_type); } -// XXX: `str` must be raw 8-bit contents. No UTF-8 encoded strings +/* Warning: str must be ASCII only */ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, int atom_type) { @@ -3098,7 +2933,7 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, p->atom_type == JS_ATOM_TYPE_STRING && p->len == len && p->is_wide_char == 0 && - memcmp(str8(p), str, len) == 0) { + memcmp(p->u.str8, str, len) == 0) { if (!__JS_AtomIsConst(i)) p->header.ref_count++; return i; @@ -3110,6 +2945,12 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p) { +#if 0 /* JS_ATOM_NULL is not refcounted: __JS_AtomIsConst() includes 0 */ + if (unlikely(i == JS_ATOM_NULL)) { + p->header.ref_count = INT32_MAX / 2; + return; + } +#endif uint32_t i = p->hash_next; /* atom_index */ if (p->atom_type != JS_ATOM_TYPE_SYMBOL) { JSAtomStruct *p0, *p1; @@ -3136,14 +2977,17 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p) /* insert in free atom list */ rt->atom_array[i] = atom_set_free(rt->atom_free_index); rt->atom_free_index = i; - if (unlikely(p->first_weak_ref)) { - reset_weak_ref(rt, &p->first_weak_ref); - } /* free the string structure */ -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS list_del(&p->link); #endif - js_free_rt(rt, p); + if (p->atom_type == JS_ATOM_TYPE_SYMBOL && + p->hash != JS_ATOM_HASH_PRIVATE && p->hash != 0) { + /* live weak references are still present on this object: keep + it */ + } else { + js_free_rt(rt, p); + } rt->atom_count--; assert(rt->atom_count >= 0); } @@ -3173,14 +3017,25 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p) return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING); } -/* `str` may be pure ASCII or UTF-8 encoded */ +/* XXX: optimize */ +static size_t count_ascii(const uint8_t *buf, size_t len) +{ + const uint8_t *p, *p_end; + p = buf; + p_end = buf + len; + while (p < p_end && *p < 128) + p++; + return p - buf; +} + +/* str is UTF-8 encoded */ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len) { JSValue val; - if (len == 0 || !is_digit(*str)) { - // TODO(chqrlie): this does not work if `str` has UTF-8 encoded contents - // bug example: `({ "\u00c3\u00a9": 1 }).\u00e9` evaluates to `1`. + if (len == 0 || + (!is_digit(*str) && + count_ascii((const uint8_t *)str, len) == len)) { JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING); if (atom) return atom; @@ -3191,7 +3046,6 @@ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len) return JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(val)); } -/* `str` may be pure ASCII or UTF-8 encoded */ JSAtom JS_NewAtom(JSContext *ctx, const char *str) { return JS_NewAtomLen(ctx, str, strlen(str)); @@ -3202,9 +3056,11 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n) if (n <= JS_ATOM_MAX_INT) { return __JS_AtomFromUInt32(n); } else { - char buf[16]; - size_t len = u32toa(buf, n); - JSValue val = js_new_string8_len(ctx, buf, len); + char buf[11]; + JSValue val; + size_t len; + len = u32toa(buf, n); + val = js_new_string8_len(ctx, buf, len); if (JS_IsException(val)) return JS_ATOM_NULL; return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), @@ -3218,8 +3074,10 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) return __JS_AtomFromUInt32((uint32_t)n); } else { char buf[24]; - size_t len = i64toa(buf, n); - JSValue val = js_new_string8_len(ctx, buf, len); + JSValue val; + size_t len; + len = i64toa(buf, n); + val = js_new_string8_len(ctx, buf, len); if (JS_IsException(val)) return JS_ATOM_NULL; return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val), @@ -3228,7 +3086,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) } /* 'p' is freed */ -static JSValue JS_NewSymbolInternal(JSContext *ctx, JSString *p, int atom_type) +static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type) { JSRuntime *rt = ctx->rt; JSAtom atom; @@ -3248,44 +3106,54 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr, assert(!__JS_AtomIsTaggedInt(descr)); assert(descr < rt->atom_size); p = rt->atom_array[descr]; - js_dup(JS_MKPTR(JS_TAG_STRING, p)); - return JS_NewSymbolInternal(ctx, p, atom_type); -} - -/* `description` may be pure ASCII or UTF-8 encoded */ -JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global) -{ - JSAtom atom = JS_NewAtom(ctx, description); - if (atom == JS_ATOM_NULL) - return JS_EXCEPTION; - return JS_NewSymbolFromAtom(ctx, atom, is_global ? JS_ATOM_TYPE_GLOBAL_SYMBOL : JS_ATOM_TYPE_SYMBOL); + JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + return JS_NewSymbol(ctx, p, atom_type); } #define ATOM_GET_STR_BUF_SIZE 64 +/* Should only be used for debug. */ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, JSAtom atom) { if (__JS_AtomIsTaggedInt(atom)) { snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); - } else if (atom == JS_ATOM_NULL) { - snprintf(buf, buf_size, ""); - } else if (atom >= rt->atom_size) { - assert(atom < rt->atom_size); - snprintf(buf, buf_size, "", atom); } else { - JSAtomStruct *p = rt->atom_array[atom]; - *buf = '\0'; - if (atom_is_free(p)) { - snprintf(buf, buf_size, "", atom); - } else if (p != NULL) { - JSString *str = p; - if (str->is_wide_char) { - /* encode surrogates correctly */ - utf8_encode_buf16(buf, buf_size, str16(str), str->len); - } else { - utf8_encode_buf8(buf, buf_size, str8(str), str->len); + JSAtomStruct *p; + assert(atom < rt->atom_size); + if (atom == JS_ATOM_NULL) { + snprintf(buf, buf_size, ""); + } else { + int i, c; + char *q; + JSString *str; + + q = buf; + p = rt->atom_array[atom]; + assert(!atom_is_free(p)); + str = p; + if (str) { + if (!str->is_wide_char) { + /* special case ASCII strings */ + c = 0; + for(i = 0; i < str->len; i++) { + c |= str->u.str8[i]; + } + if (c < 0x80) + return (const char *)str->u.str8; + } + for(i = 0; i < str->len; i++) { + c = string_get(str, i); + if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX) + break; + if (c < 128) { + *q++ = c; + } else { + q += unicode_to_utf8((uint8_t *)q, c); + } + } } + *q = '\0'; } } return buf; @@ -3296,7 +3164,7 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom); } -static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, bool force_string) +static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string) { char buf[ATOM_GET_STR_BUF_SIZE]; @@ -3316,30 +3184,30 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, bool force_string) p = rt->atom_array[JS_ATOM_empty_string]; } ret_string: - return js_dup(JS_MKPTR(JS_TAG_STRING, p)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); } else { - return js_dup(JS_MKPTR(JS_TAG_SYMBOL, p)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p)); } } } JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom) { - return __JS_AtomToValue(ctx, atom, false); + return __JS_AtomToValue(ctx, atom, FALSE); } JSValue JS_AtomToString(JSContext *ctx, JSAtom atom) { - return __JS_AtomToValue(ctx, atom, true); + return __JS_AtomToValue(ctx, atom, TRUE); } -/* return true if the atom is an array index (i.e. 0 <= index <= +/* return TRUE if the atom is an array index (i.e. 0 <= index <= 2^32-2 and return its value */ -static bool JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) +static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) { if (__JS_AtomIsTaggedInt(atom)) { *pval = __JS_AtomToUInt32(atom); - return true; + return TRUE; } else { JSRuntime *rt = ctx->rt; JSAtomStruct *p; @@ -3350,10 +3218,10 @@ static bool JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) if (p->atom_type == JS_ATOM_TYPE_STRING && is_num_string(&val, p) && val != -1) { *pval = val; - return true; + return TRUE; } else { *pval = 0; - return false; + return FALSE; } } } @@ -3366,61 +3234,33 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) JSRuntime *rt = ctx->rt; JSAtomStruct *p1; JSString *p; - int c, len, ret; + int c, ret; JSValue num, str; if (__JS_AtomIsTaggedInt(atom)) - return js_int32(__JS_AtomToUInt32(atom)); + return JS_NewInt32(ctx, __JS_AtomToUInt32(atom)); assert(atom < rt->atom_size); p1 = rt->atom_array[atom]; if (p1->atom_type != JS_ATOM_TYPE_STRING) return JS_UNDEFINED; - p = p1; - len = p->len; - if (p->is_wide_char) { - const uint16_t *r = str16(p), *r_end = str16(p) + len; - if (r >= r_end) - return JS_UNDEFINED; - c = *r; - if (c == '-') { - if (r >= r_end) - return JS_UNDEFINED; - r++; - c = *r; - /* -0 case is specific */ - if (c == '0' && len == 2) - goto minus_zero; - } - /* XXX: should test NaN, but the tests do not check it */ - if (!is_num(c)) { - /* XXX: String should be normalized, therefore 8-bit only */ - const uint16_t nfinity16[7] = { 'n', 'f', 'i', 'n', 'i', 't', 'y' }; - if (!(c =='I' && (r_end - r) == 8 && - !memcmp(r + 1, nfinity16, sizeof(nfinity16)))) - return JS_UNDEFINED; - } - } else { - const uint8_t *r = str8(p), *r_end = str8(p) + len; - if (r >= r_end) - return JS_UNDEFINED; - c = *r; - if (c == '-') { - if (r >= r_end) - return JS_UNDEFINED; - r++; - c = *r; - /* -0 case is specific */ - if (c == '0' && len == 2) { - minus_zero: - return js_float64(-0.0); - } - } - if (!is_num(c)) { - if (!(c =='I' && (r_end - r) == 8 && - !memcmp(r + 1, "nfinity", 7))) - return JS_UNDEFINED; - } + switch(atom) { + case JS_ATOM_minus_zero: + return __JS_NewFloat64(ctx, -0.0); + case JS_ATOM_Infinity: + return __JS_NewFloat64(ctx, INFINITY); + case JS_ATOM_minus_Infinity: + return __JS_NewFloat64(ctx, -INFINITY); + case JS_ATOM_NaN: + return __JS_NewFloat64(ctx, NAN); + default: + break; } + p = p1; + if (p->len == 0) + return JS_UNDEFINED; + c = string_get(p, 0); + if (!is_num(c) && c != '-') + return JS_UNDEFINED; /* this is ECMA CanonicalNumericIndexString primitive */ num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p)); if (JS_IsException(num)) @@ -3430,9 +3270,9 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) JS_FreeValue(ctx, num); return str; } - ret = js_string_eq(p, JS_VALUE_GET_STRING(str)); + ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str)); JS_FreeValue(ctx, str); - if (ret) { + if (ret == 0) { return num; } else { JS_FreeValue(ctx, num); @@ -3440,17 +3280,17 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) } } -/* return -1 if exception or true/false */ +/* return -1 if exception or TRUE/FALSE */ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom) { JSValue num; num = JS_AtomIsNumericIndex1(ctx, atom); if (likely(JS_IsUndefined(num))) - return false; + return FALSE; if (JS_IsException(num)) return -1; JS_FreeValue(ctx, num); - return true; + return TRUE; } void JS_FreeAtom(JSContext *ctx, JSAtom v) @@ -3465,60 +3305,22 @@ void JS_FreeAtomRT(JSRuntime *rt, JSAtom v) __JS_FreeAtom(rt, v); } -/* return true if 'v' is a symbol with a string description */ -static bool JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) +/* return TRUE if 'v' is a symbol with a string description */ +static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) { JSRuntime *rt; JSAtomStruct *p; rt = ctx->rt; if (__JS_AtomIsTaggedInt(v)) - return false; + return FALSE; p = rt->atom_array[v]; return (((p->atom_type == JS_ATOM_TYPE_SYMBOL && - p->hash == JS_ATOM_HASH_SYMBOL) || + p->hash != JS_ATOM_HASH_PRIVATE) || p->atom_type == JS_ATOM_TYPE_GLOBAL_SYMBOL) && !(p->len == 0 && p->is_wide_char != 0)); } -static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom) -{ - char buf[ATOM_GET_STR_BUF_SIZE]; - const char *p; - int i; - - /* XXX: should handle embedded null characters */ - /* XXX: should move encoding code to JS_AtomGetStr */ - p = JS_AtomGetStr(ctx, buf, sizeof(buf), atom); - for (i = 0; p[i]; i++) { - int c = (unsigned char)p[i]; - if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || - (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0))) - break; - } - if (i > 0 && p[i] == '\0') { - printf("%s", p); - } else { - putchar('"'); - printf("%.*s", i, p); - for (; p[i]; i++) { - int c = (unsigned char)p[i]; - if (c == '\"' || c == '\\') { - putchar('\\'); - putchar(c); - } else if (c >= ' ' && c <= 126) { - putchar(c); - } else if (c == '\n') { - putchar('\\'); - putchar('n'); - } else { - printf("\\u%04x", c); - } - } - putchar('\"'); - } -} - /* free with JS_FreeCString() */ const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom) { @@ -3536,11 +3338,7 @@ const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom) return cstr; } -#ifndef QJS_DISABLE_PARSER - /* return a string atom containing name concatenated with str1 */ -/* `str1` may be pure ASCII or UTF-8 encoded */ -// TODO(chqrlie): use string concatenation instead of UTF-8 conversion static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) { JSValue str; @@ -3577,42 +3375,50 @@ static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n) { char buf[16]; size_t len; - len = u32toa(buf, n); buf[len] = '\0'; return js_atom_concat_str(ctx, name, buf); } -#endif // QJS_DISABLE_PARSER - -static inline bool JS_IsEmptyString(JSValueConst v) +static inline BOOL JS_IsEmptyString(JSValueConst v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0; } /* JSClass support */ -/* a new class ID is allocated if *pclass_id == 0, otherwise *pclass_id is left unchanged */ -JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id) +#ifdef CONFIG_ATOMICS +static pthread_mutex_t js_class_id_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* a new class ID is allocated if *pclass_id != 0 */ +JSClassID JS_NewClassID(JSClassID *pclass_id) { - JSClassID class_id = *pclass_id; + JSClassID class_id; +#ifdef CONFIG_ATOMICS + pthread_mutex_lock(&js_class_id_mutex); +#endif + class_id = *pclass_id; if (class_id == 0) { - class_id = rt->js_class_id_alloc++; + class_id = js_class_id_alloc++; *pclass_id = class_id; } +#ifdef CONFIG_ATOMICS + pthread_mutex_unlock(&js_class_id_mutex); +#endif return class_id; } -JSClassID JS_GetClassID(JSValueConst v) +JSClassID JS_GetClassID(JSValue v) { - JSObject *p; - if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) - return JS_INVALID_CLASS_ID; - p = JS_VALUE_GET_OBJ(v); - return p->class_id; + JSObject *p; + if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) + return JS_INVALID_CLASS_ID; + p = JS_VALUE_GET_OBJ(v); + return p->class_id; } -bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id) +BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id) { return (class_id < rt->class_count && rt->class_array[class_id].class_id != 0); @@ -3674,7 +3480,6 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def) int ret, len; JSAtom name; - // XXX: class_def->class_name must be raw 8-bit contents. No UTF-8 encoded strings len = strlen(class_def->class_name); name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING); if (name == JS_ATOM_NULL) { @@ -3687,30 +3492,24 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def) return ret; } -static inline JSValue js_empty_string(JSRuntime *rt) -{ - JSAtomStruct *p = rt->atom_array[JS_ATOM_empty_string]; - return js_dup(JS_MKPTR(JS_TAG_STRING, p)); -} - -// XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed -// XXX: no special case for len == 0 static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len) { JSString *str; + + if (len <= 0) { + return JS_AtomToString(ctx, JS_ATOM_empty_string); + } str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; - memcpy(str8(str), buf, len); - str8(str)[len] = '\0'; + memcpy(str->u.str8, buf, len); + str->u.str8[len] = '\0'; return JS_MKPTR(JS_TAG_STRING, str); } -// XXX: `buf` contains raw 8-bit data, no UTF-8 decoding is performed -// XXX: no special case for the empty string -static inline JSValue js_new_string8(JSContext *ctx, const char *str) +static JSValue js_new_string8(JSContext *ctx, const char *buf) { - return js_new_string8_len(ctx, str, strlen(str)); + return js_new_string8_len(ctx, buf, strlen(buf)); } static JSValue js_new_string16_len(JSContext *ctx, const uint16_t *buf, int len) @@ -3719,15 +3518,15 @@ static JSValue js_new_string16_len(JSContext *ctx, const uint16_t *buf, int len) str = js_alloc_string(ctx, len, 1); if (!str) return JS_EXCEPTION; - memcpy(str16(str), buf, len * 2); + memcpy(str->u.str16, buf, len * 2); return JS_MKPTR(JS_TAG_STRING, str); } static JSValue js_new_string_char(JSContext *ctx, uint16_t c) { if (c < 0x100) { - char ch8 = c; - return js_new_string8_len(ctx, &ch8, 1); + uint8_t ch8 = c; + return js_new_string8_len(ctx, (const char *)&ch8, 1); } else { uint16_t ch16 = c; return js_new_string16_len(ctx, &ch16, 1); @@ -3736,57 +3535,30 @@ static JSValue js_new_string_char(JSContext *ctx, uint16_t c) static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) { - JSStringSlice *slice; - JSString *q; - int len; - - len = end - start; + int len = end - start; if (start == 0 && end == p->len) { - return js_dup(JS_MKPTR(JS_TAG_STRING, p)); - } - if (len <= 0) { - return js_empty_string(ctx->rt); - } - if (len > (JS_STRING_SLICE_LEN_MAX >> p->is_wide_char)) { - if (p->kind == JS_STRING_KIND_SLICE) { - slice = (void *)&p[1]; - p = slice->parent; - start += slice->start; - } - // allocate as 16 bit wide string to avoid wastage; - // js_alloc_string allocates 1 byte extra for 8 bit strings; - q = js_alloc_string(ctx, sizeof(*slice)/2, /*is_wide_char*/true); - if (!q) - return JS_EXCEPTION; - q->is_wide_char = p->is_wide_char; - q->kind = JS_STRING_KIND_SLICE; - q->len = len; - slice = (void *)&q[1]; - slice->parent = p; - slice->start = start; - p->header.ref_count++; - return JS_MKPTR(JS_TAG_STRING, q); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); } - if (p->is_wide_char) { + if (p->is_wide_char && len > 0) { JSString *str; int i; uint16_t c = 0; for (i = start; i < end; i++) { - c |= str16(p)[i]; + c |= p->u.str16[i]; } if (c > 0xFF) - return js_new_string16_len(ctx, str16(p) + start, len); + return js_new_string16_len(ctx, p->u.str16 + start, len); str = js_alloc_string(ctx, len, 0); if (!str) return JS_EXCEPTION; for (i = 0; i < len; i++) { - str8(str)[i] = str16(p)[start + i]; + str->u.str8[i] = p->u.str16[start + i]; } - str8(str)[len] = '\0'; + str->u.str8[len] = '\0'; return JS_MKPTR(JS_TAG_STRING, str); } else { - return js_new_string8_len(ctx, (const char *)(str8(p) + start), len); + return js_new_string8_len(ctx, (const char *)(p->u.str8 + start), len); } } @@ -3816,7 +3588,7 @@ static int string_buffer_init2(JSContext *ctx, StringBuffer *s, int size, s->size = 0; return s->error_status = -1; } -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS +#ifdef DUMP_LEAKS /* the StringBuffer may reallocate the JSString, only link it at the end */ list_del(&s->str->link); #endif @@ -3857,7 +3629,7 @@ static no_inline int string_buffer_widen(StringBuffer *s, int size) return string_buffer_set_error(s); size += slack >> 1; for(i = s->len; i-- > 0;) { - str16(str)[i] = str8(str)[i]; + str->u.str16[i] = str->u.str8[i]; } s->is_wide_char = 1; s->size = size; @@ -3875,7 +3647,7 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) return -1; if (new_len > JS_STRING_LEN_MAX) { - JS_ThrowRangeError(s->ctx, "invalid string length"); + JS_ThrowInternalError(s->ctx, "string too long"); return string_buffer_set_error(s); } new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX); @@ -3892,20 +3664,20 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) return 0; } -static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c) +static no_inline int string_buffer_putc16_slow(StringBuffer *s, uint32_t c) { if (unlikely(s->len >= s->size)) { if (string_buffer_realloc(s, s->len + 1, c)) return -1; } if (s->is_wide_char) { - str16(s->str)[s->len++] = c; + s->str->u.str16[s->len++] = c; } else if (c < 0x100) { - str8(s->str)[s->len++] = c; + s->str->u.str8[s->len++] = c; } else { if (string_buffer_widen(s, s->size)) return -1; - str16(s->str)[s->len++] = c; + s->str->u.str16[s->len++] = c; } return 0; } @@ -3918,9 +3690,9 @@ static int string_buffer_putc8(StringBuffer *s, uint32_t c) return -1; } if (s->is_wide_char) { - str16(s->str)[s->len++] = c; + s->str->u.str16[s->len++] = c; } else { - str8(s->str)[s->len++] = c; + s->str->u.str8[s->len++] = c; } return 0; } @@ -3930,18 +3702,17 @@ static int string_buffer_putc16(StringBuffer *s, uint32_t c) { if (likely(s->len < s->size)) { if (s->is_wide_char) { - str16(s->str)[s->len++] = c; + s->str->u.str16[s->len++] = c; return 0; } else if (c < 0x100) { - str8(s->str)[s->len++] = c; + s->str->u.str8[s->len++] = c; return 0; } } - return string_buffer_putc_slow(s, c); + return string_buffer_putc16_slow(s, c); } -/* 0 <= c <= 0x10ffff */ -static int string_buffer_putc(StringBuffer *s, uint32_t c) +static int string_buffer_putc_slow(StringBuffer *s, uint32_t c) { if (unlikely(c >= 0x10000)) { /* surrogate pair */ @@ -3952,21 +3723,42 @@ static int string_buffer_putc(StringBuffer *s, uint32_t c) return string_buffer_putc16(s, c); } -static int string_getc(JSString *p, int *pidx) +/* 0 <= c <= 0x10ffff */ +static inline int string_buffer_putc(StringBuffer *s, uint32_t c) +{ + if (likely(s->len < s->size)) { + if (s->is_wide_char) { + if (c < 0x10000) { + s->str->u.str16[s->len++] = c; + return 0; + } else if (likely((s->len + 1) < s->size)) { + s->str->u.str16[s->len++] = get_hi_surrogate(c); + s->str->u.str16[s->len++] = get_lo_surrogate(c); + return 0; + } + } else if (c < 0x100) { + s->str->u.str8[s->len++] = c; + return 0; + } + } + return string_buffer_putc_slow(s, c); +} + +static int string_getc(const JSString *p, int *pidx) { int idx, c, c1; idx = *pidx; if (p->is_wide_char) { - c = str16(p)[idx++]; + c = p->u.str16[idx++]; if (is_hi_surrogate(c) && idx < p->len) { - c1 = str16(p)[idx]; + c1 = p->u.str16[idx]; if (is_lo_surrogate(c1)) { c = from_surrogate(c, c1); idx++; } } } else { - c = str8(p)[idx++]; + c = p->u.str8[idx++]; } *pidx = idx; return c; @@ -3982,11 +3774,11 @@ static int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len) } if (s->is_wide_char) { for (i = 0; i < len; i++) { - str16(s->str)[s->len + i] = p[i]; + s->str->u.str16[s->len + i] = p[i]; } s->len += len; } else { - memcpy(&str8(s->str)[s->len], p, len); + memcpy(&s->str->u.str8[s->len], p, len); s->len += len; } return 0; @@ -4007,11 +3799,11 @@ static int string_buffer_write16(StringBuffer *s, const uint16_t *p, int len) return -1; } if (s->is_wide_char) { - memcpy(&str16(s->str)[s->len], p, len << 1); + memcpy(&s->str->u.str16[s->len], p, len << 1); s->len += len; } else { for (i = 0; i < len; i++) { - str8(s->str)[s->len + i] = p[i]; + s->str->u.str8[s->len + i] = p[i]; } s->len += len; } @@ -4024,15 +3816,15 @@ static int string_buffer_puts8(StringBuffer *s, const char *str) return string_buffer_write8(s, (const uint8_t *)str, strlen(str)); } -static int string_buffer_concat(StringBuffer *s, JSString *p, +static int string_buffer_concat(StringBuffer *s, const JSString *p, uint32_t from, uint32_t to) { if (to <= from) return 0; if (p->is_wide_char) - return string_buffer_write16(s, str16(p) + from, to - from); + return string_buffer_write16(s, p->u.str16 + from, to - from); else - return string_buffer_write8(s, str8(p) + from, to - from); + return string_buffer_write8(s, p->u.str8 + from, to - from); } static int string_buffer_concat_value(StringBuffer *s, JSValueConst v) @@ -4046,13 +3838,21 @@ static int string_buffer_concat_value(StringBuffer *s, JSValueConst v) return -1; } if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) { - v1 = JS_ToString(s->ctx, v); - if (JS_IsException(v1)) - return string_buffer_set_error(s); - p = JS_VALUE_GET_STRING(v1); - res = string_buffer_concat(s, p, 0, p->len); - JS_FreeValue(s->ctx, v1); - return res; + if (JS_VALUE_GET_TAG(v) == JS_TAG_STRING_ROPE) { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(v); + /* recursion is acceptable because the rope depth is bounded */ + if (string_buffer_concat_value(s, r->left)) + return -1; + return string_buffer_concat_value(s, r->right); + } else { + v1 = JS_ToString(s->ctx, v); + if (JS_IsException(v1)) + return string_buffer_set_error(s); + p = JS_VALUE_GET_STRING(v1); + res = string_buffer_concat(s, p, 0, p->len); + JS_FreeValue(s->ctx, v1); + return res; + } } p = JS_VALUE_GET_STRING(v); return string_buffer_concat(s, p, 0, p->len); @@ -4102,7 +3902,7 @@ static JSValue string_buffer_end(StringBuffer *s) if (s->len == 0) { js_free(s->ctx, str); s->str = NULL; - return js_empty_string(s->ctx->rt); + return JS_AtomToString(s->ctx, JS_ATOM_empty_string); } if (s->len < s->size) { /* smaller size so js_realloc should not fail, but OK if it does */ @@ -4115,8 +3915,8 @@ static JSValue string_buffer_end(StringBuffer *s) s->str = str; } if (!s->is_wide_char) - str8(str)[s->len] = 0; -#ifdef ENABLE_DUMPS // JS_DUMP_LEAKS + str->u.str8[s->len] = 0; +#ifdef DUMP_LEAKS list_add_tail(&str->link, &s->ctx->rt->string_list); #endif str->is_wide_char = s->is_wide_char; @@ -4128,57 +3928,59 @@ static JSValue string_buffer_end(StringBuffer *s) /* create a string from a UTF-8 buffer */ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) { - JSString *str; - size_t len; - int kind; - - if (buf_len <= 0) { - return js_empty_string(ctx->rt); - } - /* Compute string kind and length: 7-bit, 8-bit, 16-bit, 16-bit UTF-16 */ - kind = utf8_scan(buf, buf_len, &len); - if (len > JS_STRING_LEN_MAX) - return JS_ThrowRangeError(ctx, "invalid string length"); - - switch (kind) { - case UTF8_PLAIN_ASCII: - str = js_alloc_string(ctx, len, 0); - if (!str) - return JS_EXCEPTION; - memcpy(str8(str), buf, len); - str8(str)[len] = '\0'; - break; - case UTF8_NON_ASCII: - /* buf contains non-ASCII code-points, but limited to 8-bit values */ - str = js_alloc_string(ctx, len, 0); - if (!str) - return JS_EXCEPTION; - utf8_decode_buf8(str8(str), len + 1, buf, buf_len); - break; - default: - // This causes a potential problem in JS_ThrowError if message is invalid - //if (kind & UTF8_HAS_ERRORS) - // return JS_ThrowRangeError(ctx, "invalid UTF-8 sequence"); - str = js_alloc_string(ctx, len, 1); - if (!str) - return JS_EXCEPTION; - utf8_decode_buf16(str16(str), len, buf, buf_len); - break; + const uint8_t *p, *p_end, *p_start, *p_next; + uint32_t c; + StringBuffer b_s, *b = &b_s; + size_t len1; + + p_start = (const uint8_t *)buf; + p_end = p_start + buf_len; + len1 = count_ascii(p_start, buf_len); + p = p_start + len1; + if (len1 > JS_STRING_LEN_MAX) + return JS_ThrowInternalError(ctx, "string too long"); + if (p == p_end) { + /* ASCII string */ + return js_new_string8_len(ctx, buf, buf_len); + } else { + if (string_buffer_init(ctx, b, buf_len)) + goto fail; + string_buffer_write8(b, p_start, len1); + while (p < p_end) { + if (*p < 128) { + string_buffer_putc8(b, *p++); + } else { + /* parse utf-8 sequence, return 0xFFFFFFFF for error */ + c = unicode_from_utf8(p, p_end - p, &p_next); + if (c < 0x10000) { + p = p_next; + } else if (c <= 0x10FFFF) { + p = p_next; + /* surrogate pair */ + string_buffer_putc16(b, get_hi_surrogate(c)); + c = get_lo_surrogate(c); + } else { + /* invalid char */ + c = 0xfffd; + /* skip the invalid chars */ + /* XXX: seems incorrect. Why not just use c = *p++; ? */ + while (p < p_end && (*p >= 0x80 && *p < 0xc0)) + p++; + if (p < p_end) { + p++; + while (p < p_end && (*p >= 0x80 && *p < 0xc0)) + p++; + } + } + string_buffer_putc16(b, c); + } + } } - return JS_MKPTR(JS_TAG_STRING, str); -} - -JSValue JS_NewTwoByteString(JSContext *ctx, const uint16_t *buf, size_t len) -{ - JSString *str; + return string_buffer_end(b); - if (!len) - return js_empty_string(ctx->rt); - str = js_alloc_string(ctx, len, 1); - if (!str) - return JS_EXCEPTION; - memcpy(str16(str), buf, len * sizeof(*buf)); - return JS_MKPTR(JS_TAG_STRING, str); + fail: + string_buffer_free(b); + return JS_EXCEPTION; } static JSValue JS_ConcatString3(JSContext *ctx, const char *str1, @@ -4212,7 +4014,6 @@ static JSValue JS_ConcatString3(JSContext *ctx, const char *str1, return JS_EXCEPTION; } -/* `str` may be pure ASCII or UTF-8 encoded */ JSValue JS_NewAtomString(JSContext *ctx, const char *str) { JSAtom atom = JS_NewAtom(ctx, str); @@ -4226,46 +4027,25 @@ JSValue JS_NewAtomString(JSContext *ctx, const char *str) /* return (NULL, 0) if exception. */ /* return pointer into a JSString with a live ref_count */ /* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */ -const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, - bool cesu8) +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BOOL cesu8) { JSValue val; JSString *str, *str_new; int pos, len, c, c1; - JSObject *p; uint8_t *q; - if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) { - val = js_dup(val1); - goto go; - } - - val = JS_ToString(ctx, val1); - if (!JS_IsException(val)) - goto go; - - // Stringification can fail when there is an exception pending, - // e.g. a stack overflow InternalError. Special-case exception - // objects to make debugging easier, look up the .message property - // and stringify that. - if (JS_VALUE_GET_TAG(val1) != JS_TAG_OBJECT) - goto fail; - - p = JS_VALUE_GET_OBJ(val1); - if (p->class_id != JS_CLASS_ERROR) - goto fail; - - val = JS_GetProperty(ctx, val1, JS_ATOM_message); - if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) { - JS_FreeValue(ctx, val); - goto fail; + if (JS_VALUE_GET_TAG(val1) != JS_TAG_STRING) { + val = JS_ToString(ctx, val1); + if (JS_IsException(val)) + goto fail; + } else { + val = JS_DupValue(ctx, val1); } -go: str = JS_VALUE_GET_STRING(val); len = str->len; if (!str->is_wide_char) { - const uint8_t *src = str8(str); + const uint8_t *src = str->u.str8; int count; /* count the number of non-ASCII characters */ @@ -4286,7 +4066,7 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, str_new = js_alloc_string(ctx, len + count, 0); if (!str_new) goto fail; - q = str8(str_new); + q = str_new->u.str8; for (pos = 0; pos < len; pos++) { c = src[pos]; if (c < 0x80) { @@ -4297,14 +4077,14 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, } } } else { - const uint16_t *src = str16(str); + const uint16_t *src = str->u.str16; /* Allocate 3 bytes per 16 bit code point. Surrogate pairs may produce 4 bytes but use 2 code points. */ str_new = js_alloc_string(ctx, len * 3, 0); if (!str_new) goto fail; - q = str8(str_new); + q = str_new->u.str8; pos = 0; while (pos < len) { c = src[pos++]; @@ -4326,17 +4106,17 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, /* c = 0xfffd; */ /* error */ } } - q += utf8_encode(q, c); + q += unicode_to_utf8(q, c); } } } *q = '\0'; - str_new->len = q - str8(str_new); + str_new->len = q - str_new->u.str8; JS_FreeValue(ctx, val); if (plen) *plen = str_new->len; - return (const char *)str8(str_new); + return (const char *)str_new->u.str8; fail: if (plen) *plen = 0; @@ -4345,10 +4125,12 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, void JS_FreeCString(JSContext *ctx, const char *ptr) { + JSString *p; if (!ptr) return; /* purposely removing constness */ - JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, (JSString *)ptr - 1)); + p = container_of(ptr, JSString, u); + JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); } static int memcmp16_8(const uint16_t *src1, const uint8_t *src2, int len) @@ -4373,47 +4155,49 @@ static int memcmp16(const uint16_t *src1, const uint16_t *src2, int len) return 0; } -static int js_string_memcmp(JSString *p1, JSString *p2, int len) +static int js_string_memcmp(const JSString *p1, int pos1, const JSString *p2, + int pos2, int len) { int res; if (likely(!p1->is_wide_char)) { if (likely(!p2->is_wide_char)) - res = memcmp(str8(p1), str8(p2), len); + res = memcmp(p1->u.str8 + pos1, p2->u.str8 + pos2, len); else - res = -memcmp16_8(str16(p2), str8(p1), len); + res = -memcmp16_8(p2->u.str16 + pos2, p1->u.str8 + pos1, len); } else { if (!p2->is_wide_char) - res = memcmp16_8(str16(p1), str8(p2), len); + res = memcmp16_8(p1->u.str16 + pos1, p2->u.str8 + pos2, len); else - res = memcmp16(str16(p1), str16(p2), len); + res = memcmp16(p1->u.str16 + pos1, p2->u.str16 + pos2, len); } return res; } -static bool js_string_eq(JSString *p1, JSString *p2) { - if (p1->len != p2->len) - return false; - return js_string_memcmp(p1, p2, p1->len) == 0; -} - /* return < 0, 0 or > 0 */ -static int js_string_compare(JSString *p1, JSString *p2) +static int js_string_compare(JSContext *ctx, + const JSString *p1, const JSString *p2) { int res, len; len = min_int(p1->len, p2->len); - res = js_string_memcmp(p1, p2, len); - if (res == 0) - res = compare_u32(p1->len, p2->len); + res = js_string_memcmp(p1, 0, p2, 0, len); + if (res == 0) { + if (p1->len == p2->len) + res = 0; + else if (p1->len < p2->len) + res = -1; + else + res = 1; + } return res; } -static void copy_str16(uint16_t *dst, JSString *p, int offset, int len) +static void copy_str16(uint16_t *dst, const JSString *p, int offset, int len) { if (p->is_wide_char) { - memcpy(dst, str16(p) + offset, len * 2); + memcpy(dst, p->u.str16 + offset, len * 2); } else { - const uint8_t *src1 = str8(p) + offset; + const uint8_t *src1 = p->u.str8 + offset; int i; for(i = 0; i < len; i++) @@ -4421,7 +4205,8 @@ static void copy_str16(uint16_t *dst, JSString *p, int offset, int len) } } -static JSValue JS_ConcatString1(JSContext *ctx, JSString *p1, JSString *p2) +static JSValue JS_ConcatString1(JSContext *ctx, + const JSString *p1, const JSString *p2) { JSString *p; uint32_t len; @@ -4429,69 +4214,468 @@ static JSValue JS_ConcatString1(JSContext *ctx, JSString *p1, JSString *p2) len = p1->len + p2->len; if (len > JS_STRING_LEN_MAX) - return JS_ThrowRangeError(ctx, "invalid string length"); + return JS_ThrowInternalError(ctx, "string too long"); is_wide_char = p1->is_wide_char | p2->is_wide_char; p = js_alloc_string(ctx, len, is_wide_char); if (!p) return JS_EXCEPTION; if (!is_wide_char) { - memcpy(str8(p), str8(p1), p1->len); - memcpy(str8(p) + p1->len, str8(p2), p2->len); - str8(p)[len] = '\0'; + memcpy(p->u.str8, p1->u.str8, p1->len); + memcpy(p->u.str8 + p1->len, p2->u.str8, p2->len); + p->u.str8[len] = '\0'; } else { - copy_str16(str16(p), p1, 0, p1->len); - copy_str16(str16(p) + p1->len, p2, 0, p2->len); + copy_str16(p->u.str16, p1, 0, p1->len); + copy_str16(p->u.str16 + p1->len, p2, 0, p2->len); } return JS_MKPTR(JS_TAG_STRING, p); } -/* op1 and op2 are converted to strings. For convience, op1 or op2 = +static BOOL JS_ConcatStringInPlace(JSContext *ctx, JSString *p1, JSValueConst op2) { + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + JSString *p2 = JS_VALUE_GET_STRING(op2); + size_t size1; + + if (p2->len == 0) + return TRUE; + if (p1->header.ref_count != 1) + return FALSE; + size1 = js_malloc_usable_size(ctx, p1); + if (p1->is_wide_char) { + if (size1 >= sizeof(*p1) + ((p1->len + p2->len) << 1)) { + if (p2->is_wide_char) { + memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1); + p1->len += p2->len; + return TRUE; + } else { + size_t i; + for (i = 0; i < p2->len; i++) { + p1->u.str16[p1->len++] = p2->u.str8[i]; + } + return TRUE; + } + } + } else if (!p2->is_wide_char) { + if (size1 >= sizeof(*p1) + p1->len + p2->len + 1) { + memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len); + p1->len += p2->len; + p1->u.str8[p1->len] = '\0'; + return TRUE; + } + } + } + return FALSE; +} + +static JSValue JS_ConcatString2(JSContext *ctx, JSValue op1, JSValue op2) +{ + JSValue ret; + JSString *p1, *p2; + p1 = JS_VALUE_GET_STRING(op1); + if (JS_ConcatStringInPlace(ctx, p1, op2)) { + JS_FreeValue(ctx, op2); + return op1; + } + p2 = JS_VALUE_GET_STRING(op2); + ret = JS_ConcatString1(ctx, p1, p2); + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); + return ret; +} + +/* Return the character at position 'idx'. 'val' must be a string or rope */ +static int string_rope_get(JSValueConst val, uint32_t idx) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + return string_get(JS_VALUE_GET_STRING(val), idx); + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + uint32_t len; + if (JS_VALUE_GET_TAG(r->left) == JS_TAG_STRING) + len = JS_VALUE_GET_STRING(r->left)->len; + else + len = JS_VALUE_GET_STRING_ROPE(r->left)->len; + if (idx < len) + return string_rope_get(r->left, idx); + else + return string_rope_get(r->right, idx - len); + } +} + +typedef struct { + JSValueConst stack[JS_STRING_ROPE_MAX_DEPTH]; + int stack_len; +} JSStringRopeIter; + +static void string_rope_iter_init(JSStringRopeIter *s, JSValueConst val) +{ + s->stack_len = 0; + s->stack[s->stack_len++] = val; +} + +/* iterate thru a rope and return the strings in order */ +static JSString *string_rope_iter_next(JSStringRopeIter *s) +{ + JSValueConst val; + JSStringRope *r; + + if (s->stack_len == 0) + return NULL; + val = s->stack[--s->stack_len]; + for(;;) { + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) + return JS_VALUE_GET_STRING(val); + r = JS_VALUE_GET_STRING_ROPE(val); + assert(s->stack_len < JS_STRING_ROPE_MAX_DEPTH); + s->stack[s->stack_len++] = r->right; + val = r->left; + } +} + +static uint32_t string_rope_get_len(JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) + return JS_VALUE_GET_STRING(val)->len; + else + return JS_VALUE_GET_STRING_ROPE(val)->len; +} + +static int js_string_rope_compare(JSContext *ctx, JSValueConst op1, + JSValueConst op2, BOOL eq_only) +{ + uint32_t len1, len2, len, pos1, pos2, l; + int res; + JSStringRopeIter it1, it2; + JSString *p1, *p2; + + len1 = string_rope_get_len(op1); + len2 = string_rope_get_len(op2); + /* no need to go further for equality test if + different length */ + if (eq_only && len1 != len2) + return 1; + len = min_uint32(len1, len2); + string_rope_iter_init(&it1, op1); + string_rope_iter_init(&it2, op2); + p1 = string_rope_iter_next(&it1); + p2 = string_rope_iter_next(&it2); + pos1 = 0; + pos2 = 0; + while (len != 0) { + l = min_uint32(p1->len - pos1, p2->len - pos2); + l = min_uint32(l, len); + res = js_string_memcmp(p1, pos1, p2, pos2, l); + if (res != 0) + return res; + len -= l; + pos1 += l; + if (pos1 >= p1->len) { + p1 = string_rope_iter_next(&it1); + pos1 = 0; + } + pos2 += l; + if (pos2 >= p2->len) { + p2 = string_rope_iter_next(&it2); + pos2 = 0; + } + } + + if (len1 == len2) + res = 0; + else if (len1 < len2) + res = -1; + else + res = 1; + return res; +} + +/* 'rope' must be a rope. return a string and modify the rope so that + it won't need to be linearized again. */ +static JSValue js_linearize_string_rope(JSContext *ctx, JSValue rope) +{ + StringBuffer b_s, *b = &b_s; + JSStringRope *r; + JSValue ret; + + r = JS_VALUE_GET_STRING_ROPE(rope); + + /* check whether it is already linearized */ + if (JS_VALUE_GET_TAG(r->right) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r->right)->len == 0) { + ret = JS_DupValue(ctx, r->left); + JS_FreeValue(ctx, rope); + return ret; + } + if (string_buffer_init2(ctx, b, r->len, r->is_wide_char)) + goto fail; + if (string_buffer_concat_value(b, rope)) + goto fail; + ret = string_buffer_end(b); + if (r->header.ref_count > 1) { + /* update the rope so that it won't need to be linearized again */ + JS_FreeValue(ctx, r->left); + JS_FreeValue(ctx, r->right); + r->left = JS_DupValue(ctx, ret); + r->right = JS_AtomToString(ctx, JS_ATOM_empty_string); + } + JS_FreeValue(ctx, rope); + return ret; + fail: + JS_FreeValue(ctx, rope); + return JS_EXCEPTION; +} + +static JSValue js_rebalancee_string_rope(JSContext *ctx, JSValueConst rope); + +/* op1 and op2 must be strings or string ropes */ +static JSValue js_new_string_rope(JSContext *ctx, JSValue op1, JSValue op2) +{ + uint32_t len; + int is_wide_char, depth; + JSStringRope *r; + JSValue res; + + if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + JSString *p1 = JS_VALUE_GET_STRING(op1); + len = p1->len; + is_wide_char = p1->is_wide_char; + depth = 0; + } else { + JSStringRope *r1 = JS_VALUE_GET_STRING_ROPE(op1); + len = r1->len; + is_wide_char = r1->is_wide_char; + depth = r1->depth; + } + + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + JSString *p2 = JS_VALUE_GET_STRING(op2); + len += p2->len; + is_wide_char |= p2->is_wide_char; + } else { + JSStringRope *r2 = JS_VALUE_GET_STRING_ROPE(op2); + len += r2->len; + is_wide_char |= r2->is_wide_char; + depth = max_int(depth, r2->depth); + } + if (len > JS_STRING_LEN_MAX) { + JS_ThrowInternalError(ctx, "string too long"); + goto fail; + } + r = js_malloc(ctx, sizeof(*r)); + if (!r) + goto fail; + r->header.ref_count = 1; + r->len = len; + r->is_wide_char = is_wide_char; + r->depth = depth + 1; + r->left = op1; + r->right = op2; + res = JS_MKPTR(JS_TAG_STRING_ROPE, r); + if (r->depth > JS_STRING_ROPE_MAX_DEPTH) { + JSValue res2; +#ifdef DUMP_ROPE_REBALANCE + printf("rebalance: initial depth=%d\n", r->depth); +#endif + res2 = js_rebalancee_string_rope(ctx, res); +#ifdef DUMP_ROPE_REBALANCE + if (JS_VALUE_GET_TAG(res2) == JS_TAG_STRING_ROPE) + printf("rebalance: final depth=%d\n", JS_VALUE_GET_STRING_ROPE(res2)->depth); +#endif + JS_FreeValue(ctx, res); + return res2; + } else { + return res; + } + fail: + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); + return JS_EXCEPTION; +} + +#define ROPE_N_BUCKETS 44 + +/* Fibonacii numbers starting from F_2 */ +static const uint32_t rope_bucket_len[ROPE_N_BUCKETS] = { + 1, 2, 3, 5, + 8, 13, 21, 34, + 55, 89, 144, 233, + 377, 610, 987, 1597, + 2584, 4181, 6765, 10946, + 17711, 28657, 46368, 75025, + 121393, 196418, 317811, 514229, + 832040, 1346269, 2178309, 3524578, + 5702887, 9227465, 14930352, 24157817, + 39088169, 63245986, 102334155, 165580141, + 267914296, 433494437, 701408733, 1134903170, /* > JS_STRING_LEN_MAX */ +}; + +static int js_rebalancee_string_rope_rec(JSContext *ctx, JSValue *buckets, + JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + JSString *p = JS_VALUE_GET_STRING(val); + uint32_t len, i; + JSValue a, b; + + len = p->len; + if (len == 0) + return 0; /* nothing to do */ + /* find the bucket i so that rope_bucket_len[i] <= len < + rope_bucket_len[i + 1] and concatenate the ropes in the + buckets before */ + a = JS_NULL; + i = 0; + while (len >= rope_bucket_len[i + 1]) { + b = buckets[i]; + if (!JS_IsNull(b)) { + buckets[i] = JS_NULL; + if (JS_IsNull(a)) { + a = b; + } else { + a = js_new_string_rope(ctx, b, a); + if (JS_IsException(a)) + return -1; + } + } + i++; + } + if (!JS_IsNull(a)) { + a = js_new_string_rope(ctx, a, JS_DupValue(ctx, val)); + if (JS_IsException(a)) + return -1; + } else { + a = JS_DupValue(ctx, val); + } + while (!JS_IsNull(buckets[i])) { + a = js_new_string_rope(ctx, buckets[i], a); + buckets[i] = JS_NULL; + if (JS_IsException(a)) + return -1; + i++; + } + buckets[i] = a; + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + js_rebalancee_string_rope_rec(ctx, buckets, r->left); + js_rebalancee_string_rope_rec(ctx, buckets, r->right); + } + return 0; +} + +/* Return a new rope which is balanced. Algorithm from "Ropes: an + Alternative to Strings", Hans-J. Boehm, Russ Atkinson and Michael + Plass. */ +static JSValue js_rebalancee_string_rope(JSContext *ctx, JSValueConst rope) +{ + JSValue buckets[ROPE_N_BUCKETS], a, b; + int i; + + for(i = 0; i < ROPE_N_BUCKETS; i++) + buckets[i] = JS_NULL; + if (js_rebalancee_string_rope_rec(ctx, buckets, rope)) + goto fail; + a = JS_NULL; + for(i = 0; i < ROPE_N_BUCKETS; i++) { + b = buckets[i]; + if (!JS_IsNull(b)) { + buckets[i] = JS_NULL; + if (JS_IsNull(a)) { + a = b; + } else { + a = js_new_string_rope(ctx, b, a); + if (JS_IsException(a)) + goto fail; + } + } + } + /* fail safe */ + if (JS_IsNull(a)) + return JS_AtomToString(ctx, JS_ATOM_empty_string); + else + return a; + fail: + for(i = 0; i < ROPE_N_BUCKETS; i++) { + JS_FreeValue(ctx, buckets[i]); + } + return JS_EXCEPTION; +} + +/* op1 and op2 are converted to strings. For convenience, op1 or op2 = JS_EXCEPTION are accepted and return JS_EXCEPTION. */ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) { - JSValue ret; JSString *p1, *p2; - if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING)) { + if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING && + JS_VALUE_GET_TAG(op1) != JS_TAG_STRING_ROPE)) { op1 = JS_ToStringFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); return JS_EXCEPTION; } } - if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING)) { + if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING && + JS_VALUE_GET_TAG(op2) != JS_TAG_STRING_ROPE)) { op2 = JS_ToStringFree(ctx, op2); if (JS_IsException(op2)) { JS_FreeValue(ctx, op1); return JS_EXCEPTION; } } - p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - /* XXX: could also check if p1 is empty */ - if (p2->len == 0) { - goto ret_op1; - } - if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char - && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) { - /* Concatenate in place in available space at the end of p1 */ - if (p1->is_wide_char) { - memcpy(str16(p1) + p1->len, str16(p2), p2->len << 1); - p1->len += p2->len; - } else { - memcpy(str8(p1) + p1->len, str8(p2), p2->len); - p1->len += p2->len; - str8(p1)[p1->len] = '\0'; + /* normal concatenation for short strings */ + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + p2 = JS_VALUE_GET_STRING(op2); + if (p2->len == 0) { + JS_FreeValue(ctx, op2); + return op1; + } + if (p2->len <= JS_STRING_ROPE_SHORT_LEN) { + if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + p1 = JS_VALUE_GET_STRING(op1); + if (p1->len <= JS_STRING_ROPE_SHORT2_LEN) { + return JS_ConcatString2(ctx, op1, op2); + } else { + return js_new_string_rope(ctx, op1, op2); + } + } else { + JSStringRope *r1; + r1 = JS_VALUE_GET_STRING_ROPE(op1); + if (JS_VALUE_GET_TAG(r1->right) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r1->right)->len <= JS_STRING_ROPE_SHORT_LEN) { + JSValue val, ret; + val = JS_ConcatString2(ctx, JS_DupValue(ctx, r1->right), op2); + if (JS_IsException(val)) { + JS_FreeValue(ctx, op1); + return JS_EXCEPTION; + } + ret = js_new_string_rope(ctx, JS_DupValue(ctx, r1->left), val); + JS_FreeValue(ctx, op1); + return ret; + } + } + } + } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + JSStringRope *r2; + p1 = JS_VALUE_GET_STRING(op1); + if (p1->len == 0) { + JS_FreeValue(ctx, op1); + return op2; + } + r2 = JS_VALUE_GET_STRING_ROPE(op2); + if (JS_VALUE_GET_TAG(r2->left) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r2->left)->len <= JS_STRING_ROPE_SHORT_LEN) { + JSValue val, ret; + val = JS_ConcatString2(ctx, op1, JS_DupValue(ctx, r2->left)); + if (JS_IsException(val)) { + JS_FreeValue(ctx, op2); + return JS_EXCEPTION; + } + ret = js_new_string_rope(ctx, val, JS_DupValue(ctx, r2->right)); + JS_FreeValue(ctx, op2); + return ret; } - ret_op1: - JS_FreeValue(ctx, op2); - return op1; } - ret = JS_ConcatString1(ctx, p1, p2); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return ret; + return js_new_string_rope(ctx, op1, op2); } /* Shape support */ @@ -4524,7 +4708,7 @@ static inline JSShapeProperty *get_shape_prop(JSShape *sh) static int init_shape_hash(JSRuntime *rt) { - rt->shape_hash_bits = 6; /* 64 shapes */ + rt->shape_hash_bits = 4; /* 16 shapes */ rt->shape_hash_size = 1 << rt->shape_hash_bits; rt->shape_hash_count = 0; rt->shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) * @@ -4603,19 +4787,14 @@ static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh) rt->shape_hash_count--; } -/* create a new empty shape with prototype 'proto' */ -static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, - int hash_size, int prop_size) +/* create a new empty shape with prototype 'proto'. It is not hashed */ +static inline JSShape *js_new_shape_nohash(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) { JSRuntime *rt = ctx->rt; void *sh_alloc; JSShape *sh; - /* resize the shape hash table if necessary */ - if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { - resize_shape_hash(rt, rt->shape_hash_bits + 1); - } - sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size)); if (!sh_alloc) return NULL; @@ -4623,7 +4802,7 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, sh->header.ref_count = 1; add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); if (proto) - js_dup(JS_MKPTR(JS_TAG_OBJECT, proto)); + JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto)); sh->proto = proto; memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) * hash_size); @@ -4631,11 +4810,29 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; + sh->is_hashed = FALSE; + return sh; +} + +/* create a new empty shape with prototype 'proto' */ +static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) +{ + JSRuntime *rt = ctx->rt; + JSShape *sh; + + /* resize the shape hash table if necessary */ + if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { + resize_shape_hash(rt, rt->shape_hash_bits + 1); + } + sh = js_new_shape_nohash(ctx, proto, hash_size, prop_size); + if (!sh) + return NULL; + /* insert in the hash table */ sh->hash = shape_initial_hash(proto); - sh->is_hashed = true; - sh->has_small_array_index = false; + sh->is_hashed = TRUE; js_shape_hash_link(ctx->rt, sh); return sh; } @@ -4666,9 +4863,9 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) sh = get_shape_from_alloc(sh_alloc, hash_size); sh->header.ref_count = 1; add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); - sh->is_hashed = false; + sh->is_hashed = FALSE; if (sh->proto) { - js_dup(JS_MKPTR(JS_TAG_OBJECT, sh->proto)); + JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { JS_DupAtom(ctx, pr->atom); @@ -4724,6 +4921,7 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, JSShapeProperty *pr; void *sh_alloc; intptr_t h; + JSShape *old_sh; sh = *psh; new_size = max_int(count, sh->prop_size * 3 / 2); @@ -4739,19 +4937,21 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, new_hash_size = sh->prop_hash_mask + 1; while (new_hash_size < new_size) new_hash_size = 2 * new_hash_size; + /* resize the property shapes. Using js_realloc() is not possible in + case the GC runs during the allocation */ + old_sh = sh; + sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); + if (!sh_alloc) + return -1; + sh = get_shape_from_alloc(sh_alloc, new_hash_size); + list_del(&old_sh->header.link); + /* copy all the shape properties */ + memcpy(sh, old_sh, + sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count); + list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); + if (new_hash_size != (sh->prop_hash_mask + 1)) { - JSShape *old_sh; /* resize the hash table and the properties */ - old_sh = sh; - sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); - if (!sh_alloc) - return -1; - sh = get_shape_from_alloc(sh_alloc, new_hash_size); - list_del(&old_sh->header.link); - /* copy all the fields and the properties */ - memcpy(sh, old_sh, - sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count); - list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); new_hash_mask = new_hash_size - 1; sh->prop_hash_mask = new_hash_mask; memset(prop_hash_end(sh) - new_hash_size, 0, @@ -4763,20 +4963,12 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, prop_hash_end(sh)[-h - 1] = i + 1; } } - js_free(ctx, get_alloc_from_shape(old_sh)); } else { - /* only resize the properties */ - list_del(&sh->header.link); - sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh), - get_shape_size(new_hash_size, new_size)); - if (unlikely(!sh_alloc)) { - /* insert again in the GC list */ - list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); - return -1; - } - sh = get_shape_from_alloc(sh_alloc, new_hash_size); - list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); + /* just copy the previous hash table */ + memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size, + sizeof(prop_hash_end(sh)[0]) * new_hash_size); } + js_free(ctx, get_alloc_from_shape(old_sh)); *psh = sh; sh->prop_size = new_size; return 0; @@ -4885,7 +5077,6 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, pr = &prop[sh->prop_count++]; pr->atom = JS_DupAtom(ctx, atom); pr->flags = prop_flags; - sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); /* add in hash table */ hash_mask = sh->prop_hash_mask; h = atom & hash_mask; @@ -5000,15 +5191,16 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas if (unlikely(!p)) goto fail; p->class_id = class_id; - p->extensible = true; + p->is_prototype = 0; + p->extensible = TRUE; p->free_mark = 0; p->is_exotic = 0; p->fast_array = 0; p->is_constructor = 0; - p->is_uncatchable_error = 0; + p->has_immutable_prototype = 0; p->tmp_mark = 0; p->is_HTMLDDA = 0; - p->first_weak_ref = NULL; + p->weakref_count = 0; p->u.opaque = NULL; p->shape = sh; p->prop = js_malloc(ctx, sizeof(JSProperty) * sh->prop_size); @@ -5039,7 +5231,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); } - pr->u.value = js_int32(0); + pr->u.value = JS_NewInt32(ctx, 0); } break; case JS_CLASS_C_FUNCTION: @@ -5118,6 +5310,50 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, return JS_NewObjectFromShape(ctx, sh, class_id); } +/* WARNING: the shape is not hashed. It is used for objects where + factorizing the shape is not relevant (prototypes, constructors) */ +static JSValue JS_NewObjectProtoClassAlloc(JSContext *ctx, JSValueConst proto_val, + JSClassID class_id, int n_alloc_props) +{ + JSShape *sh; + JSObject *proto; + int hash_size, hash_bits; + + if (n_alloc_props <= JS_PROP_INITIAL_SIZE) { + n_alloc_props = JS_PROP_INITIAL_SIZE; + hash_size = JS_PROP_INITIAL_HASH_SIZE; + } else { + hash_bits = 32 - clz32(n_alloc_props - 1); /* ceil(log2(radix)) */ + hash_size = 1 << hash_bits; + } + proto = get_proto_obj(proto_val); + sh = js_new_shape_nohash(ctx, proto, hash_size, n_alloc_props); + if (!sh) + return JS_EXCEPTION; + return JS_NewObjectFromShape(ctx, sh, class_id); +} + +#if 0 +static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj) +{ + JSObject *p; + + if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { + p = JS_VALUE_GET_OBJ(obj); + switch(p->class_id) { + case JS_CLASS_NUMBER: + case JS_CLASS_STRING: + case JS_CLASS_BOOLEAN: + case JS_CLASS_SYMBOL: + case JS_CLASS_DATE: + case JS_CLASS_BIG_INT: + return JS_DupValue(ctx, p->u.object_data); + } + } + return JS_UNDEFINED; +} +#endif + static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) { JSObject *p; @@ -5132,7 +5368,9 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) case JS_CLASS_DATE: case JS_CLASS_BIG_INT: JS_FreeValue(ctx, p->u.object_data); - p->u.object_data = val; + p->u.object_data = val; /* for JS_CLASS_STRING, 'val' must + be JS_TAG_STRING (and not a + rope) */ return 0; } } @@ -5142,7 +5380,7 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) return -1; } -JSValue JS_NewObjectClass(JSContext *ctx, JSClassID class_id) +JSValue JS_NewObjectClass(JSContext *ctx, int class_id) { return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id); } @@ -5152,134 +5390,29 @@ JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto) return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT); } -JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props, - const JSValue *values) -{ - JSShapeProperty *pr; - uint32_t *hash; - JSRuntime *rt; - JSObject *p; - JSShape *sh; - JSValue obj; - JSAtom atom; - intptr_t h; - int i; - - rt = ctx->rt; - obj = JS_NewObject(ctx); - if (JS_IsException(obj)) - return JS_EXCEPTION; - if (count > 0) { - p = JS_VALUE_GET_OBJ(obj); - sh = p->shape; - assert(sh->is_hashed); - assert(sh->header.ref_count == 1); - js_shape_hash_unlink(rt, sh); - if (resize_properties(ctx, &sh, p, count)) { - js_shape_hash_link(rt, sh); - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - p->shape = sh; - for (i = 0; i < count; i++) { - atom = props[i]; - pr = &sh->prop[i]; - sh->hash = shape_hash(shape_hash(sh->hash, atom), JS_PROP_C_W_E); - sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); - h = atom & sh->prop_hash_mask; - hash = &prop_hash_end(sh)[-h - 1]; - pr->hash_next = *hash; - *hash = i + 1; - pr->atom = JS_DupAtom(ctx, atom); - pr->flags = JS_PROP_C_W_E; - p->prop[i].u.value = values[i]; - } - js_shape_hash_link(rt, sh); - sh->prop_count = count; - } - return obj; -} - -JSValue JS_NewObjectFromStr(JSContext *ctx, int count, const char **props, - const JSValue *values) -{ - JSAtom atoms_s[16], *atoms = atoms_s; - JSValue ret; - int i; - - i = 0; - ret = JS_EXCEPTION; - if (count < 1) - goto out; - if (count > (int)countof(atoms_s)) { - atoms = js_malloc(ctx, count * sizeof(*atoms)); - if (!atoms) - return JS_EXCEPTION; - } - for (i = 0; i < count; i++) { - atoms[i] = JS_NewAtom(ctx, props[i]); - if (atoms[i] == JS_ATOM_NULL) - goto out; - } - ret = JS_NewObjectFrom(ctx, count, atoms, values); -out: - while (i-- > 0) - JS_FreeAtom(ctx, atoms[i]); - if (atoms != atoms_s) - js_free(ctx, atoms); - return ret; -} - JSValue JS_NewArray(JSContext *ctx) { return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape), JS_CLASS_ARRAY); } -// note: takes ownership of |values|, unlike js_create_array -JSValue JS_NewArrayFrom(JSContext *ctx, int count, const JSValue *values) -{ - JSObject *p; - JSValue obj; - int i; - - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - goto exception; - if (count > 0) { - p = JS_VALUE_GET_OBJ(obj); - if (expand_fast_array(ctx, p, count)) { - JS_FreeValue(ctx, obj); - goto exception; - } - p->u.array.count = count; - p->prop[0].u.value = js_int32(count); - memcpy(p->u.array.u.values, values, count * sizeof(*values)); - } - return obj; -exception: - for (i = 0; i < count; i++) - JS_FreeValue(ctx, values[i]); - return JS_EXCEPTION; -} - JSValue JS_NewObject(JSContext *ctx) { /* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */ return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT); } -static void js_function_set_properties(JSContext *ctx, JSValue func_obj, +static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj, JSAtom name, int len) { /* ES6 feature non compatible with ES5.1: length is configurable */ - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, js_int32(len), + JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len), JS_PROP_CONFIGURABLE); JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE); } -static bool js_class_has_bytecode(JSClassID class_id) +static BOOL js_class_has_bytecode(JSClassID class_id) { return (class_id == JS_CLASS_BYTECODE_FUNCTION || class_id == JS_CLASS_GENERATOR_FUNCTION || @@ -5299,8 +5432,8 @@ static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val) return p->u.func.function_bytecode; } -static void js_method_set_home_object(JSContext *ctx, JSValue func_obj, - JSValue home_obj) +static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj, + JSValueConst home_obj) { JSObject *p, *p1; JSFunctionBytecode *b; @@ -5317,7 +5450,7 @@ static void js_method_set_home_object(JSContext *ctx, JSValue func_obj, JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); } if (JS_VALUE_GET_TAG(home_obj) == JS_TAG_OBJECT) - p1 = JS_VALUE_GET_OBJ(js_dup(home_obj)); + p1 = JS_VALUE_GET_OBJ(JS_DupValue(ctx, home_obj)); else p1 = NULL; p->u.func.home_object = p1; @@ -5339,8 +5472,8 @@ static JSValue js_get_function_name(JSContext *ctx, JSAtom name) 'flags'. 'flags' is a bitmask of JS_PROP_HAS_GET and JS_PROP_HAS_SET. Also set the home object of the method. Return < 0 if exception. */ -static int js_method_set_properties(JSContext *ctx, JSValue func_obj, - JSAtom name, int flags, JSValue home_obj) +static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj, + JSAtom name, int flags, JSValueConst home_obj) { JSValue name_str; @@ -5360,17 +5493,20 @@ static int js_method_set_properties(JSContext *ctx, JSValue func_obj, } /* Note: at least 'length' arguments will be readable in 'argv' */ -/* `name` may be NULL, pure ASCII or UTF-8 encoded */ -JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, - const char *name, - int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val) +static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic, + JSValueConst proto_val, int n_fields) { JSValue func_obj; JSObject *p; JSAtom name_atom; - func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + if (n_fields > 0) { + func_obj = JS_NewObjectProtoClassAlloc(ctx, proto_val, JS_CLASS_C_FUNCTION, n_fields); + } else { + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + } if (JS_IsException(func_obj)) return func_obj; p = JS_VALUE_GET_OBJ(func_obj); @@ -5401,7 +5537,7 @@ JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, int length, JSCFunctionEnum cproto, int magic) { return JS_NewCFunction3(ctx, func, name, length, cproto, magic, - ctx->function_proto); + ctx->function_proto, 0); } typedef struct JSCFunctionDataRecord { @@ -5409,10 +5545,10 @@ typedef struct JSCFunctionDataRecord { uint8_t length; uint8_t data_len; uint16_t magic; - JSValue data[]; + JSValue data[0]; } JSCFunctionDataRecord; -static void js_c_function_data_finalizer(JSRuntime *rt, JSValueConst val) +static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val) { JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); int i; @@ -5457,7 +5593,7 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, arg_buf = argv; } - return s->func(ctx, this_val, argc, arg_buf, s->magic, vc(s->data)); + return s->func(ctx, this_val, argc, arg_buf, s->magic, s->data); } JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, @@ -5482,8 +5618,8 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, s->data_len = data_len; s->magic = magic; for(i = 0; i < data_len; i++) - s->data[i] = js_dup(data[i]); - JS_SetOpaqueInternal(func_obj, s); + s->data[i] = JS_DupValue(ctx, data[i]); + JS_SetOpaque(func_obj, s); js_function_set_properties(ctx, func_obj, JS_ATOM_empty_string, length); return func_obj; @@ -5572,6 +5708,11 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, return NULL; } +/* indicate that the object may be part of a function prototype cycle */ +static void set_cycle_flag(JSContext *ctx, JSValueConst obj) +{ +} + static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) { if (var_ref) { @@ -5579,16 +5720,18 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) if (--var_ref->header.ref_count == 0) { if (var_ref->is_detached) { JS_FreeValueRT(rt, var_ref->value); - remove_gc_object(&var_ref->header); } else { - list_del(&var_ref->header.link); /* still on the stack */ + list_del(&var_ref->var_ref_link); /* still on the stack */ + if (var_ref->async_func) + async_func_free(rt, var_ref->async_func); } + remove_gc_object(&var_ref->header); js_free_rt(rt, var_ref); } } } -static void js_array_finalizer(JSRuntime *rt, JSValueConst val) +static void js_array_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); int i; @@ -5610,7 +5753,7 @@ static void js_array_mark(JSRuntime *rt, JSValueConst val, } } -static void js_object_data_finalizer(JSRuntime *rt, JSValueConst val) +static void js_object_data_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JS_FreeValueRT(rt, p->u.object_data); @@ -5624,7 +5767,7 @@ static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, p->u.object_data, mark_func); } -static void js_c_function_finalizer(JSRuntime *rt, JSValueConst val) +static void js_c_function_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5641,7 +5784,7 @@ static void js_c_function_mark(JSRuntime *rt, JSValueConst val, mark_func(rt, &p->u.cfunc.realm->header); } -static void js_bytecode_function_finalizer(JSRuntime *rt, JSValueConst val) +static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val) { JSObject *p1, *p = JS_VALUE_GET_OBJ(val); JSFunctionBytecode *b; @@ -5680,7 +5823,7 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, if (var_refs) { for(i = 0; i < b->closure_var_count; i++) { JSVarRef *var_ref = var_refs[i]; - if (var_ref && var_ref->is_detached) { + if (var_ref) { mark_func(rt, &var_ref->header); } } @@ -5691,7 +5834,7 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, } } -static void js_bound_function_finalizer(JSRuntime *rt, JSValueConst val) +static void js_bound_function_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSBoundFunction *bf = p->u.bound_function; @@ -5718,11 +5861,19 @@ static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, bf->argv[i], mark_func); } -static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValueConst val) +static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSForInIterator *it = p->u.for_in_iterator; + int i; + JS_FreeValueRT(rt, it->obj); + if (!it->is_array) { + for(i = 0; i < it->atom_count; i++) { + JS_FreeAtomRT(rt, it->tab_atom[i].atom); + } + js_free_rt(rt, it->tab_atom); + } js_free_rt(rt, it); } @@ -5759,10 +5910,6 @@ static void free_object(JSRuntime *rt, JSObject *p) p->shape = NULL; p->prop = NULL; - if (unlikely(p->first_weak_ref)) { - reset_weak_ref(rt, &p->first_weak_ref); - } - finalizer = rt->class_array[p->class_id].finalizer; if (finalizer) (*finalizer)(rt, JS_MKPTR(JS_TAG_OBJECT, p)); @@ -5774,10 +5921,21 @@ static void free_object(JSRuntime *rt, JSObject *p) p->u.func.home_object = NULL; remove_gc_object(&p->header); - if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && p->header.ref_count != 0) { - list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list); + if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES) { + if (p->header.ref_count == 0 && p->weakref_count == 0) { + js_free_rt(rt, p); + } else { + /* keep the object structure because there are may be + references to it */ + list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list); + } } else { - js_free_rt(rt, p); + /* keep the object structure in case there are weak references to it */ + if (p->weakref_count == 0) { + js_free_rt(rt, p); + } else { + p->header.mark = 0; /* reset the mark so that the weakref can be freed */ + } } } @@ -5790,6 +5948,12 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp) case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: free_function_bytecode(rt, (JSFunctionBytecode *)gp); break; + case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: + __async_func_free(rt, (JSAsyncFunctionState *)gp); + break; + case JS_GC_OBJ_TYPE_MODULE: + js_free_module_def(rt, (JSModuleDef *)gp); + break; default: abort(); } @@ -5813,46 +5977,60 @@ static void free_zero_refcount(JSRuntime *rt) } /* called with the ref_count of 'v' reaches zero. */ -static void js_free_value_rt(JSRuntime *rt, JSValue v) +void __JS_FreeValueRT(JSRuntime *rt, JSValue v) { uint32_t tag = JS_VALUE_GET_TAG(v); -#ifdef ENABLE_DUMPS // JS_DUMP_FREE - if (check_dump_flag(rt, JS_DUMP_FREE)) { - /* Prevent invalid object access during GC */ - if ((rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) - || (tag != JS_TAG_OBJECT && tag != JS_TAG_FUNCTION_BYTECODE)) { - printf("Freeing "); - if (tag == JS_TAG_OBJECT) { - JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); - } else { - JS_DumpValue(rt, v); - printf("\n"); - } +#ifdef DUMP_FREE + { + printf("Freeing "); + if (tag == JS_TAG_OBJECT) { + JS_DumpObject(rt, JS_VALUE_GET_OBJ(v)); + } else { + JS_DumpValueShort(rt, v); + printf("\n"); } } #endif switch(tag) { case JS_TAG_STRING: - js_free_string0(rt, JS_VALUE_GET_STRING(v)); + { + JSString *p = JS_VALUE_GET_STRING(v); + if (p->atom_type) { + JS_FreeAtomStruct(rt, p); + } else { +#ifdef DUMP_LEAKS + list_del(&p->link); +#endif + js_free_rt(rt, p); + } + } + break; + case JS_TAG_STRING_ROPE: + /* Note: recursion is acceptable because the rope depth is bounded */ + { + JSStringRope *p = JS_VALUE_GET_STRING_ROPE(v); + JS_FreeValueRT(rt, p->left); + JS_FreeValueRT(rt, p->right); + js_free_rt(rt, p); + } break; case JS_TAG_OBJECT: case JS_TAG_FUNCTION_BYTECODE: + case JS_TAG_MODULE: { JSGCObjectHeader *p = JS_VALUE_GET_PTR(v); if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) { list_del(&p->link); list_add(&p->link, &rt->gc_zero_ref_count_list); + p->mark = 1; /* indicate that the object is about to be freed */ if (rt->gc_phase == JS_GC_PHASE_NONE) { free_zero_refcount(rt); } } } break; - case JS_TAG_MODULE: - abort(); /* never freed here */ - break; case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(v); @@ -5866,27 +6044,46 @@ static void js_free_value_rt(JSRuntime *rt, JSValue v) } break; default: - printf("js_free_value_rt: unknown tag=%d\n", tag); abort(); } } -void JS_FreeValueRT(JSRuntime *rt, JSValue v) +void __JS_FreeValue(JSContext *ctx, JSValue v) { - if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - if (--p->ref_count <= 0) { - js_free_value_rt(rt, v); - } - } + __JS_FreeValueRT(ctx->rt, v); } -void JS_FreeValue(JSContext *ctx, JSValue v) +/* garbage collection */ + +static void gc_remove_weak_objects(JSRuntime *rt) { - JS_FreeValueRT(ctx->rt, v); -} + struct list_head *el; -/* garbage collection */ + /* add the freed objects to rt->gc_zero_ref_count_list so that + rt->weakref_list is not modified while we traverse it */ + rt->gc_phase = JS_GC_PHASE_DECREF; + + list_for_each(el, &rt->weakref_list) { + JSWeakRefHeader *wh = list_entry(el, JSWeakRefHeader, link); + switch(wh->weakref_type) { + case JS_WEAKREF_TYPE_MAP: + map_delete_weakrefs(rt, wh); + break; + case JS_WEAKREF_TYPE_WEAKREF: + weakref_delete_weakref(rt, wh); + break; + case JS_WEAKREF_TYPE_FINREC: + finrec_delete_weakref(rt, wh); + break; + default: + abort(); + } + } + + rt->gc_phase = JS_GC_PHASE_NONE; + /* free the freed objects here. */ + free_zero_refcount(rt); +} static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type) @@ -5907,6 +6104,7 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_OBJECT: case JS_TAG_FUNCTION_BYTECODE: + case JS_TAG_MODULE: mark_func(rt, JS_VALUE_GET_PTR(val)); break; default: @@ -5915,22 +6113,6 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) } } -static void mark_weak_map_value(JSRuntime *rt, JSWeakRefRecord *first_weak_ref, JS_MarkFunc *mark_func) { - JSWeakRefRecord *wr; - JSMapRecord *mr; - JSMapState *s; - - for (wr = first_weak_ref; wr != NULL; wr = wr->next_weak_ref) { - if (wr->kind == JS_WEAK_REF_KIND_MAP) { - mr = wr->u.map_record; - s = mr->map; - assert(s->is_weak); - assert(!mr->empty); /* no iterator on WeakMap/WeakSet */ - JS_MarkValue(rt, mr->value, mark_func); - } - } -} - static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkFunc *mark_func) { @@ -5955,11 +6137,9 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, if (pr->u.getset.setter) mark_func(rt, &pr->u.getset.setter->header); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - if (pr->u.var_ref->is_detached) { - /* Note: the tag does not matter - provided it is a GC object */ - mark_func(rt, &pr->u.var_ref->header); - } + /* Note: the tag does not matter + provided it is a GC object */ + mark_func(rt, &pr->u.var_ref->header); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { js_autoinit_mark(rt, pr, mark_func); } @@ -5970,10 +6150,6 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, prs++; } - if (unlikely(p->first_weak_ref)) { - mark_weak_map_value(rt, p->first_weak_ref, mark_func); - } - if (p->class_id != JS_CLASS_OBJECT) { JSClassGCMark *gc_mark; gc_mark = rt->class_array[p->class_id].gc_mark; @@ -5997,16 +6173,32 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, case JS_GC_OBJ_TYPE_VAR_REF: { JSVarRef *var_ref = (JSVarRef *)gp; - /* only detached variable referenced are taken into account */ - assert(var_ref->is_detached); - JS_MarkValue(rt, *var_ref->pvalue, mark_func); + if (var_ref->is_detached) { + JS_MarkValue(rt, *var_ref->pvalue, mark_func); + } else if (var_ref->async_func) { + mark_func(rt, &var_ref->async_func->header); + } } break; case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: { - JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp; - if (s->is_active) - async_func_mark(rt, &s->func_state, mark_func); + JSAsyncFunctionState *s = (JSAsyncFunctionState *)gp; + JSStackFrame *sf = &s->frame; + JSValue *sp; + + if (!s->is_completed) { + JS_MarkValue(rt, sf->cur_func, mark_func); + JS_MarkValue(rt, s->this_val, mark_func); + /* sf->cur_sp = NULL if the function is running */ + if (sf->cur_sp) { + /* if the function is running, cur_sp is not known so we + cannot mark the stack. Marking the variables is not needed + because a running function cannot be part of a removable + cycle */ + for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) + JS_MarkValue(rt, *sp, mark_func); + } + } JS_MarkValue(rt, s->resolving_funcs[0], mark_func); JS_MarkValue(rt, s->resolving_funcs[1], mark_func); } @@ -6025,6 +6217,12 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkContext(rt, ctx, mark_func); } break; + case JS_GC_OBJ_TYPE_MODULE: + { + JSModuleDef *m = (JSModuleDef *)gp; + js_mark_module_def(rt, m, mark_func); + } + break; default: abort(); } @@ -6103,8 +6301,8 @@ static void gc_free_cycles(JSRuntime *rt) { struct list_head *el, *el1; JSGCObjectHeader *p; -#ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE - bool header_done = false; +#ifdef DUMP_GC_FREE + BOOL header_done = FALSE; #endif rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES; @@ -6114,21 +6312,21 @@ static void gc_free_cycles(JSRuntime *rt) if (el == &rt->tmp_obj_list) break; p = list_entry(el, JSGCObjectHeader, link); - /* Only need to free the GC object associated with JS - values. The rest will be automatically removed because they - must be referenced by them. */ + /* Only need to free the GC object associated with JS values + or async functions. The rest will be automatically removed + because they must be referenced by them. */ switch(p->gc_obj_type) { case JS_GC_OBJ_TYPE_JS_OBJECT: case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: -#ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE - if (check_dump_flag(rt, JS_DUMP_GC_FREE)) { - if (!header_done) { - printf("Freeing cycles:\n"); - JS_DumpObjectHeader(rt); - header_done = true; - } - JS_DumpGCObject(rt, p); + case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: + case JS_GC_OBJ_TYPE_MODULE: +#ifdef DUMP_GC_FREE + if (!header_done) { + printf("Freeing cycles:\n"); + JS_DumpObjectHeader(rt); + header_done = TRUE; } + JS_DumpGCObject(rt, p); #endif free_gc_object(rt, p); break; @@ -6143,15 +6341,30 @@ static void gc_free_cycles(JSRuntime *rt) list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) { p = list_entry(el, JSGCObjectHeader, link); assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT || - p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); - js_free_rt(rt, p); + p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE || + p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION || + p->gc_obj_type == JS_GC_OBJ_TYPE_MODULE); + if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT && + ((JSObject *)p)->weakref_count != 0) { + /* keep the object because there are weak references to it */ + p->mark = 0; + } else { + js_free_rt(rt, p); + } } init_list_head(&rt->gc_zero_ref_count_list); } -void JS_RunGC(JSRuntime *rt) +static void JS_RunGCInternal(JSRuntime *rt, BOOL remove_weak_objects) { + if (remove_weak_objects) { + /* free the weakly referenced object or symbol structures, delete + the associated Map/Set entries and queue the finalization + registry callbacks. */ + gc_remove_weak_objects(rt); + } + /* decrement the reference of the children of each object. mark = 1 after this pass. */ gc_decref(rt); @@ -6163,14 +6376,19 @@ void JS_RunGC(JSRuntime *rt) gc_free_cycles(rt); } +void JS_RunGC(JSRuntime *rt) +{ + JS_RunGCInternal(rt, TRUE); +} + /* Return false if not an object or if the object has already been freed (zombie objects are visible in finalizers when freeing cycles). */ -bool JS_IsLiveObject(JSRuntime *rt, JSValueConst obj) +BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj) { JSObject *p; if (!JS_IsObject(obj)) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); return !p->free_mark; } @@ -6188,7 +6406,7 @@ typedef struct JSMemoryUsage_helper { int64_t js_func_pc2line_size; } JSMemoryUsage_helper; -static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp); +static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp); static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp) { @@ -6205,36 +6423,41 @@ static void compute_bytecode_size(JSFunctionBytecode *b, JSMemoryUsage_helper *h int memory_used_count, js_func_size, i; memory_used_count = 0; - js_func_size = sizeof(*b); + js_func_size = offsetof(JSFunctionBytecode, debug); if (b->vardefs) { js_func_size += (b->arg_count + b->var_count) * sizeof(*b->vardefs); } if (b->cpool) { js_func_size += b->cpool_count * sizeof(*b->cpool); for (i = 0; i < b->cpool_count; i++) { - JSValue val = b->cpool[i]; + JSValueConst val = b->cpool[i]; compute_value_size(val, hp); } } if (b->closure_var) { js_func_size += b->closure_var_count * sizeof(*b->closure_var); } - if (b->byte_code_buf) { + if (!b->read_only_bytecode && b->byte_code_buf) { hp->js_func_code_size += b->byte_code_len; } - memory_used_count++; - js_func_size += b->source_len + 1; - if (b->pc2line_len) { - memory_used_count++; - hp->js_func_pc2line_count += 1; - hp->js_func_pc2line_size += b->pc2line_len; + if (b->has_debug) { + js_func_size += sizeof(*b) - offsetof(JSFunctionBytecode, debug); + if (b->debug.source) { + memory_used_count++; + js_func_size += b->debug.source_len + 1; + } + if (b->debug.pc2line_len) { + memory_used_count++; + hp->js_func_pc2line_count += 1; + hp->js_func_pc2line_size += b->debug.pc2line_len; + } } hp->js_func_size += js_func_size; hp->js_func_count += 1; hp->memory_used_count += memory_used_count; } -static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp) +static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp) { switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_STRING: @@ -6258,7 +6481,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) s->malloc_limit = rt->malloc_state.malloc_limit; s->memory_used_count = 2; /* rt + rt->class_array */ - s->memory_used_size = sizeof(JSRuntime) + sizeof(JSClass) * rt->class_count; + s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count; list_for_each(el, &rt->context_list) { JSContext *ctx = list_entry(el, JSContext, link); @@ -6530,8 +6753,9 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) { - fprintf(fp, "QuickJS-ng memory usage -- %s version, %d-bit, %s Endian, malloc limit: %"PRId64"\n\n", - JS_GetVersion(), (int)sizeof(void *) * 8, is_be() ? "Big" : "Little", s->malloc_limit); + fprintf(fp, "QuickJS memory usage -- " CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n", + (int)sizeof(void *) * 8, s->malloc_limit); +#if 1 if (rt) { static const struct { const char *name; @@ -6587,6 +6811,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) } fprintf(fp, "\n"); } +#endif fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE"); if (s->malloc_count) { @@ -6653,7 +6878,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) JSValue JS_GetGlobalObject(JSContext *ctx) { - return js_dup(ctx->global_obj); + return JS_DupValue(ctx, ctx->global_obj); } /* WARNING: obj is freed */ @@ -6662,6 +6887,7 @@ JSValue JS_Throw(JSContext *ctx, JSValue obj) JSRuntime *rt = ctx->rt; JS_FreeValue(ctx, rt->current_exception); rt->current_exception = obj; + rt->current_exception_is_uncatchable = FALSE; return JS_EXCEPTION; } @@ -6675,7 +6901,7 @@ JSValue JS_GetException(JSContext *ctx) return val; } -bool JS_HasException(JSContext *ctx) +JS_BOOL JS_HasException(JSContext *ctx) { return !JS_IsUninitialized(ctx->rt->current_exception); } @@ -6735,71 +6961,98 @@ static int get_sleb128(int32_t *pval, const uint8_t *buf, return ret; } +/* use pc_value = -1 to get the position of the function definition */ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, - uint32_t pc_value, int *col) + uint32_t pc_value, int *pcol_num) { const uint8_t *p_end, *p; - int new_line_num, new_col_num, line_num, col_num, pc, v, ret; + int new_line_num, line_num, pc, v, ret, new_col_num, col_num; + uint32_t val; unsigned int op; - *col = 1; - p = b->pc2line_buf; - if (!p) + if (!b->has_debug || !b->debug.pc2line_buf) + goto fail; /* function was stripped */ + + p = b->debug.pc2line_buf; + p_end = p + b->debug.pc2line_len; + + /* get the function line and column numbers */ + ret = get_leb128(&val, p, p_end); + if (ret < 0) goto fail; - p_end = p + b->pc2line_len; - pc = 0; - line_num = b->line_num; - col_num = b->col_num; - while (p < p_end) { - op = *p++; - if (op == 0) { - uint32_t val; - ret = get_leb128(&val, p, p_end); - if (ret < 0) - goto fail; - pc += val; - p += ret; + p += ret; + line_num = val + 1; + + ret = get_leb128(&val, p, p_end); + if (ret < 0) + goto fail; + p += ret; + col_num = val + 1; + + if (pc_value != -1) { + pc = 0; + while (p < p_end) { + op = *p++; + if (op == 0) { + ret = get_leb128(&val, p, p_end); + if (ret < 0) + goto fail; + pc += val; + p += ret; + ret = get_sleb128(&v, p, p_end); + if (ret < 0) + goto fail; + p += ret; + new_line_num = line_num + v; + } else { + op -= PC2LINE_OP_FIRST; + pc += (op / PC2LINE_RANGE); + new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE; + } ret = get_sleb128(&v, p, p_end); if (ret < 0) goto fail; p += ret; - new_line_num = line_num + v; - } else { - op -= PC2LINE_OP_FIRST; - pc += (op / PC2LINE_RANGE); - new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE; + new_col_num = col_num + v; + + if (pc_value < pc) + goto done; + line_num = new_line_num; + col_num = new_col_num; } - ret = get_sleb128(&v, p, p_end); - if (ret < 0) - goto fail; - p += ret; - new_col_num = col_num + v; - if (pc_value < pc) - break; - line_num = new_line_num; - col_num = new_col_num; } - *col = col_num; + done: + *pcol_num = col_num; return line_num; -fail: - /* should never happen */ - return b->line_num; + fail: + *pcol_num = 0; + return 0; } -/* in order to avoid executing arbitrary code during the stack trace - generation, we only look at simple 'name' properties containing a - string. */ -static const char *get_func_name(JSContext *ctx, JSValueConst func) +/* return a string property without executing arbitrary JS code (used + when dumping the stack trace or in debug print). */ +static const char *get_prop_string(JSContext *ctx, JSValueConst obj, JSAtom prop) { + JSObject *p; JSProperty *pr; JSShapeProperty *prs; - JSValue val; + JSValueConst val; - if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT) - return NULL; - prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name); - if (!prs) + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return NULL; + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { + /* we look at one level in the prototype to handle the 'name' + field of the Error objects */ + p = p->shape->proto; + if (!p) + return NULL; + prs = find_own_property(&pr, p, prop); + if (!prs) + return NULL; + } + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) return NULL; val = pr->u.value; @@ -6808,340 +7061,171 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func) return JS_ToCString(ctx, val); } -/* Note: it is important that no exception is returned by this function */ -static bool can_add_backtrace(JSValueConst obj) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - return false; - p = JS_VALUE_GET_OBJ(obj); - if (p->class_id != JS_CLASS_ERROR && p->class_id != JS_CLASS_DOM_EXCEPTION) - return false; - if (find_own_property1(p, JS_ATOM_stack)) - return false; - return true; -} - #define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0) -/* only taken into account if filename is provided */ -#define JS_BACKTRACE_FLAG_SINGLE_LEVEL (1 << 1) -#define JS_BACKTRACE_FLAG_FILTER_FUNC (1 << 2) /* if filename != NULL, an additional level is added with the filename and line number information (used for parse error). */ -static void build_backtrace(JSContext *ctx, JSValueConst error_val, - JSValueConst filter_func, const char *filename, - int line_num, int col_num, int backtrace_flags) +static void build_backtrace(JSContext *ctx, JSValueConst error_obj, + const char *filename, int line_num, int col_num, + int backtrace_flags) { - JSStackFrame *sf, *sf_start; - JSValue stack, prepare, saved_exception; + JSStackFrame *sf; + JSValue str; DynBuf dbuf; const char *func_name_str; const char *str1; JSObject *p; - JSFunctionBytecode *b; - bool backtrace_barrier, has_prepare, has_filter_func; - JSRuntime *rt; - JSCallSiteData csd[64]; - uint32_t i; - double d; - int stack_trace_limit; - - rt = ctx->rt; - if (rt->in_build_stack_trace) - return; - rt->in_build_stack_trace = true; - - // Save exception because conversion to double may fail. - saved_exception = JS_GetException(ctx); - - // Extract stack trace limit. - // Ignore error since it sets d to NAN anyway. - // coverity[check_return] - JS_ToFloat64(ctx, &d, ctx->error_stack_trace_limit); - if (isnan(d) || d < 0.0) - stack_trace_limit = 0; - else if (d > INT32_MAX) - stack_trace_limit = INT32_MAX; - else - stack_trace_limit = fabs(d); - - // Restore current exception. - JS_Throw(ctx, saved_exception); - saved_exception = JS_UNINITIALIZED; - - stack_trace_limit = min_int(stack_trace_limit, countof(csd)); - stack_trace_limit = max_int(stack_trace_limit, 0); - has_prepare = false; - has_filter_func = backtrace_flags & JS_BACKTRACE_FLAG_FILTER_FUNC; - i = 0; - - if (!JS_IsNull(ctx->error_ctor)) { - prepare = js_dup(ctx->error_prepare_stack); - has_prepare = JS_IsFunction(ctx, prepare); - } - - if (has_prepare) { - saved_exception = JS_GetException(ctx); - if (stack_trace_limit == 0) - goto done; - if (filename) - js_new_callsite_data2(ctx, &csd[i++], filename, line_num, col_num); - } else { - js_dbuf_init(ctx, &dbuf); - if (stack_trace_limit == 0) - goto done; - if (filename) { - i++; - dbuf_printf(&dbuf, " at %s", filename); - if (line_num != -1) - dbuf_printf(&dbuf, ":%d:%d", line_num, col_num); - dbuf_putc(&dbuf, '\n'); - } - } - - if (filename && (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)) - goto done; - - sf_start = rt->current_stack_frame; - /* Find the frame we want to start from. Note that when a filter is used the filter - function will be the first, but we also specify we want to skip the first one. */ - if (has_filter_func) { - for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) { - if (js_same_value(ctx, sf->cur_func, filter_func)) { - sf_start = sf; - break; - } + if (!JS_IsObject(error_obj)) + return; /* protection in the out of memory case */ + + js_dbuf_init(ctx, &dbuf); + if (filename) { + dbuf_printf(&dbuf, " at %s", filename); + if (line_num != -1) + dbuf_printf(&dbuf, ":%d:%d", line_num, col_num); + dbuf_putc(&dbuf, '\n'); + str = JS_NewString(ctx, filename); + if (JS_IsException(str)) + return; + /* Note: SpiderMonkey does that, could update once there is a standard */ + if (JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 || + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 || + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) { + return; } } - - for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) { + for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) { + if (sf->js_mode & JS_MODE_BACKTRACE_BARRIER) + break; if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) { backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL; continue; } + func_name_str = get_prop_string(ctx, sf->cur_func, JS_ATOM_name); + if (!func_name_str || func_name_str[0] == '\0') + str1 = ""; + else + str1 = func_name_str; + dbuf_printf(&dbuf, " at %s", str1); + JS_FreeCString(ctx, func_name_str); p = JS_VALUE_GET_OBJ(sf->cur_func); - b = NULL; - backtrace_barrier = false; - if (js_class_has_bytecode(p->class_id)) { - b = p->u.func.function_bytecode; - backtrace_barrier = b->backtrace_barrier; - } + JSFunctionBytecode *b; + const char *atom_str; + int line_num1, col_num1; - if (has_prepare) { - js_new_callsite_data(ctx, &csd[i], sf); - } else { - /* func_name_str is UTF-8 encoded if needed */ - func_name_str = get_func_name(ctx, sf->cur_func); - if (!func_name_str || func_name_str[0] == '\0') - str1 = ""; - else - str1 = func_name_str; - dbuf_printf(&dbuf, " at %s", str1); - JS_FreeCString(ctx, func_name_str); - - if (b && sf->cur_pc) { - const char *atom_str; - int line_num1, col_num1; - uint32_t pc; - - pc = sf->cur_pc - b->byte_code_buf - 1; - line_num1 = find_line_num(ctx, b, pc, &col_num1); - atom_str = b->filename ? JS_AtomToCString(ctx, b->filename) : NULL; - dbuf_printf(&dbuf, " (%s", atom_str ? atom_str : ""); + b = p->u.func.function_bytecode; + if (b->has_debug) { + line_num1 = find_line_num(ctx, b, + sf->cur_pc - b->byte_code_buf - 1, &col_num1); + atom_str = JS_AtomToCString(ctx, b->debug.filename); + dbuf_printf(&dbuf, " (%s", + atom_str ? atom_str : ""); JS_FreeCString(ctx, atom_str); - if (line_num1 != -1) + if (line_num1 != 0) dbuf_printf(&dbuf, ":%d:%d", line_num1, col_num1); dbuf_putc(&dbuf, ')'); - } else if (b) { - // FIXME(bnoordhuis) Missing `sf->cur_pc = pc` in bytecode - // handler in JS_CallInternal. Almost never user observable - // except with intercepting JS proxies that throw exceptions. - dbuf_printf(&dbuf, " (missing)"); - } else { - dbuf_printf(&dbuf, " (native)"); } - dbuf_putc(&dbuf, '\n'); - } - i++; - - /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */ - if (backtrace_barrier) - break; - } - done: - if (has_prepare) { - int j = 0, k; - stack = JS_NewArray(ctx); - if (JS_IsException(stack)) { - stack = JS_NULL; } else { - for (; j < i; j++) { - JSValue v = js_new_callsite(ctx, &csd[j]); - if (JS_IsException(v)) - break; - if (JS_DefinePropertyValueUint32(ctx, stack, j, v, JS_PROP_C_W_E) < 0) { - JS_FreeValue(ctx, v); - break; - } - } - } - // Clear the csd's we didn't use in case of error. - for (k = j; k < i; k++) { - JS_FreeValue(ctx, csd[k].filename); - JS_FreeValue(ctx, csd[k].func); - JS_FreeValue(ctx, csd[k].func_name); + dbuf_printf(&dbuf, " (native)"); } - JSValueConst args[] = { - error_val, - stack, - }; - JSValue stack2 = JS_Call(ctx, prepare, ctx->error_ctor, countof(args), args); - JS_FreeValue(ctx, stack); - if (JS_IsException(stack2)) - stack = JS_NULL; - else - stack = stack2; - JS_FreeValue(ctx, prepare); - JS_Throw(ctx, saved_exception); - } else { - if (dbuf_error(&dbuf)) - stack = JS_NULL; - else - stack = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); - dbuf_free(&dbuf); + dbuf_putc(&dbuf, '\n'); } - - if (JS_IsUndefined(ctx->error_back_trace)) - ctx->error_back_trace = js_dup(stack); - if (has_filter_func || can_add_backtrace(error_val)) { - JS_DefinePropertyValue(ctx, error_val, JS_ATOM_stack, stack, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - } else { - JS_FreeValue(ctx, stack); - } - - rt->in_build_stack_trace = false; + dbuf_putc(&dbuf, '\0'); + if (dbuf_error(&dbuf)) + str = JS_NULL; + else + str = JS_NewString(ctx, (char *)dbuf.buf); + dbuf_free(&dbuf); + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } -JSValue JS_NewError(JSContext *ctx) +/* Note: it is important that no exception is returned by this function */ +static BOOL is_backtrace_needed(JSContext *ctx, JSValueConst obj) { - JSValue obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR); - if (JS_IsException(obj)) - return JS_EXCEPTION; - build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0); - return obj; + JSObject *p; + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) + return FALSE; + p = JS_VALUE_GET_OBJ(obj); + if (p->class_id != JS_CLASS_ERROR) + return FALSE; + if (find_own_property1(p, JS_ATOM_stack)) + return FALSE; + return TRUE; } -static JSValue JS_MakeError2(JSContext *ctx, JSErrorEnum error_num, - bool add_backtrace, const char *message) +JSValue JS_NewError(JSContext *ctx) { - JSValue obj, msg; - - if (error_num == JS_PLAIN_ERROR) { - obj = JS_NewObjectClass(ctx, JS_CLASS_ERROR); - } else { - obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num], - JS_CLASS_ERROR); - } - if (JS_IsException(obj)) - return JS_EXCEPTION; - msg = JS_NewString(ctx, message); - if (JS_IsException(msg)) - msg = JS_NewString(ctx, "Invalid error message"); - if (!JS_IsException(msg)) { - JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - } - if (add_backtrace) - build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, 0); - return obj; + return JS_NewObjectClass(ctx, JS_CLASS_ERROR); } -static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) -JS_MakeError(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, - JS_PRINTF_FORMAT const char *fmt, va_list ap) +static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, + const char *fmt, va_list ap, BOOL add_backtrace) { char buf[256]; + JSValue obj, ret; vsnprintf(buf, sizeof(buf), fmt, ap); - return JS_MakeError2(ctx, error_num, add_backtrace, buf); -} - -/* fmt and arguments may be pure ASCII or UTF-8 encoded contents */ -static JSValue JS_PRINTF_FORMAT_ATTR(4, 0) -JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, bool add_backtrace, - JS_PRINTF_FORMAT const char *fmt, va_list ap) -{ - JSValue obj; - - obj = JS_MakeError(ctx, error_num, add_backtrace, fmt, ap); + obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num], + JS_CLASS_ERROR); if (unlikely(JS_IsException(obj))) { /* out of memory: throw JS_NULL to avoid recursing */ obj = JS_NULL; + } else { + JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, + JS_NewString(ctx, buf), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (add_backtrace) { + build_backtrace(ctx, obj, NULL, 0, 0, 0); + } } - return JS_Throw(ctx, obj); + ret = JS_Throw(ctx, obj); + return ret; } -static JSValue JS_PRINTF_FORMAT_ATTR(3, 0) -JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, - JS_PRINTF_FORMAT const char *fmt, va_list ap) +static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, + const char *fmt, va_list ap) { JSRuntime *rt = ctx->rt; JSStackFrame *sf; - bool add_backtrace; + BOOL add_backtrace; /* the backtrace is added later if called from a bytecode function */ sf = rt->current_stack_frame; add_backtrace = !rt->in_out_of_memory && (!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL)); - return JS_ThrowError2(ctx, error_num, add_backtrace, fmt, ap); -} - -#define JS_ERROR_MAP(X) \ - X(Internal, INTERNAL) \ - X(Plain, PLAIN) \ - X(Range, RANGE) \ - X(Reference, REFERENCE) \ - X(Syntax, SYNTAX) \ - X(Type, TYPE) \ - -#define X(lc, uc) \ - JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ - JS_New##lc##Error(JSContext *ctx, \ - JS_PRINTF_FORMAT const char *fmt, ...) \ - { \ - JSValue val; \ - va_list ap; \ - \ - va_start(ap, fmt); \ - val = JS_MakeError(ctx, JS_##uc##_ERROR, \ - /*add_backtrace*/true, fmt, ap); \ - va_end(ap); \ - return val; \ - } \ - JSValue JS_PRINTF_FORMAT_ATTR(2, 3) \ - JS_Throw##lc##Error(JSContext *ctx, \ - JS_PRINTF_FORMAT const char *fmt, ...) \ - { \ - JSValue val; \ - va_list ap; \ - \ - va_start(ap, fmt); \ - val = JS_ThrowError(ctx, JS_##uc##_ERROR, fmt, ap); \ - va_end(ap); \ - return val; \ - } \ - -JS_ERROR_MAP(X) - -#undef X -#undef JS_ERROR_MAP - -static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, JS_PRINTF_FORMAT const char *fmt, ...) + return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace); +} + +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_SYNTAX_ERROR, fmt, ap); + va_end(ap); + return val; +} + +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap); + va_end(ap); + return val; +} + +static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...) { va_list ap; @@ -7152,30 +7236,30 @@ static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, va_end(ap); return -1; } else { - return false; + return FALSE; } } -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif // __GNUC__ -static JSValue JS_ThrowTypeErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom) +/* never use it directly */ +static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...) { char buf[ATOM_GET_STR_BUF_SIZE]; - JS_AtomGetStr(ctx, buf, sizeof(buf), atom); - return JS_ThrowTypeError(ctx, fmt, buf); + return JS_ThrowTypeError(ctx, fmt, + JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); } -static JSValue JS_ThrowSyntaxErrorAtom(JSContext *ctx, const char *fmt, JSAtom atom) +/* never use it directly */ +static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...) { char buf[ATOM_GET_STR_BUF_SIZE]; - JS_AtomGetStr(ctx, buf, sizeof(buf), atom); - return JS_ThrowSyntaxError(ctx, fmt, buf); + return JS_ThrowSyntaxError(ctx, fmt, + JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); } -#ifdef __GNUC__ -#pragma GCC diagnostic pop // ignored "-Wformat-nonliteral" -#endif // __GNUC__ + +/* %s is replaced by 'atom'. The macro is used so that gcc can check + the format string. */ +#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "") +#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "") static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) { @@ -7184,29 +7268,57 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom); return -1; } else { - return false; + return FALSE; } } +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_REFERENCE_ERROR, fmt, ap); + va_end(ap); + return val; +} + +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_RANGE_ERROR, fmt, ap); + va_end(ap); + return val; +} + +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_INTERNAL_ERROR, fmt, ap); + va_end(ap); + return val; +} + JSValue JS_ThrowOutOfMemory(JSContext *ctx) { JSRuntime *rt = ctx->rt; if (!rt->in_out_of_memory) { - rt->in_out_of_memory = true; + rt->in_out_of_memory = TRUE; JS_ThrowInternalError(ctx, "out of memory"); - rt->in_out_of_memory = false; + rt->in_out_of_memory = FALSE; } return JS_EXCEPTION; } static JSValue JS_ThrowStackOverflow(JSContext *ctx) { - return JS_ThrowRangeError(ctx, "Maximum call stack size exceeded"); -} - -static JSValue JS_ThrowTypeErrorNotAFunction(JSContext *ctx) -{ - return JS_ThrowTypeError(ctx, "not a function"); + return JS_ThrowInternalError(ctx, "stack overflow"); } static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx) @@ -7222,7 +7334,7 @@ static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx) static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name) { char buf[ATOM_GET_STR_BUF_SIZE]; - return JS_ThrowReferenceError(ctx, "%s is not defined", + return JS_ThrowReferenceError(ctx, "'%s' is not defined", JS_AtomGetStr(ctx, buf, sizeof(buf), name)); } @@ -7236,7 +7348,7 @@ static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name) static JSValue JS_ThrowReferenceErrorUninitialized2(JSContext *ctx, JSFunctionBytecode *b, - int idx, bool is_ref) + int idx, BOOL is_ref) { JSAtom atom = JS_ATOM_NULL; if (is_ref) { @@ -7260,7 +7372,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id) static void JS_ThrowInterrupted(JSContext *ctx) { JS_ThrowInternalError(ctx, "interrupted"); - JS_SetUncatchableError(ctx, ctx->rt->current_exception); + JS_SetUncatchableException(ctx, TRUE); } static no_inline __exception int __js_poll_interrupts(JSContext *ctx) @@ -7285,9 +7397,20 @@ static inline __exception int js_poll_interrupts(JSContext *ctx) } } -/* return -1 (exception) or true/false */ +static void JS_SetImmutablePrototype(JSContext *ctx, JSValueConst obj) +{ + JSObject *p; + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) + return; + p = JS_VALUE_GET_OBJ(obj); + p->has_immutable_prototype = TRUE; +} + +/* Return -1 (exception) or TRUE/FALSE. 'throw_flag' = FALSE indicates + that it is called from Reflect.setPrototypeOf(). */ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, - JSValueConst proto_val, bool throw_flag) + JSValueConst proto_val, + BOOL throw_flag) { JSObject *proto, *p, *p1; JSShape *sh; @@ -7313,26 +7436,39 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, } if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - return true; + return TRUE; + + if (unlikely(p->is_exotic)) { + const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; + int ret; + if (em && em->set_prototype) { + ret = em->set_prototype(ctx, obj, proto_val); + if (ret == 0 && throw_flag) { + JS_ThrowTypeError(ctx, "proxy: bad prototype"); + return -1; + } else { + return ret; + } + } + } - if (unlikely(p->class_id == JS_CLASS_PROXY)) - return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag); sh = p->shape; if (sh->proto == proto) - return true; - if (p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) { + return TRUE; + if (unlikely(p->has_immutable_prototype)) { if (throw_flag) { - JS_ThrowTypeError(ctx, "'Immutable prototype object \'Object.prototype\' cannot have their prototype set'"); + JS_ThrowTypeError(ctx, "prototype is immutable"); return -1; + } else { + return FALSE; } - return false; } - if (!p->extensible) { + if (unlikely(!p->extensible)) { if (throw_flag) { JS_ThrowTypeError(ctx, "object is not extensible"); return -1; } else { - return false; + return FALSE; } } if (proto) { @@ -7344,13 +7480,13 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, JS_ThrowTypeError(ctx, "circular prototype chain"); return -1; } else { - return false; + return FALSE; } } /* Note: for Proxy objects, proto is NULL */ p1 = p1->shape->proto; } while (p1 != NULL); - js_dup(proto_val); + JS_DupValue(ctx, proto_val); } if (js_shape_prepare_update(ctx, p, NULL)) @@ -7359,65 +7495,75 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, if (sh->proto) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); sh->proto = proto; - return true; + if (proto) + proto->is_prototype = TRUE; + if (p->is_prototype) { + /* track modification of Array.prototype */ + if (unlikely(p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]))) { + ctx->std_array_prototype = FALSE; + } + } + return TRUE; } -/* return -1 (exception) or true/false */ -int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValue proto_val) +/* return -1 (exception) or TRUE/FALSE */ +int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val) { - return JS_SetPrototypeInternal(ctx, obj, proto_val, true); + return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE); } /* Only works for primitive types, otherwise return JS_NULL. */ static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val) { - JSValue ret; switch(JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: - ret = ctx->class_proto[JS_CLASS_BIG_INT]; + val = ctx->class_proto[JS_CLASS_BIG_INT]; break; case JS_TAG_INT: case JS_TAG_FLOAT64: - ret = ctx->class_proto[JS_CLASS_NUMBER]; + val = ctx->class_proto[JS_CLASS_NUMBER]; break; case JS_TAG_BOOL: - ret = ctx->class_proto[JS_CLASS_BOOLEAN]; + val = ctx->class_proto[JS_CLASS_BOOLEAN]; break; case JS_TAG_STRING: - ret = ctx->class_proto[JS_CLASS_STRING]; + case JS_TAG_STRING_ROPE: + val = ctx->class_proto[JS_CLASS_STRING]; break; case JS_TAG_SYMBOL: - ret = ctx->class_proto[JS_CLASS_SYMBOL]; + val = ctx->class_proto[JS_CLASS_SYMBOL]; break; case JS_TAG_OBJECT: case JS_TAG_NULL: case JS_TAG_UNDEFINED: default: - ret = JS_NULL; + val = JS_NULL; break; } - return ret; + return val; } -/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */ +/* Return an Object, JS_NULL or JS_EXCEPTION in case of exotic object. */ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) { JSValue val; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p; p = JS_VALUE_GET_OBJ(obj); - if (unlikely(p->class_id == JS_CLASS_PROXY)) { - val = js_proxy_getPrototypeOf(ctx, obj); - } else { - p = p->shape->proto; - if (!p) - val = JS_NULL; - else - val = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + if (unlikely(p->is_exotic)) { + const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; + if (em && em->get_prototype) { + return em->get_prototype(ctx, obj); + } } + p = p->shape->proto; + if (!p) + val = JS_NULL; + else + val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); } else { - val = js_dup(JS_GetPrototypePrimitive(ctx, obj)); + val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj)); } return val; } @@ -7430,25 +7576,17 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj) return obj1; } -int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres) { - return js_get_length64(ctx, pres, obj); -} - -int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len) { - return js_set_length64(ctx, obj, len); -} - -/* return true, false or (-1) in case of exception */ +/* return TRUE, FALSE or (-1) in case of exception */ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) { JSValue obj_proto; JSObject *proto; const JSObject *p, *proto1; - int ret; + BOOL ret; if (!JS_IsFunction(ctx, obj)) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_BOUND_FUNCTION) { JSBoundFunction *s = p->u.bound_function; @@ -7457,7 +7595,7 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, /* Only explicitly boxed values are instances of constructors */ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; + return FALSE; obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype); if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) { if (!JS_IsException(obj_proto)) @@ -7470,10 +7608,10 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, for(;;) { proto1 = p->shape->proto; if (!proto1) { - /* slow case if proxy in the prototype chain */ - if (unlikely(p->class_id == JS_CLASS_PROXY)) { + /* slow case if exotic object in the prototype chain */ + if (unlikely(p->is_exotic && !p->fast_array)) { JSValue obj1; - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); for(;;) { obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsException(obj1)) { @@ -7481,12 +7619,12 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, break; } if (JS_IsNull(obj1)) { - ret = false; + ret = FALSE; break; } if (proto == JS_VALUE_GET_OBJ(obj1)) { JS_FreeValue(ctx, obj1); - ret = true; + ret = TRUE; break; } /* must check for timeout to avoid infinite loop */ @@ -7497,13 +7635,13 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, } } } else { - ret = false; + ret = FALSE; } break; } p = proto1; if (proto == p) { - ret = true; + ret = TRUE; break; } } @@ -7512,7 +7650,7 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, return ret; } -/* return true, false or (-1) in case of exception */ +/* return TRUE, FALSE or (-1) in case of exception */ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) { JSValue method; @@ -7537,60 +7675,13 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) return JS_OrdinaryIsInstanceOf(ctx, val, obj); } -#include "builtin-array-fromasync.h" - -static JSValue js_bytecode_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, - void *opaque) -{ - switch ((uintptr_t)opaque) { - default: - abort(); - case JS_BUILTIN_ARRAY_FROMASYNC: - { - JSValue obj = JS_ReadObject(ctx, qjsc_builtin_array_fromasync, - sizeof(qjsc_builtin_array_fromasync), - JS_READ_OBJ_BYTECODE); - if (JS_IsException(obj)) - return JS_EXCEPTION; - JSValue fun = JS_EvalFunction(ctx, obj); - if (JS_IsException(fun)) - return JS_EXCEPTION; - assert(JS_IsFunction(ctx, fun)); - JSValue args[] = { - JS_NewCFunction(ctx, js_array_constructor, "Array", 0), - JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", 1, - JS_CFUNC_constructor_or_func_magic, - JS_TYPE_ERROR), - JS_AtomToValue(ctx, JS_ATOM_Symbol_asyncIterator), - JS_NewCFunctionMagic(ctx, js_object_defineProperty, - "Object.defineProperty", 3, - JS_CFUNC_generic_magic, 0), - JS_AtomToValue(ctx, JS_ATOM_Symbol_iterator), - }; - JSValue result = JS_Call(ctx, fun, JS_UNDEFINED, - countof(args), vc(args)); - for (size_t i = 0; i < countof(args); i++) - JS_FreeValue(ctx, args[i]); - JS_FreeValue(ctx, fun); - if (JS_SetPrototypeInternal(ctx, result, ctx->function_proto, - /*throw_flag*/true) < 0) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } - return result; - } - } - return JS_UNDEFINED; -} - /* return the value associated to the autoinit property or an exception */ typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); -static JSAutoInitFunc *const js_autoinit_func_table[] = { +static JSAutoInitFunc *js_autoinit_func_table[] = { js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */ js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */ JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */ - js_bytecode_autoinit, /* JS_AUTOINIT_ID_BYTECODE */ }; /* warning: 'prs' is reallocated after it */ @@ -7600,12 +7691,14 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValue val; JSContext *realm; JSAutoInitFunc *func; - + JSAutoInitIDEnum id; + if (js_shape_prepare_update(ctx, p, &prs)) return -1; realm = js_autoinit_get_realm(pr); - func = js_autoinit_func_table[js_autoinit_get_id(pr)]; + id = js_autoinit_get_id(pr); + func = js_autoinit_func_table[id]; /* 'func' shall not modify the object properties 'pr' */ val = func(realm, p, prop, pr->u.init.opaque); js_autoinit_free(ctx->rt, pr); @@ -7613,13 +7706,21 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, pr->u.value = JS_UNDEFINED; if (JS_IsException(val)) return -1; - pr->u.value = val; + if (id == JS_AUTOINIT_ID_MODULE_NS && + JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + /* WARNING: a varref is returned as a string ! */ + prs->flags |= JS_PROP_VARREF; + pr->u.var_ref = JS_VALUE_GET_PTR(val); + pr->u.var_ref->header.ref_count++; + } else { + pr->u.value = val; + } return 0; } -static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValueConst this_obj, - bool throw_ref_error) +JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, + JSAtom prop, JSValueConst this_obj, + BOOL throw_ref_error) { JSObject *p; JSProperty *pr; @@ -7639,14 +7740,27 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, { JSString *p1 = JS_VALUE_GET_STRING(obj); if (__JS_AtomIsTaggedInt(prop)) { - uint32_t idx, ch; + uint32_t idx; + idx = __JS_AtomToUInt32(prop); + if (idx < p1->len) { + return js_new_string_char(ctx, string_get(p1, idx)); + } + } else if (prop == JS_ATOM_length) { + return JS_NewInt32(ctx, p1->len); + } + } + break; + case JS_TAG_STRING_ROPE: + { + JSStringRope *p1 = JS_VALUE_GET_STRING_ROPE(obj); + if (__JS_AtomIsTaggedInt(prop)) { + uint32_t idx; idx = __JS_AtomToUInt32(prop); if (idx < p1->len) { - ch = string_get(p1, idx); - return js_new_string_char(ctx, ch); + return js_new_string_char(ctx, string_rope_get(obj, idx)); } } else if (prop == JS_ATOM_length) { - return js_int32(p1->len); + return JS_NewInt32(ctx, p1->len); } } break; @@ -7672,14 +7786,14 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } else { JSValue func = JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter); /* Note: the field could be removed in the getter */ - func = js_dup(func); + func = JS_DupValue(ctx, func); return JS_CallFree(ctx, func, this_obj, 0, NULL); } } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { JSValue val = *pr->u.var_ref->pvalue; if (unlikely(JS_IsUninitialized(val))) return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); - return js_dup(val); + return JS_DupValue(ctx, val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) @@ -7687,7 +7801,7 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, continue; } } else { - return js_dup(pr->u.value); + return JS_DupValue(ctx, pr->u.value); } } if (unlikely(p->is_exotic)) { @@ -7698,10 +7812,12 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, if (idx < p->u.array.count) { /* we avoid duplicating the code */ return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); - } else if (is_typed_array(p->class_id)) { + } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { return JS_UNDEFINED; } - } else if (is_typed_array(p->class_id)) { + } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { int ret; ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { @@ -7718,7 +7834,7 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, /* XXX: should pass throw_ref_error */ /* Note: if 'p' is a prototype, it can be freed in the called function */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); retval = em->get_property(ctx, obj1, prop, this_obj); JS_FreeValue(ctx, obj1); return retval; @@ -7730,7 +7846,7 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, /* Note: if 'p' is a prototype, it can be freed in the called function */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); if (ret < 0) @@ -7758,11 +7874,6 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } -JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop) -{ - return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, false); -} - static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) { return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist", @@ -7772,7 +7883,7 @@ static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) /* Private fields can be added even on non extensible objects or Proxies */ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, - JSValue name, JSValue val) + JSValueConst name, JSValue val) { JSObject *p; JSShapeProperty *prs; @@ -7788,7 +7899,7 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, JS_ThrowTypeErrorNotASymbol(ctx); goto fail; } - prop = js_symbol_to_atom(ctx, name); + prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (prs) { @@ -7819,14 +7930,14 @@ static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj, /* safety check */ if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) return JS_ThrowTypeErrorNotASymbol(ctx); - prop = js_symbol_to_atom(ctx, name); + prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (!prs) { JS_ThrowTypeErrorPrivateNotFound(ctx, prop); return JS_EXCEPTION; } - return js_dup(pr->u.value); + return JS_DupValue(ctx, pr->u.value); } static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, @@ -7846,7 +7957,7 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, JS_ThrowTypeErrorNotASymbol(ctx); goto fail; } - prop = js_symbol_to_atom(ctx, name); + prop = js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(name)); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (!prs) { @@ -7885,9 +7996,9 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) JS_FreeValue(ctx, brand); return -1; } - pr->u.value = js_dup(brand); + pr->u.value = JS_DupValue(ctx, brand); } else { - brand = js_dup(pr->u.value); + brand = JS_DupValue(ctx, pr->u.value); } brand_atom = js_symbol_to_atom(ctx, brand); @@ -7907,18 +8018,17 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) } else { JS_FreeAtom(ctx, brand_atom); } - return 0; } /* return a boolean telling if the brand of the home object of 'func' is present on 'obj' or -1 in case of exception */ -static int JS_CheckBrand(JSContext *ctx, JSValue obj, JSValue func) +static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) { JSObject *p, *p1, *home_obj; JSShapeProperty *prs; JSProperty *pr; - JSValue brand; + JSValueConst brand; /* get the home object of 'func' */ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) @@ -7946,20 +8056,20 @@ static int JS_CheckBrand(JSContext *ctx, JSValue obj, JSValue func) return -1; } p = JS_VALUE_GET_OBJ(obj); - prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand)); + prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, JS_VALUE_CONST_CAST(brand))); return (prs != NULL); } -static uint32_t js_string_obj_get_length(JSContext *ctx, JSValueConst obj) +static uint32_t js_string_obj_get_length(JSContext *ctx, + JSValueConst obj) { JSObject *p; - JSString *p1; uint32_t len = 0; /* This is a class exotic method: obj class_id is JS_CLASS_STRING */ p = JS_VALUE_GET_OBJ(obj); if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) { - p1 = JS_VALUE_GET_STRING(p->u.object_data); + JSString *p1 = JS_VALUE_GET_STRING(p->u.object_data); len = p1->len; } return len; @@ -7971,7 +8081,7 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque) JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom; JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom; uint32_t v1, v2; - bool atom1_is_integer, atom2_is_integer; + BOOL atom1_is_integer, atom2_is_integer; atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1); atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2); @@ -7984,7 +8094,7 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque) return 1; } -static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) +void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) { uint32_t i; if (tab) { @@ -8008,7 +8118,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, JSAtom atom; uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count; uint32_t num_index, str_index, sym_index, exotic_count, exotic_keys_count; - bool is_enumerable, num_sorted; + BOOL is_enumerable, num_sorted; uint32_t num_key; JSAtomKindEnum kind; @@ -8071,14 +8181,14 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, atom = tab_exotic[i].atom; kind = JS_AtomGetKind(ctx, atom); if (((flags >> kind) & 1) != 0) { - is_enumerable = false; + is_enumerable = FALSE; if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) { JSPropertyDescriptor desc; int res; /* set the "is_enumerable" field if necessary */ res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); if (res < 0) { - js_free_prop_enum(ctx, tab_exotic, exotic_count); + JS_FreePropertyEnum(ctx, tab_exotic, exotic_count); return -1; } if (res) { @@ -8099,11 +8209,25 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, /* fill them */ - atom_count = num_keys_count + str_keys_count + sym_keys_count + exotic_keys_count; + atom_count = num_keys_count + str_keys_count; + if (atom_count < str_keys_count) + goto add_overflow; + atom_count += sym_keys_count; + if (atom_count < sym_keys_count) + goto add_overflow; + atom_count += exotic_keys_count; + if (atom_count < exotic_keys_count || atom_count > INT32_MAX) { + add_overflow: + JS_ThrowOutOfMemory(ctx); + JS_FreePropertyEnum(ctx, tab_exotic, exotic_count); + return -1; + } + /* XXX: need generic way to test for js_malloc(ctx, a * b) overflow */ + /* avoid allocating 0 bytes */ tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1)); if (!tab_atom) { - js_free_prop_enum(ctx, tab_exotic, exotic_count); + JS_FreePropertyEnum(ctx, tab_exotic, exotic_count); return -1; } @@ -8111,7 +8235,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, str_index = num_keys_count; sym_index = str_index + str_keys_count; - num_sorted = true; + num_sorted = TRUE; sh = p->shape; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; @@ -8122,7 +8246,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, ((flags >> kind) & 1) != 0) { if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; - num_sorted = false; + num_sorted = FALSE; } else if (kind == JS_ATOM_KIND_STRING) { j = str_index++; } else { @@ -8148,10 +8272,10 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, for(i = 0; i < len; i++) { tab_atom[num_index].atom = __JS_AtomFromUInt32(i); if (tab_atom[num_index].atom == JS_ATOM_NULL) { - js_free_prop_enum(ctx, tab_atom, num_index); + JS_FreePropertyEnum(ctx, tab_atom, num_index); return -1; } - tab_atom[num_index].is_enumerable = true; + tab_atom[num_index].is_enumerable = TRUE; num_index++; } } @@ -8199,7 +8323,7 @@ int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, } /* Return -1 if exception, - false if the property does not exist, true if it exists. If true is + FALSE if the property does not exist, TRUE if it exists. If TRUE is returned, the property descriptor 'desc' is filled present. */ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop) @@ -8219,16 +8343,16 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { desc->flags |= JS_PROP_GETSET; if (pr->u.getset.getter) - desc->getter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); + desc->getter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (pr->u.getset.setter) - desc->setter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); + desc->setter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { JSValue val = *pr->u.var_ref->pvalue; if (unlikely(JS_IsUninitialized(val))) { JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } - desc->value = js_dup(val); + desc->value = JS_DupValue(ctx, val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) @@ -8236,7 +8360,7 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, goto retry; } } else { - desc->value = js_dup(pr->u.value); + desc->value = JS_DupValue(ctx, pr->u.value); } } else { /* for consistency, send the exception even if desc is NULL */ @@ -8249,7 +8373,7 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, /* nothing to do: delay instantiation until actual value and/or attributes are read */ } } - return true; + return TRUE; } if (p->is_exotic) { if (p->fast_array) { @@ -8265,7 +8389,7 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, desc->setter = JS_UNDEFINED; desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); } - return true; + return TRUE; } } } else { @@ -8276,7 +8400,7 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, } } } - return false; + return FALSE; } int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, @@ -8289,41 +8413,54 @@ int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop); } -void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, - uint32_t len) -{ - js_free_prop_enum(ctx, tab, len); -} - -/* return -1 if exception (Proxy object only) or true/false */ +/* return -1 if exception (exotic object only) or TRUE/FALSE */ int JS_IsExtensible(JSContext *ctx, JSValueConst obj) { JSObject *p; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); - if (unlikely(p->class_id == JS_CLASS_PROXY)) - return js_proxy_isExtensible(ctx, obj); - else - return p->extensible; + if (unlikely(p->is_exotic)) { + const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; + if (em && em->is_extensible) { + return em->is_extensible(ctx, obj); + } + } + return p->extensible; } -/* return -1 if exception (Proxy object only) or true/false */ +/* return -1 if exception (exotic object only) or TRUE/FALSE */ int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) { JSObject *p; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); - if (unlikely(p->class_id == JS_CLASS_PROXY)) - return js_proxy_preventExtensions(ctx, obj); - p->extensible = false; - return true; + if (unlikely(p->is_exotic)) { + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { + JSTypedArray *ta; + JSArrayBuffer *abuf; + /* resizable type arrays return FALSE */ + ta = p->u.typed_array; + abuf = ta->buffer->u.array_buffer; + if (ta->track_rab || + (array_buffer_is_resizable(abuf) && !abuf->shared)) + return FALSE; + } else { + const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; + if (em && em->prevent_extensions) { + return em->prevent_extensions(ctx, obj); + } + } + } + p->extensible = FALSE; + return TRUE; } -/* return -1 if exception otherwise true or false */ +/* return -1 if exception otherwise TRUE or FALSE */ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) { JSObject *p; @@ -8331,42 +8468,43 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) JSValue obj1; if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); for(;;) { if (p->is_exotic) { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->has_property) { /* has_property can free the prototype */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); ret = em->has_property(ctx, obj1, prop); JS_FreeValue(ctx, obj1); return ret; } } /* JS_GetOwnPropertyInternal can free the prototype */ - js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop); JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); if (ret != 0) return ret; - if (is_typed_array(p->class_id)) { + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) return -1; - return false; + return FALSE; } } p = p->shape->proto; if (!p) break; } - return false; + return FALSE; } /* val must be a symbol */ -static JSAtom js_symbol_to_atom(JSContext *ctx, JSValueConst val) +static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val) { JSAtomStruct *p = JS_VALUE_GET_PTR(val); return js_get_atom_index(ctx->rt, p); @@ -8399,154 +8537,128 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) return atom; } -static bool js_get_fast_array_element(JSContext *ctx, JSObject *p, - uint32_t idx, JSValue *pval) -{ - switch(p->class_id) { - case JS_CLASS_ARRAY: - case JS_CLASS_ARGUMENTS: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_dup(p->u.array.u.values[idx]); - return true; - case JS_CLASS_INT8_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_int32(p->u.array.u.int8_ptr[idx]); - return true; - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_int32(p->u.array.u.uint8_ptr[idx]); - return true; - case JS_CLASS_INT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_int32(p->u.array.u.int16_ptr[idx]); - return true; - case JS_CLASS_UINT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_int32(p->u.array.u.uint16_ptr[idx]); - return true; - case JS_CLASS_INT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_int32(p->u.array.u.int32_ptr[idx]); - return true; - case JS_CLASS_UINT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_uint32(p->u.array.u.uint32_ptr[idx]); - return true; - case JS_CLASS_BIG_INT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]); - return true; - case JS_CLASS_BIG_UINT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]); - return true; - case JS_CLASS_FLOAT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_float64(fromfp16(p->u.array.u.fp16_ptr[idx])); - return true; - case JS_CLASS_FLOAT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_float64(p->u.array.u.float_ptr[idx]); - return true; - case JS_CLASS_FLOAT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) return false; - *pval = js_float64(p->u.array.u.double_ptr[idx]); - return true; - default: - return false; - } -} - static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSValue prop) { JSAtom atom; JSValue ret; - uint32_t tag; - tag = JS_VALUE_GET_TAG(this_obj); - if (likely(tag == JS_TAG_OBJECT)) { - if (JS_VALUE_GET_TAG(prop) == JS_TAG_INT) { - JSObject *p = JS_VALUE_GET_OBJ(this_obj); - uint32_t idx = JS_VALUE_GET_INT(prop); - JSValue val; - /* fast path for array and typed array access */ - if (js_get_fast_array_element(ctx, p, idx, &val)) - return val; + if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT && + JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) { + JSObject *p; + uint32_t idx; + /* fast path for array access */ + p = JS_VALUE_GET_OBJ(this_obj); + idx = JS_VALUE_GET_INT(prop); + switch(p->class_id) { + case JS_CLASS_ARRAY: + case JS_CLASS_ARGUMENTS: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_DupValue(ctx, p->u.array.u.values[idx]); + case JS_CLASS_INT8_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]); + case JS_CLASS_UINT8C_ARRAY: + case JS_CLASS_UINT8_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]); + case JS_CLASS_INT16_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]); + case JS_CLASS_UINT16_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]); + case JS_CLASS_INT32_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]); + case JS_CLASS_UINT32_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]); + case JS_CLASS_BIG_INT64_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]); + case JS_CLASS_BIG_UINT64_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]); + case JS_CLASS_FLOAT16_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return __JS_NewFloat64(ctx, fromfp16(p->u.array.u.fp16_ptr[idx])); + case JS_CLASS_FLOAT32_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]); + case JS_CLASS_FLOAT64_ARRAY: + if (unlikely(idx >= p->u.array.count)) goto slow_path; + return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]); + default: + goto slow_path; } } else { - switch(tag) { - case JS_TAG_NULL: - JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "cannot read property of null"); - case JS_TAG_UNDEFINED: + slow_path: + /* ToObject() must be done before ToPropertyKey() */ + if (JS_IsNull(this_obj) || JS_IsUndefined(this_obj)) { JS_FreeValue(ctx, prop); - return JS_ThrowTypeError(ctx, "cannot read property of undefined"); + return JS_ThrowTypeError(ctx, "cannot read property of %s", JS_IsNull(this_obj) ? "null" : "undefined"); } + atom = JS_ValueToAtom(ctx, prop); + JS_FreeValue(ctx, prop); + if (unlikely(atom == JS_ATOM_NULL)) + return JS_EXCEPTION; + ret = JS_GetProperty(ctx, this_obj, atom); + JS_FreeAtom(ctx, atom); + return ret; } - atom = JS_ValueToAtom(ctx, prop); - JS_FreeValue(ctx, prop); - if (unlikely(atom == JS_ATOM_NULL)) - return JS_EXCEPTION; - ret = JS_GetProperty(ctx, this_obj, atom); - JS_FreeAtom(ctx, atom); - return ret; } JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx) { - return JS_GetPropertyInt64(ctx, this_obj, idx); + return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx)); } /* Check if an object has a generalized numeric property. Return value: - -1 for exception, *pval set to JS_EXCEPTION - true if property exists, stored into *pval, - false if property does not exist. *pval set to JS_UNDEFINED. + -1 for exception, + TRUE if property exists, stored into *pval, + FALSE if proprty does not exist. */ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval) { - JSValue val; + JSValue val = JS_UNDEFINED; JSAtom prop; int present; - if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT && - (uint64_t)idx <= INT32_MAX)) { - /* fast path for array and typed array access */ - JSObject *p = JS_VALUE_GET_OBJ(obj); - if (js_get_fast_array_element(ctx, p, idx, pval)) - return true; - } - val = JS_EXCEPTION; - present = -1; - prop = JS_NewAtomInt64(ctx, idx); - if (likely(prop != JS_ATOM_NULL)) { - present = JS_HasProperty(ctx, obj, prop); + if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) { + /* fast path */ + present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx)); if (present > 0) { - val = JS_GetProperty(ctx, obj, prop); + val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); if (unlikely(JS_IsException(val))) present = -1; - } else if (present == false) { - val = JS_UNDEFINED; } - JS_FreeAtom(ctx, prop); + } else { + prop = JS_NewAtomInt64(ctx, idx); + present = -1; + if (likely(prop != JS_ATOM_NULL)) { + present = JS_HasProperty(ctx, obj, prop); + if (present > 0) { + val = JS_GetProperty(ctx, obj, prop); + if (unlikely(JS_IsException(val))) + present = -1; + } + JS_FreeAtom(ctx, prop); + } } *pval = val; return present; } -JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) +static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) { JSAtom prop; JSValue val; - if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT && - (uint64_t)idx <= INT32_MAX)) { - /* fast path for array and typed array access */ - JSObject *p = JS_VALUE_GET_OBJ(obj); - if (js_get_fast_array_element(ctx, p, idx, &val)) - return val; + if ((uint64_t)idx <= INT32_MAX) { + /* fast path for fast arrays */ + return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); } prop = JS_NewAtomInt64(ctx, idx); if (prop == JS_ATOM_NULL) @@ -8557,7 +8669,6 @@ JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) return val; } -/* `prop` may be pure ASCII or UTF-8 encoded */ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop) { @@ -8578,6 +8689,14 @@ static JSProperty *add_property(JSContext *ctx, { JSShape *sh, *new_sh; + if (unlikely(p->is_prototype)) { + /* track addition of small integer properties to Array.prototype and Object.prototype */ + if (unlikely((p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) || + p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) && + __JS_AtomIsTaggedInt(prop))) { + ctx->std_array_prototype = FALSE; + } + } sh = p->shape; if (sh->is_hashed) { /* try to find an existing shape */ @@ -8602,7 +8721,7 @@ static JSProperty *add_property(JSContext *ctx, if (!new_sh) return NULL; /* hash the cloned shape */ - new_sh->is_hashed = true; + new_sh->is_hashed = TRUE; js_shape_hash_link(ctx->rt, new_sh); js_free_shape(ctx->rt, p->shape); p->shape = new_sh; @@ -8647,6 +8766,11 @@ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx, p->u.array.u.values = NULL; /* fail safe */ p->u.array.u1.size = 0; p->fast_array = 0; + + /* track modification of Array.prototype */ + if (unlikely(p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]))) { + ctx->std_array_prototype = FALSE; + } return 0; } @@ -8670,7 +8794,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) if (likely(pr->atom == atom)) { /* found ! */ if (!(pr->flags & JS_PROP_CONFIGURABLE)) - return false; + return FALSE; /* realloc the shape if needed */ if (lpr) lpr_idx = lpr - get_shape_prop(sh); @@ -8699,7 +8823,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) { compact_properties(ctx, p); } - return true; + return TRUE; } lpr = pr; h = pr->hash_next; @@ -8716,13 +8840,13 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) if (idx == p->u.array.count - 1) { JS_FreeValue(ctx, p->u.array.u.values[idx]); p->u.array.count = idx; - return true; + return TRUE; } if (convert_fast_array_to_array(ctx, p)) return -1; goto redo; } else { - return false; + return FALSE; } } } else { @@ -8733,7 +8857,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) } } /* not found */ - return true; + return TRUE; } static int call_setter(JSContext *ctx, JSObject *setter, @@ -8743,13 +8867,13 @@ static int call_setter(JSContext *ctx, JSObject *setter, if (likely(setter)) { func = JS_MKPTR(JS_TAG_OBJECT, setter); /* Note: the field could be removed in the setter */ - func = js_dup(func); - ret = JS_CallFree(ctx, func, this_obj, 1, vc(&val)); + func = JS_DupValue(ctx, func); + ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val); JS_FreeValue(ctx, val); if (JS_IsException(ret)) return -1; JS_FreeValue(ctx, ret); - return true; + return TRUE; } else { JS_FreeValue(ctx, val); if ((flags & JS_PROP_THROW) || @@ -8757,7 +8881,7 @@ static int call_setter(JSContext *ctx, JSObject *setter, JS_ThrowTypeError(ctx, "no setter for property"); return -1; } - return false; + return FALSE; } } @@ -8769,7 +8893,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int i, ret; /* Note: this call can reallocate the properties of 'p' */ - ret = JS_ToArrayLengthFree(ctx, &len, val, false); + ret = JS_ToArrayLengthFree(ctx, &len, val, FALSE); if (ret) return -1; /* JS_ToArrayLengthFree() must be done before the read-only test */ @@ -8784,7 +8908,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } p->u.array.count = len; } - p->prop[0].u.value = js_uint32(len); + p->prop[0].u.value = JS_NewUint32(ctx, len); } else { /* Note: length is always a uint32 because the object is an array */ @@ -8844,12 +8968,12 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } else { cur_len = len; } - set_value(ctx, &p->prop[0].u.value, js_uint32(cur_len)); + set_value(ctx, &p->prop[0].u.value, JS_NewUint32(ctx, cur_len)); if (unlikely(cur_len > len)) { return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable"); } } - return true; + return TRUE; } /* return -1 if exception */ @@ -8870,9 +8994,9 @@ static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len) } /* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array = - true and p->extensible = true */ -static int add_fast_array_element(JSContext *ctx, JSObject *p, - JSValue val, int flags) + TRUE and p->extensible = TRUE */ +static inline int add_fast_array_element(JSContext *ctx, JSObject *p, + JSValue val, int flags) { uint32_t new_len, array_len; /* extend the array by one */ @@ -8887,7 +9011,7 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, JS_FreeValue(ctx, val); return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); } - p->prop[0].u.value = js_int32(new_len); + p->prop[0].u.value = JS_NewInt32(ctx, new_len); } } if (unlikely(new_len > p->u.array.u1.size)) { @@ -8898,7 +9022,82 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, } p->u.array.u.values[new_len - 1] = val; p->u.array.count = new_len; - return true; + return TRUE; +} + +/* Allocate a new fast array. Its 'length' property is set to zero. It + maximum size is 2^31-1 elements. For convenience, 'len' is a 64 bit + integer. WARNING: the content of the array is not initialized. */ +static JSValue js_allocate_fast_array(JSContext *ctx, int64_t len) +{ + JSValue arr; + JSObject *p; + + if (len > INT32_MAX) + return JS_ThrowRangeError(ctx, "invalid array length"); + arr = JS_NewArray(ctx); + if (JS_IsException(arr)) + return arr; + if (len > 0) { + p = JS_VALUE_GET_OBJ(arr); + if (expand_fast_array(ctx, p, len) < 0) { + JS_FreeValue(ctx, arr); + return JS_EXCEPTION; + } + p->u.array.count = len; + } + return arr; +} + +static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) +{ + JSValue obj; + JSObject *p; + int i; + + obj = JS_NewArray(ctx); + if (JS_IsException(obj)) + return JS_EXCEPTION; + if (len > 0) { + p = JS_VALUE_GET_OBJ(obj); + if (expand_fast_array(ctx, p, len) < 0) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + p->u.array.count = len; + for(i = 0; i < len; i++) + p->u.array.u.values[i] = JS_DupValue(ctx, tab[i]); + /* update the 'length' field */ + set_value(ctx, &p->prop[0].u.value, JS_NewInt32(ctx, len)); + } + return obj; +} + +static JSValue js_create_array_free(JSContext *ctx, int len, JSValue *tab) +{ + JSValue obj; + JSObject *p; + int i; + + obj = JS_NewArray(ctx); + if (JS_IsException(obj)) + goto fail; + if (len > 0) { + p = JS_VALUE_GET_OBJ(obj); + if (expand_fast_array(ctx, p, len) < 0) { + JS_FreeValue(ctx, obj); + fail: + for(i = 0; i < len; i++) + JS_FreeValue(ctx, tab[i]); + return JS_EXCEPTION; + } + p->u.array.count = len; + for(i = 0; i < len; i++) + p->u.array.u.values[i] = tab[i]; + /* update the 'length' field */ + set_value(ctx, &p->prop[0].u.value, JS_NewInt32(ctx, len)); + } + return obj; } static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) @@ -8908,50 +9107,61 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) JS_FreeValue(ctx, desc->value); } -/* return -1 in case of exception or true or false. Warning: 'val' is - freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD, - JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set, - the new property is not added and an error is raised. - 'obj' must be an object when obj != this_obj. - */ -static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop, - JSValue val, JSValueConst this_obj, int flags) +/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is + freed by the function. 'flags' is a bitmask of JS_PROP_THROW and + JS_PROP_THROW_STRICT. 'this_obj' is the receiver. If obj != + this_obj, then obj must be an object (Reflect.set case). */ +int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, + JSAtom prop, JSValue val, JSValueConst this_obj, int flags) { JSObject *p, *p1; JSShapeProperty *prs; JSProperty *pr; + uint32_t tag; JSPropertyDescriptor desc; int ret; - - switch(JS_VALUE_GET_TAG(this_obj)) { - case JS_TAG_NULL: - JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); - goto fail; - case JS_TAG_UNDEFINED: - JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop); - goto fail; - case JS_TAG_OBJECT: +#if 0 + printf("JS_SetPropertyInternal: "); print_atom(ctx, prop); printf("\n"); +#endif + tag = JS_VALUE_GET_TAG(this_obj); + if (unlikely(tag != JS_TAG_OBJECT)) { + if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { + p = NULL; + p1 = JS_VALUE_GET_OBJ(obj); + goto prototype_lookup; + } else { + switch(tag) { + case JS_TAG_NULL: + JS_FreeValue(ctx, val); + JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); + return -1; + case JS_TAG_UNDEFINED: + JS_FreeValue(ctx, val); + JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop); + return -1; + default: + /* even on a primitive type we can have setters on the prototype */ + p = NULL; + p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj)); + goto prototype_lookup; + } + } + } else { p = JS_VALUE_GET_OBJ(this_obj); p1 = JS_VALUE_GET_OBJ(obj); - if (p == p1) - break; - goto retry2; - default: - if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - obj = JS_GetPrototypePrimitive(ctx, obj); - p = NULL; - p1 = JS_VALUE_GET_OBJ(obj); - goto prototype_lookup; + if (unlikely(p != p1)) + goto retry2; } -retry: + /* fast path if obj == this_obj */ + retry: prs = find_own_property(&pr, p1, prop); if (prs) { if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { /* fast case */ set_value(ctx, &pr->u.value, val); - return true; + return TRUE; } else if (prs->flags & JS_PROP_LENGTH) { assert(p->class_id == JS_CLASS_ARRAY); assert(prop == JS_ATOM_length); @@ -8965,11 +9175,13 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop if (p->class_id == JS_CLASS_MODULE_NS) goto read_only_prop; set_value(ctx, pr->u.var_ref->pvalue, val); - return true; + return TRUE; } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry (potentially useless) */ - if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) - goto fail; + if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) { + JS_FreeValue(ctx, val); + return -1; + } goto retry; } else { goto read_only_prop; @@ -8983,31 +9195,39 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop uint32_t idx = __JS_AtomToUInt32(prop); if (idx < p1->u.array.count) { if (unlikely(p == p1)) - return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, flags); + return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags); else break; - } else if (is_typed_array(p1->class_id)) { + } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && + p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { goto typed_array_oob; } - } else if (is_typed_array(p1->class_id)) { + } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && + p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { - if (ret < 0) - goto fail; + if (ret < 0) { + JS_FreeValue(ctx, val); + return -1; + } typed_array_oob: - // per spec: evaluate value for side effects - if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || - p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { - int64_t v; - if (JS_ToBigInt64Free(ctx, &v, val)) - return -1; + if (p == p1) { + /* must convert the argument even if out of bound access */ + if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || + p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { + int64_t v; + if (JS_ToBigInt64Free(ctx, &v, val)) + return -1; + } else { + val = JS_ToNumberFree(ctx, val); + JS_FreeValue(ctx, val); + if (JS_IsException(val)) + return -1; + } } else { - val = JS_ToNumberFree(ctx, val); JS_FreeValue(ctx, val); - if (JS_IsException(val)) - return -1; } - return true; + return TRUE; } } } else { @@ -9016,7 +9236,7 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop JSValue obj1; if (em->set_property) { /* set_property can free the prototype */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->set_property(ctx, obj1, prop, val, this_obj, flags); JS_FreeValue(ctx, obj1); @@ -9025,12 +9245,14 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop } if (em->get_own_property) { /* get_own_property can free the prototype */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); - if (ret < 0) - goto fail; + if (ret < 0) { + JS_FreeValue(ctx, val); + return ret; + } if (ret) { if (desc.flags & JS_PROP_GETSET) { JSObject *setter; @@ -9084,22 +9306,17 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop } } - if (unlikely(flags & JS_PROP_NO_ADD)) { - JS_ThrowReferenceErrorNotDefined(ctx, prop); - goto fail; - } - if (unlikely(!p)) { - ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); - goto done; + JS_FreeValue(ctx, val); + return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); } if (unlikely(!p->extensible)) { - ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); - goto done; + JS_FreeValue(ctx, val); + return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); } - if (p == JS_VALUE_GET_OBJ(obj)) { + if (likely(p == JS_VALUE_GET_OBJ(obj))) { if (p->is_exotic) { if (p->class_id == JS_CLASS_ARRAY && p->fast_array && __JS_AtomIsTaggedInt(prop)) { @@ -9107,69 +9324,61 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop if (idx == p->u.array.count) { /* fast case */ return add_fast_array_element(ctx, p, val, flags); + } else { + goto generic_create_prop; } + } else { + goto generic_create_prop; } - goto generic_create_prop; } else { pr = add_property(ctx, p, prop, JS_PROP_C_W_E); - if (!pr) - goto fail; + if (unlikely(!pr)) { + JS_FreeValue(ctx, val); + return -1; + } pr->u.value = val; - return true; + return TRUE; } - } - - // TODO(bnoordhuis) return JSProperty slot and update in place - // when plain property (not is_exotic/setter/etc.) to avoid - // calling find_own_property() thrice? - ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); - if (ret < 0) - goto fail; - - if (ret) { - JS_FreeValue(ctx, desc.value); - if (desc.flags & JS_PROP_GETSET) { - JS_FreeValue(ctx, desc.getter); - JS_FreeValue(ctx, desc.setter); - ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden"); - goto done; - } else if (!(desc.flags & JS_PROP_WRITABLE) || - p->class_id == JS_CLASS_MODULE_NS) { - read_only_prop: - ret = JS_ThrowTypeErrorReadOnly(ctx, flags, prop); - goto done; - } - ret = JS_DefineProperty(ctx, this_obj, prop, val, - JS_UNDEFINED, JS_UNDEFINED, - JS_PROP_HAS_VALUE); } else { - generic_create_prop: - ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED, - flags | - JS_PROP_HAS_VALUE | - JS_PROP_HAS_ENUMERABLE | - JS_PROP_HAS_WRITABLE | - JS_PROP_HAS_CONFIGURABLE | - JS_PROP_C_W_E); + /* generic case: modify the property in this_obj if it already exists */ + ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); + if (ret < 0) { + JS_FreeValue(ctx, val); + return ret; + } + if (ret) { + if (desc.flags & JS_PROP_GETSET) { + JS_FreeValue(ctx, desc.getter); + JS_FreeValue(ctx, desc.setter); + JS_FreeValue(ctx, val); + return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden"); + } else { + JS_FreeValue(ctx, desc.value); + if (!(desc.flags & JS_PROP_WRITABLE) || + p->class_id == JS_CLASS_MODULE_NS) { + read_only_prop: + JS_FreeValue(ctx, val); + return JS_ThrowTypeErrorReadOnly(ctx, flags, prop); + } + } + ret = JS_DefineProperty(ctx, this_obj, prop, val, + JS_UNDEFINED, JS_UNDEFINED, + JS_PROP_HAS_VALUE); + JS_FreeValue(ctx, val); + return ret; + } else { + generic_create_prop: + ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED, + flags | + JS_PROP_HAS_VALUE | + JS_PROP_HAS_ENUMERABLE | + JS_PROP_HAS_WRITABLE | + JS_PROP_HAS_CONFIGURABLE | + JS_PROP_C_W_E); + JS_FreeValue(ctx, val); + return ret; + } } - -done: - JS_FreeValue(ctx, val); - return ret; -fail: - JS_FreeValue(ctx, val); - return -1; -} - -static int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, - JSValue val, int flags) -{ - return JS_SetPropertyInternal2(ctx, obj, prop, val, obj, flags); -} - -int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val) -{ - return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW); } /* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */ @@ -9189,27 +9398,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, switch(p->class_id) { case JS_CLASS_ARRAY: if (unlikely(idx >= (uint32_t)p->u.array.count)) { - JSObject *p1; - JSShape *sh1; - /* fast path to add an element to the array */ - if (idx != (uint32_t)p->u.array.count || - !p->fast_array || !p->extensible) + if (unlikely(idx != (uint32_t)p->u.array.count || + !p->fast_array || + !p->extensible || + p->shape->proto != JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) || + !ctx->std_array_prototype)) { goto slow_path; - /* check if prototype chain has a numeric property */ - p1 = p->shape->proto; - while (p1 != NULL) { - sh1 = p1->shape; - if (p1->class_id == JS_CLASS_ARRAY) { - if (unlikely(!p1->fast_array)) - goto slow_path; - } else if (p1->class_id == JS_CLASS_OBJECT) { - if (unlikely(sh1->has_small_array_index)) - goto slow_path; - } else { - goto slow_path; - } - p1 = sh1->proto; } /* add element */ return add_fast_array_element(ctx, p, val, flags); @@ -9223,7 +9418,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, break; case JS_CLASS_UINT8C_ARRAY: if (JS_ToUint8ClampFree(ctx, &v, val)) - goto ta_cvt_fail; + return -1; /* Note: the conversion can detach the typed array, so the array bound check must be done after */ if (unlikely(idx >= (uint32_t)p->u.array.count)) @@ -9233,7 +9428,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint8_ptr[idx] = v; @@ -9241,7 +9436,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_INT16_ARRAY: case JS_CLASS_UINT16_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint16_ptr[idx] = v; @@ -9249,7 +9444,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_INT32_ARRAY: case JS_CLASS_UINT32_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint32_ptr[idx] = v; @@ -9260,7 +9455,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, { int64_t v; if (JS_ToBigInt64Free(ctx, &v, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint64_ptr[idx] = v; @@ -9268,40 +9463,31 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, break; case JS_CLASS_FLOAT16_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.fp16_ptr[idx] = tofp16(d); break; case JS_CLASS_FLOAT32_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) - goto ta_cvt_fail; + return -1; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.float_ptr[idx] = d; break; case JS_CLASS_FLOAT64_ARRAY: - if (JS_ToFloat64Free(ctx, &d, val)) { - ta_cvt_fail: - if (flags & JS_PROP_REFLECT_DEFINE_PROPERTY) { - JS_FreeValue(ctx, JS_GetException(ctx)); - return false; - } + if (JS_ToFloat64Free(ctx, &d, val)) return -1; - } if (unlikely(idx >= (uint32_t)p->u.array.count)) { ta_out_of_bound: - if (typed_array_is_oob(p)) - if (flags & JS_PROP_DEFINE_PROPERTY) - return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index"); - return true; // per spec: no OOB exception + return TRUE; } p->u.array.u.double_ptr[idx] = d; break; default: goto slow_path; } - return true; + return TRUE; } else { JSAtom atom; int ret; @@ -9312,7 +9498,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags); JS_FreeAtom(ctx, atom); return ret; } @@ -9321,7 +9507,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val) { - return JS_SetPropertyValue(ctx, this_obj, js_uint32(idx), val, + return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val, JS_PROP_THROW); } @@ -9333,7 +9519,7 @@ int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, if ((uint64_t)idx <= INT32_MAX) { /* fast path for fast arrays */ - return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, + return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, JS_PROP_THROW); } prop = JS_NewAtomInt64(ctx, idx); @@ -9346,7 +9532,6 @@ int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, return res; } -/* `prop` may be pure ASCII or UTF-8 encoded */ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val) { @@ -9357,7 +9542,7 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW); JS_FreeAtom(ctx, atom); return ret; } @@ -9398,7 +9583,7 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, if (prop_flags != JS_PROP_C_W_E) goto convert_to_array; return add_fast_array_element(ctx, p, - js_dup(val), flags); + JS_DupValue(ctx, val), flags); } else { goto convert_to_array; } @@ -9423,10 +9608,11 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, /* XXX: should update the length after defining the property */ len = idx + 1; - set_value(ctx, &plen->u.value, js_uint32(len)); + set_value(ctx, &plen->u.value, JS_NewUint32(ctx, len)); } } - } else if (is_typed_array(p->class_id)) { + } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) @@ -9467,53 +9653,51 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, pr->u.getset.getter = NULL; if ((flags & JS_PROP_HAS_GET) && JS_IsFunction(ctx, getter)) { pr->u.getset.getter = - JS_VALUE_GET_OBJ(js_dup(getter)); + JS_VALUE_GET_OBJ(JS_DupValue(ctx, getter)); } pr->u.getset.setter = NULL; if ((flags & JS_PROP_HAS_SET) && JS_IsFunction(ctx, setter)) { pr->u.getset.setter = - JS_VALUE_GET_OBJ(js_dup(setter)); + JS_VALUE_GET_OBJ(JS_DupValue(ctx, setter)); } } else { if (flags & JS_PROP_HAS_VALUE) { - pr->u.value = js_dup(val); + pr->u.value = JS_DupValue(ctx, val); } else { pr->u.value = JS_UNDEFINED; } } - return true; + return TRUE; } -/* return false if not OK */ -static bool check_define_prop_flags(int prop_flags, int flags) +/* return FALSE if not OK */ +static BOOL check_define_prop_flags(int prop_flags, int flags) { - bool has_accessor, is_getset; + BOOL has_accessor, is_getset; if (!(prop_flags & JS_PROP_CONFIGURABLE)) { if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) == (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) { - return false; + return FALSE; } if ((flags & JS_PROP_HAS_ENUMERABLE) && (flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE)) - return false; - } - if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | - JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { - if (!(prop_flags & JS_PROP_CONFIGURABLE)) { + return FALSE; + if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | + JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { has_accessor = ((flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) != 0); is_getset = ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET); if (has_accessor != is_getset) - return false; - if (!has_accessor && !is_getset && !(prop_flags & JS_PROP_WRITABLE)) { + return FALSE; + if (!is_getset && !(prop_flags & JS_PROP_WRITABLE)) { /* not writable: cannot set the writable bit */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) - return false; + return FALSE; } } } - return true; + return TRUE; } /* ensure that the shape can be safely modified */ @@ -9538,7 +9722,7 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, *pprs = get_shape_prop(sh) + idx; } else { js_shape_hash_unlink(ctx->rt, sh); - sh->is_hashed = false; + sh->is_hashed = FALSE; } } return 0; @@ -9560,10 +9744,10 @@ static int js_update_property_flags(JSContext *ctx, JSObject *p, JS_PROP_HAS_GET, JS_PROP_HAS_SET, JS_PROP_HAS_VALUE, JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE, JS_PROP_THROW, JS_PROP_NO_EXOTIC. - If JS_PROP_THROW is set, return an exception instead of false. + If JS_PROP_THROW is set, return an exception instead of FALSE. if JS_PROP_NO_EXOTIC is set, do not call the exotic define_own_property callback. - return -1 (exception), false or true. + return -1 (exception), FALSE or TRUE. */ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValueConst val, @@ -9587,11 +9771,11 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) { uint32_t array_length; if (JS_ToArrayLengthFree(ctx, &array_length, - js_dup(val), false)) { + JS_DupValue(ctx, val), FALSE)) { return -1; } /* this code relies on the fact that Uint32 are never allocated */ - val = js_uint32(array_length); + val = JS_VALUE_MAKE_CONST(JS_NewUint32(ctx, array_length)); /* prs may have been modified */ prs = find_own_property(&pr, p, prop); assert(prs != NULL); @@ -9655,14 +9839,14 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, if (pr->u.getset.getter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (new_getter) - js_dup(getter); + JS_DupValue(ctx, getter); pr->u.getset.getter = new_getter; } if (flags & JS_PROP_HAS_SET) { if (pr->u.getset.setter) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); if (new_setter) - js_dup(setter); + JS_DupValue(ctx, setter); pr->u.getset.setter = new_setter; } } else { @@ -9684,7 +9868,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, if (!js_same_value(ctx, val, pr->u.value)) { goto not_configurable; } else { - return true; + return TRUE; } } } @@ -9696,17 +9880,22 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, spaces. */ if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue)) goto not_configurable; + } else { + /* update the reference */ + set_value(ctx, pr->u.var_ref->pvalue, + JS_DupValue(ctx, val)); } - /* update the reference */ - set_value(ctx, pr->u.var_ref->pvalue, js_dup(val)); } /* if writable is set to false, no longer a reference (for mapped arguments) */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { JSValue val1; + if (p->class_id == JS_CLASS_MODULE_NS) { + return JS_ThrowTypeErrorOrFalse(ctx, flags, "module namespace properties have writable = false"); + } if (js_shape_prepare_update(ctx, p, &prs)) return -1; - val1 = js_dup(*pr->u.var_ref->pvalue); + val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue); free_var_ref(ctx->rt, pr->u.var_ref); pr->u.value = val1; prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE); @@ -9715,9 +9904,10 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, if (flags & JS_PROP_HAS_VALUE) { /* Note: no JS code is executable because 'val' is guaranted to be a Uint32 */ - res = set_array_length(ctx, p, js_dup(val), flags); + res = set_array_length(ctx, p, JS_DupValue(ctx, val), + flags); } else { - res = true; + res = TRUE; } /* still need to reset the writable flag if needed. The JS_PROP_LENGTH is kept because the @@ -9734,7 +9924,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, } else { if (flags & JS_PROP_HAS_VALUE) { JS_FreeValue(ctx, pr->u.value); - pr->u.value = js_dup(val); + pr->u.value = JS_DupValue(ctx, val); } if (flags & JS_PROP_HAS_WRITABLE) { if (js_update_property_flags(ctx, p, &prs, @@ -9753,7 +9943,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, if (js_update_property_flags(ctx, p, &prs, (prs->flags & ~mask) | (flags & mask))) return -1; - return true; + return TRUE; } /* handle modification of fast array elements */ @@ -9775,12 +9965,13 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, goto redo_prop_update; } if (flags & JS_PROP_HAS_VALUE) { - set_value(ctx, &p->u.array.u.values[idx], js_dup(val)); + set_value(ctx, &p->u.array.u.values[idx], JS_DupValue(ctx, val)); } - return true; + return TRUE; } } - } else if (is_typed_array(p->class_id)) { + } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { JSValue num; int ret; @@ -9820,9 +10011,9 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags"); } if (flags & JS_PROP_HAS_VALUE) { - return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), js_dup(val), flags); + return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags); } - return true; + return TRUE; typed_array_done: ; } } @@ -9838,14 +10029,14 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, JSProperty *pr; if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(this_obj); if (find_own_property(&pr, p, prop)) { /* property already exists */ abort(); - return false; + return FALSE; } /* Specialized CreateProperty */ @@ -9857,7 +10048,7 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, assert(id <= 3); pr->u.init.realm_and_id |= id; pr->u.init.opaque = opaque; - return true; + return TRUE; } /* shortcut to add or redefine a new property value */ @@ -9890,18 +10081,17 @@ int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, js_uint32(idx), + return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx), val, flags); } int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx), + return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), val, flags); } -/* `prop` may be pure ASCII or UTF-8 encoded */ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val, int flags) { @@ -9934,33 +10124,33 @@ int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx), + return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), val, flags | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); } -/* return true if 'obj' has a non empty 'name' string */ -static bool js_object_has_name(JSContext *ctx, JSValue obj) +/* return TRUE if 'obj' has a non empty 'name' string */ +static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) { JSProperty *pr; JSShapeProperty *prs; - JSValue val; + JSValueConst val; JSString *p; prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name); if (!prs) - return false; + return FALSE; if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) - return true; + return TRUE; val = pr->u.value; if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) - return true; + return TRUE; p = JS_VALUE_GET_STRING(val); return (p->len != 0); } -static int JS_DefineObjectName(JSContext *ctx, JSValue obj, +static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, JSAtom name, int flags) { if (name != JS_ATOM_NULL @@ -9972,8 +10162,8 @@ static int JS_DefineObjectName(JSContext *ctx, JSValue obj, return 0; } -static int JS_DefineObjectNameComputed(JSContext *ctx, JSValue obj, - JSValue str, int flags) +static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, + JSValueConst str, int flags) { if (JS_IsObject(obj) && !js_object_has_name(ctx, obj)) { @@ -10078,7 +10268,7 @@ static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags) /* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */ /* XXX: could support exotic global object. */ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop, - JSValue func, int def_flags) + JSValueConst func, int def_flags) { JSObject *p; @@ -10098,8 +10288,8 @@ static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop, return 0; } -static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop, - bool throw_ref_error) +static inline JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop, + BOOL throw_ref_error) { JSObject *p; JSShapeProperty *prs; @@ -10112,7 +10302,15 @@ static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop, /* XXX: should handle JS_PROP_TMASK properties */ if (unlikely(JS_IsUninitialized(pr->u.value))) return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); - return js_dup(pr->u.value); + return JS_DupValue(ctx, pr->u.value); + } + + /* fast path */ + p = JS_VALUE_GET_OBJ(ctx->global_obj); + prs = find_own_property(&pr, p, prop); + if (prs) { + if (likely((prs->flags & JS_PROP_TMASK) == 0)) + return JS_DupValue(ctx, pr->u.value); } return JS_GetPropertyInternal(ctx, ctx->global_obj, prop, ctx->global_obj, throw_ref_error); @@ -10139,14 +10337,14 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp) if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) { return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop); } - sp[0] = js_dup(ctx->global_var_obj); + sp[0] = JS_DupValue(ctx, ctx->global_var_obj); } else { int ret; ret = JS_HasProperty(ctx, ctx->global_obj, prop); if (ret < 0) return -1; if (ret) { - sp[0] = js_dup(ctx->global_obj); + sp[0] = JS_DupValue(ctx, ctx->global_obj); } else { sp[0] = JS_UNDEFINED; } @@ -10155,37 +10353,16 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp) return 0; } -/* use for strict variable access: test if the variable exists */ -static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop) -{ - JSObject *p; - JSShapeProperty *prs; - int ret; - - /* no exotic behavior is possible in global_var_obj */ - p = JS_VALUE_GET_OBJ(ctx->global_var_obj); - prs = find_own_property1(p, prop); - if (prs) { - ret = true; - } else { - ret = JS_HasProperty(ctx, ctx->global_obj, prop); - if (ret < 0) - return -1; - } - return ret; -} - /* flag = 0: normal variable write flag = 1: initialize lexical variable - flag = 2: normal variable write, strict check was done before */ -static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, - int flag) +static inline int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, + int flag) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; - int flags; + int ret; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); @@ -10206,13 +10383,33 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, set_value(ctx, &pr->u.value, val); return 0; } - flags = JS_PROP_THROW_STRICT; - if (is_strict_mode(ctx)) - flags |= JS_PROP_NO_ADD; - return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags); + + p = JS_VALUE_GET_OBJ(ctx->global_obj); + prs = find_own_property(&pr, p, prop); + if (prs) { + if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | + JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { + /* fast path */ + set_value(ctx, &pr->u.value, val); + return 0; + } + } + /* slow path */ + ret = JS_HasProperty(ctx, ctx->global_obj, prop); + if (ret < 0) { + JS_FreeValue(ctx, val); + return -1; + } + if (ret == 0 && is_strict_mode(ctx)) { + JS_FreeValue(ctx, val); + JS_ThrowReferenceErrorNotDefined(ctx, prop); + return -1; + } + return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, + JS_PROP_THROW_STRICT); } -/* return -1, false or true */ +/* return -1, FALSE or TRUE */ static int JS_DeleteGlobalVar(JSContext *ctx, JSAtom prop) { JSObject *p; @@ -10224,18 +10421,18 @@ static int JS_DeleteGlobalVar(JSContext *ctx, JSAtom prop) p = JS_VALUE_GET_OBJ(ctx->global_var_obj); prs = find_own_property(&pr, p, prop); if (prs) - return false; /* lexical variables cannot be deleted */ + return FALSE; /* lexical variables cannot be deleted */ ret = JS_HasProperty(ctx, ctx->global_obj, prop); if (ret < 0) return -1; if (ret) { return JS_DeleteProperty(ctx, ctx->global_obj, prop, 0); } else { - return true; + return TRUE; } } -/* return -1, false or true. return false if not configurable or +/* return -1, FALSE or TRUE. return FALSE if not configurable or invalid object. return -1 in case of exception. flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) @@ -10250,14 +10447,14 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) p = JS_VALUE_GET_OBJ(obj1); res = delete_property(ctx, p, prop); JS_FreeValue(ctx, obj1); - if (res != false) + if (res != FALSE) return res; if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { JS_ThrowTypeError(ctx, "could not delete property"); return -1; } - return false; + return FALSE; } int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags) @@ -10277,15 +10474,15 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl return res; } -bool JS_IsFunction(JSContext *ctx, JSValueConst val) +BOOL JS_IsFunction(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(val); switch(p->class_id) { case JS_CLASS_BYTECODE_FUNCTION: - return true; + return TRUE; case JS_CLASS_PROXY: return p->u.proxy_data->is_func; default: @@ -10293,136 +10490,59 @@ bool JS_IsFunction(JSContext *ctx, JSValueConst val) } } -static bool JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, - int magic) +BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(val); if (p->class_id == JS_CLASS_C_FUNCTION) return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic); else - return false; + return FALSE; } -bool JS_IsConstructor(JSContext *ctx, JSValueConst val) +BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(val); return p->is_constructor; } -bool JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, bool val) +BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val) { JSObject *p; if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(func_obj); p->is_constructor = val; - return true; -} - -bool JS_IsRegExp(JSValueConst val) -{ - return JS_CLASS_REGEXP == JS_GetClassID(val); -} - -bool JS_IsMap(JSValueConst val) -{ - return JS_CLASS_MAP == JS_GetClassID(val); -} - -bool JS_IsSet(JSValueConst val) -{ - return JS_CLASS_SET == JS_GetClassID(val); -} - -bool JS_IsWeakRef(JSValueConst val) -{ - return JS_CLASS_WEAK_REF == JS_GetClassID(val); -} - -bool JS_IsWeakSet(JSValueConst val) -{ - return JS_CLASS_WEAKSET == JS_GetClassID(val); -} - -bool JS_IsWeakMap(JSValueConst val) -{ - return JS_CLASS_WEAKMAP == JS_GetClassID(val); -} - -bool JS_IsDataView(JSValueConst val) -{ - return JS_CLASS_DATAVIEW == JS_GetClassID(val); -} - -bool JS_IsError(JSContext *ctx, JSValueConst val) -{ - return JS_CLASS_ERROR == JS_GetClassID(val); -} - -/* used to avoid catching interrupt exceptions */ -bool JS_IsUncatchableError(JSContext *ctx, JSValueConst val) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; - p = JS_VALUE_GET_OBJ(val); - return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error; + return TRUE; } -static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, bool flag) +BOOL JS_IsError(JSContext *ctx, JSValueConst val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return; + return FALSE; p = JS_VALUE_GET_OBJ(val); - if (p->class_id == JS_CLASS_ERROR) - p->is_uncatchable_error = flag; -} - -void JS_SetUncatchableError(JSContext *ctx, JSValueConst val) -{ - js_set_uncatchable_error(ctx, val, true); + return (p->class_id == JS_CLASS_ERROR); } -void JS_ClearUncatchableError(JSContext *ctx, JSValueConst val) +/* must be called after JS_Throw() */ +void JS_SetUncatchableException(JSContext *ctx, BOOL flag) { - js_set_uncatchable_error(ctx, val, false); + ctx->rt->current_exception_is_uncatchable = flag; } -void JS_ResetUncatchableError(JSContext *ctx) +void JS_SetOpaque(JSValue obj, void *opaque) { - js_set_uncatchable_error(ctx, ctx->rt->current_exception, false); -} - -int JS_SetOpaque(JSValueConst obj, void *opaque) -{ - JSObject *p; + JSObject *p; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(obj); - // User code can't set the opaque of internal objects. - if (p->class_id >= JS_CLASS_INIT_COUNT) { - p->u.opaque = opaque; - return 0; - } + p->u.opaque = opaque; } - - return -1; -} - -/* |obj| must be a JSObject of an internal class. */ -static void JS_SetOpaqueInternal(JSValueConst obj, void *opaque) -{ - JSObject *p; - assert(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT); - p = JS_VALUE_GET_OBJ(obj); - assert(p->class_id < JS_CLASS_INIT_COUNT); - p->u.opaque = opaque; } /* return NULL if not an object of class class_id */ @@ -10461,7 +10581,7 @@ void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id) static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) { int i; - bool force_ordinary; + BOOL force_ordinary; JSAtom method_name; JSValue method, ret; @@ -10491,7 +10611,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) break; } arg = JS_AtomToString(ctx, atom); - ret = JS_CallFree(ctx, method, val, 1, vc(&arg)); + ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg); JS_FreeValue(ctx, arg); if (JS_IsException(ret)) goto exception; @@ -10534,7 +10654,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint) { - return JS_ToPrimitiveFree(ctx, js_dup(val), hint); + return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint); } void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj) @@ -10543,14 +10663,14 @@ void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj) if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return; p = JS_VALUE_GET_OBJ(obj); - p->is_HTMLDDA = true; + p->is_HTMLDDA = TRUE; } -static inline bool JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) +static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - return false; + return FALSE; p = JS_VALUE_GET_OBJ(obj); return p->is_HTMLDDA; } @@ -10569,7 +10689,13 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) return -1; case JS_TAG_STRING: { - bool ret = JS_VALUE_GET_STRING(val)->len != 0; + BOOL ret = JS_VALUE_GET_STRING(val)->len != 0; + JS_FreeValue(ctx, val); + return ret; + } + case JS_TAG_STRING_ROPE: + { + BOOL ret = JS_VALUE_GET_STRING_ROPE(val)->len != 0; JS_FreeValue(ctx, val); return ret; } @@ -10578,16 +10704,16 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) case JS_TAG_BIG_INT: { JSBigInt *p = JS_VALUE_GET_PTR(val); - bool ret; + BOOL ret; int i; - + /* fail safe: we assume it is not necessarily - normalized. Beginning from the MSB ensures that the - test is fast. */ - ret = false; + normalized. Beginning from the MSB ensures that the + test is fast. */ + ret = FALSE; for(i = p->len - 1; i >= 0; i--) { if (p->tab[i] != 0) { - ret = true; + ret = TRUE; break; } } @@ -10597,7 +10723,8 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) case JS_TAG_OBJECT: { JSObject *p = JS_VALUE_GET_OBJ(val); - bool ret = !p->is_HTMLDDA; + BOOL ret; + ret = !p->is_HTMLDDA; JS_FreeValue(ctx, val); return ret; } @@ -10608,17 +10735,16 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) return !isnan(d) && d != 0; } else { JS_FreeValue(ctx, val); - return true; + return TRUE; } } } int JS_ToBool(JSContext *ctx, JSValueConst val) { - return JS_ToBoolFree(ctx, js_dup(val)); + return JS_ToBoolFree(ctx, JS_DupValue(ctx, val)); } -/* pc points to pure ASCII or UTF-8, null terminated contents */ static int skip_spaces(const char *pc) { const uint8_t *p, *p_next, *p_start; @@ -10626,22 +10752,22 @@ static int skip_spaces(const char *pc) p = p_start = (const uint8_t *)pc; for (;;) { - c = *p++; - if (c < 0x80) { + c = *p; + if (c < 128) { if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20))) break; + p++; } else { - c = utf8_decode(p - 1, &p_next); - /* no need to test for invalid UTF-8, 0xFFFD is not a space */ + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next); if (!lre_is_space(c)) break; p = p_next; } } - return p - 1 - p_start; + return p - p_start; } -static inline int js_to_digit(int c) +static inline int to_digit(int c) { if (c >= '0' && c <= '9') return c - '0'; @@ -10655,6 +10781,19 @@ static inline int js_to_digit(int c) /* bigint support */ +#define JS_BIGINT_MAX_SIZE ((1024 * 1024) / JS_LIMB_BITS) /* in limbs */ + +/* it is currently assumed that JS_SHORT_BIG_INT_BITS = JS_LIMB_BITS */ +#if JS_SHORT_BIG_INT_BITS == 32 +#define JS_SHORT_BIG_INT_MIN INT32_MIN +#define JS_SHORT_BIG_INT_MAX INT32_MAX +#elif JS_SHORT_BIG_INT_BITS == 64 +#define JS_SHORT_BIG_INT_MIN INT64_MIN +#define JS_SHORT_BIG_INT_MAX INT64_MAX +#else +#error unsupported +#endif + #define ADDC(res, carry_out, op1, op2, carry_in) \ do { \ js_limb_t __v, __a, __k, __k1; \ @@ -10667,15 +10806,29 @@ do { \ res = __a; \ } while (0) +#if JS_LIMB_BITS == 32 /* a != 0 */ static inline js_limb_t js_limb_clz(js_limb_t a) { - if (!a) - return JS_LIMB_BITS; return clz32(a); } +#else +static inline js_limb_t js_limb_clz(js_limb_t a) +{ + return clz64(a); +} +#endif -static js_limb_t js_mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, +/* handle a = 0 too */ +static inline js_limb_t js_limb_safe_clz(js_limb_t a) +{ + if (a == 0) + return JS_LIMB_BITS; + else + return js_limb_clz(a); +} + +static js_limb_t mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, js_limb_t n, js_limb_t carry) { int i; @@ -10685,7 +10838,7 @@ static js_limb_t js_mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t return carry; } -static js_limb_t js_mp_sub(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, +static js_limb_t mp_sub(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2, int n, js_limb_t carry) { int i; @@ -10704,7 +10857,7 @@ static js_limb_t js_mp_sub(js_limb_t *res, const js_limb_t *op1, const js_limb_t } /* compute 0 - op2. carry = 0 or 1. */ -static js_limb_t js_mp_neg(js_limb_t *res, const js_limb_t *op2, int n) +static js_limb_t mp_neg(js_limb_t *res, const js_limb_t *op2, int n) { int i; js_limb_t v, carry; @@ -10719,7 +10872,7 @@ static js_limb_t js_mp_neg(js_limb_t *res, const js_limb_t *op2, int n) } /* tabr[] = taba[] * b + l. Return the high carry */ -static js_limb_t js_mp_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, +static js_limb_t mp_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b, js_limb_t l) { js_limb_t i; @@ -10733,7 +10886,7 @@ static js_limb_t js_mp_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, return l; } -static js_limb_t js_mp_div1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, +static js_limb_t mp_div1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b, js_limb_t r) { js_slimb_t i; @@ -10747,7 +10900,7 @@ static js_limb_t js_mp_div1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, } /* tabr[] += taba[] * b, return the high word. */ -static js_limb_t js_mp_add_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, +static js_limb_t mp_add_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b) { js_limb_t i, l; @@ -10763,23 +10916,23 @@ static js_limb_t js_mp_add_mul1(js_limb_t *tabr, const js_limb_t *taba, js_limb_ } /* size of the result : op1_size + op2_size. */ -static void js_mp_mul_basecase(js_limb_t *result, +static void mp_mul_basecase(js_limb_t *result, const js_limb_t *op1, js_limb_t op1_size, const js_limb_t *op2, js_limb_t op2_size) { int i; js_limb_t r; - - result[op1_size] = js_mp_mul1(result, op1, op1_size, op2[0], 0); + + result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0); for(i=1;i= 2^(JS_LIMB_BITS-1) */ -static inline js_limb_t js_udiv1norm_init(js_limb_t d) +static inline js_limb_t udiv1norm_init(js_limb_t d) { js_limb_t a0, a1; a1 = -d - 1; @@ -10805,8 +10958,8 @@ static inline js_limb_t js_udiv1norm_init(js_limb_t d) /* return the quotient and the remainder in '*pr'of 'a1*2^JS_LIMB_BITS+a0 / d' with 0 <= a1 < d. */ -static inline js_limb_t js_udiv1norm(js_limb_t *pr, js_limb_t a1, js_limb_t a0, - js_limb_t d, js_limb_t d_inv) +static inline js_limb_t udiv1norm(js_limb_t *pr, js_limb_t a1, js_limb_t a0, + js_limb_t d, js_limb_t d_inv) { js_limb_t n1m, n_adj, q, r, ah; js_dlimb_t a; @@ -10828,16 +10981,16 @@ static inline js_limb_t js_udiv1norm(js_limb_t *pr, js_limb_t a1, js_limb_t a0, #define UDIV1NORM_THRESHOLD 3 /* b must be >= 1 << (JS_LIMB_BITS - 1) */ -static js_limb_t js_mp_div1norm(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, +static js_limb_t mp_div1norm(js_limb_t *tabr, const js_limb_t *taba, js_limb_t n, js_limb_t b, js_limb_t r) { js_slimb_t i; if (n >= UDIV1NORM_THRESHOLD) { js_limb_t b_inv; - b_inv = js_udiv1norm_init(b); + b_inv = udiv1norm_init(b); for(i = n - 1; i >= 0; i--) { - tabr[i] = js_udiv1norm(&r, r, taba[i], b, b_inv); + tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv); } } else { js_dlimb_t a1; @@ -10854,7 +11007,7 @@ static js_limb_t js_mp_div1norm(js_limb_t *tabr, const js_limb_t *taba, js_limb_ - 1] must be >= 1 << (JS_LIMB_BITS - 1). na - nb must be >= 0. 'taba' is modified and contains the remainder (nb limbs). tabq[0..na-nb] contains the quotient with tabq[na - nb] <= 1. */ -static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, +static void mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, const js_limb_t *tabb, js_limb_t nb) { js_limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r; @@ -10862,13 +11015,13 @@ static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, b1 = tabb[nb - 1]; if (nb == 1) { - taba[0] = js_mp_div1norm(tabq, taba, na, b1, 0); + taba[0] = mp_div1norm(tabq, taba, na, b1, 0); return; } n = na - nb; if (n >= UDIV1NORM_THRESHOLD) - b1_inv = js_udiv1norm_init(b1); + b1_inv = udiv1norm_init(b1); else b1_inv = 0; @@ -10883,21 +11036,21 @@ static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, } tabq[n] = q; if (q) { - js_mp_sub(taba + n, taba + n, tabb, nb, 0); + mp_sub(taba + n, taba + n, tabb, nb, 0); } for(i = n - 1; i >= 0; i--) { if (unlikely(taba[i + nb] >= b1)) { q = -1; } else if (b1_inv) { - q = js_udiv1norm(&dummy_r, taba[i + nb], taba[i + nb - 1], b1, b1_inv); + q = udiv1norm(&dummy_r, taba[i + nb], taba[i + nb - 1], b1, b1_inv); } else { js_dlimb_t al; al = ((js_dlimb_t)taba[i + nb] << JS_LIMB_BITS) | taba[i + nb - 1]; q = al / b1; r = al % b1; } - r = js_mp_sub_mul1(taba + i, tabb, nb, q); + r = mp_sub_mul1(taba + i, tabb, nb, q); v = taba[i + nb]; a = v - r; @@ -10908,7 +11061,7 @@ static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, /* negative result */ for(;;) { q--; - c = js_mp_add(taba + i, taba + i, tabb, nb, 0); + c = mp_add(taba + i, taba + i, tabb, nb, 0); /* propagate carry and test if positive result */ if (c != 0) { if (++taba[i + nb] == 0) { @@ -10922,7 +11075,7 @@ static void js_mp_divnorm(js_limb_t *tabq, js_limb_t *taba, js_limb_t na, } /* 1 <= shift <= JS_LIMB_BITS - 1 */ -static js_limb_t js_mp_shl(js_limb_t *tabr, const js_limb_t *taba, int n, +static js_limb_t mp_shl(js_limb_t *tabr, const js_limb_t *taba, int n, int shift) { int i; @@ -10936,9 +11089,9 @@ static js_limb_t js_mp_shl(js_limb_t *tabr, const js_limb_t *taba, int n, return l; } -/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). +/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). 1 <= shift <= LIMB_BITS - 1 */ -static js_limb_t js_mp_shr(js_limb_t *tab_r, const js_limb_t *tab, int n, +static js_limb_t mp_shr(js_limb_t *tab_r, const js_limb_t *tab, int n, int shift, js_limb_t high) { int i; @@ -10979,6 +11132,9 @@ static JSBigInt *js_bigint_set_si(JSBigIntBuf *buf, js_slimb_t a) static JSBigInt *js_bigint_set_si64(JSBigIntBuf *buf, int64_t a) { +#if JS_LIMB_BITS == 64 + return js_bigint_set_si(buf, a); +#else JSBigInt *r = (JSBigInt *)buf->big_int_buf; r->header.ref_count = 0; /* fail safe */ if (a >= INT32_MIN && a <= INT32_MAX) { @@ -10990,6 +11146,7 @@ static JSBigInt *js_bigint_set_si64(JSBigIntBuf *buf, int64_t a) r->tab[1] = a >> JS_LIMB_BITS; } return r; +#endif } /* val must be a short big int */ @@ -11004,7 +11161,11 @@ static __maybe_unused void js_bigint_dump1(JSContext *ctx, const char *str, int i; printf("%s: ", str); for(i = len - 1; i >= 0; i--) { +#if JS_LIMB_BITS == 32 printf(" %08x", tab[i]); +#else + printf(" %016" PRIx64, tab[i]); +#endif } printf("\n"); } @@ -11027,6 +11188,9 @@ static JSBigInt *js_bigint_new_si(JSContext *ctx, js_slimb_t a) static JSBigInt *js_bigint_new_si64(JSContext *ctx, int64_t a) { +#if JS_LIMB_BITS == 64 + return js_bigint_new_si(ctx, a); +#else if (a >= INT32_MIN && a <= INT32_MAX) { return js_bigint_new_si(ctx, a); } else { @@ -11038,6 +11202,7 @@ static JSBigInt *js_bigint_new_si64(JSContext *ctx, int64_t a) r->tab[1] = a >> 32; return r; } +#endif } static JSBigInt *js_bigint_new_ui64(JSContext *ctx, uint64_t a) @@ -11049,9 +11214,14 @@ static JSBigInt *js_bigint_new_ui64(JSContext *ctx, uint64_t a) r = js_bigint_new(ctx, (65 + JS_LIMB_BITS - 1) / JS_LIMB_BITS); if (!r) return NULL; +#if JS_LIMB_BITS == 64 + r->tab[0] = a; + r->tab[1] = 0; +#else r->tab[0] = a; r->tab[1] = a >> 32; r->tab[2] = 0; +#endif return r; } } @@ -11117,10 +11287,17 @@ static js_slimb_t js_bigint_get_si_sat(const JSBigInt *a) if (a->len == 1) { return a->tab[0]; } else { +#if JS_LIMB_BITS == 32 if (js_bigint_sign(a)) return INT32_MIN; else return INT32_MAX; +#else + if (js_bigint_sign(a)) + return INT64_MIN; + else + return INT64_MAX; +#endif } } @@ -11157,7 +11334,7 @@ static JSBigInt *js_bigint_add(JSContext *ctx, const JSBigInt *a, JSBigInt *r; int n1, n2, i; js_limb_t carry, op1, op2, a_sign, b_sign; - + n2 = max_int(a->len, b->len); n1 = min_int(a->len, b->len); r = js_bigint_new(ctx, n2); @@ -11204,44 +11381,44 @@ static JSBigInt *js_bigint_mul(JSContext *ctx, const JSBigInt *a, const JSBigInt *b) { JSBigInt *r; - + r = js_bigint_new(ctx, a->len + b->len); if (!r) return NULL; - js_mp_mul_basecase(r->tab, a->tab, a->len, b->tab, b->len); + mp_mul_basecase(r->tab, a->tab, a->len, b->tab, b->len); /* correct the result if negative operands (no overflow is possible) */ if (js_bigint_sign(a)) - js_mp_sub(r->tab + a->len, r->tab + a->len, b->tab, b->len, 0); + mp_sub(r->tab + a->len, r->tab + a->len, b->tab, b->len, 0); if (js_bigint_sign(b)) - js_mp_sub(r->tab + b->len, r->tab + b->len, a->tab, a->len, 0); + mp_sub(r->tab + b->len, r->tab + b->len, a->tab, a->len, 0); return js_bigint_normalize(ctx, r); } /* return the division or the remainder. 'b' must be != 0. return NULL in case of exception (division by zero or memory error) */ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, - const JSBigInt *b, bool is_rem) + const JSBigInt *b, BOOL is_rem) { JSBigInt *r, *q; js_limb_t *tabb, h; int na, nb, a_sign, b_sign, shift; - + if (b->len == 1 && b->tab[0] == 0) { JS_ThrowRangeError(ctx, "BigInt division by zero"); return NULL; } - + a_sign = js_bigint_sign(a); b_sign = js_bigint_sign(b); na = a->len; nb = b->len; - r = js_bigint_new(ctx, na + 2); + r = js_bigint_new(ctx, na + 2); if (!r) return NULL; if (a_sign) { - js_mp_neg(r->tab, a->tab, na); + mp_neg(r->tab, a->tab, na); } else { memcpy(r->tab, a->tab, na * sizeof(a->tab[0])); } @@ -11255,7 +11432,7 @@ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, return NULL; } if (b_sign) { - js_mp_neg(tabb, b->tab, nb); + mp_neg(tabb, b->tab, nb); } else { memcpy(tabb, b->tab, nb * sizeof(tabb[0])); } @@ -11272,7 +11449,7 @@ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, r = js_bigint_new(ctx, a->len); if (!r) return NULL; - memcpy(r->tab, a->tab, a->len * sizeof(a->tab[0])); + memcpy(r->tab, a->tab, a->len * sizeof(a->tab[0])); return r; } else { /* q = 0 */ @@ -11283,8 +11460,8 @@ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, /* normalize 'b' */ shift = js_limb_clz(tabb[nb - 1]); if (shift != 0) { - js_mp_shl(tabb, tabb, nb, shift); - h = js_mp_shl(r->tab, r->tab, na, shift); + mp_shl(tabb, tabb, nb, shift); + h = mp_shl(r->tab, r->tab, na, shift); if (h != 0) r->tab[na++] = h; } @@ -11298,23 +11475,23 @@ static JSBigInt *js_bigint_divrem(JSContext *ctx, const JSBigInt *a, // js_bigint_dump1(ctx, "a", r->tab, na); // js_bigint_dump1(ctx, "b", tabb, nb); - js_mp_divnorm(q->tab, r->tab, na, tabb, nb); + mp_divnorm(q->tab, r->tab, na, tabb, nb); js_free(ctx, tabb); if (is_rem) { js_free(ctx, q); if (shift != 0) - js_mp_shr(r->tab, r->tab, nb, shift, 0); + mp_shr(r->tab, r->tab, nb, shift, 0); r->tab[nb++] = 0; if (a_sign) - js_mp_neg(r->tab, r->tab, nb); + mp_neg(r->tab, r->tab, nb); r = js_bigint_normalize1(ctx, r, nb); return r; } else { js_free(ctx, r); q->tab[na - nb + 1] = 0; if (a_sign ^ b_sign) { - js_mp_neg(q->tab, q->tab, q->len); + mp_neg(q->tab, q->tab, q->len); } q = js_bigint_normalize(ctx, q); return q; @@ -11378,7 +11555,7 @@ static JSBigInt *js_bigint_not(JSContext *ctx, const JSBigInt *a) { JSBigInt *r; int i; - + r = js_bigint_new(ctx, a->len); if (!r) return NULL; @@ -11410,7 +11587,7 @@ static JSBigInt *js_bigint_shl(JSContext *ctx, const JSBigInt *a, r->tab[i + d] = a->tab[i]; } } else { - l = js_mp_shl(r->tab + d, a->tab, a->len, shift); + l = mp_shl(r->tab + d, a->tab, a->len, shift); if (js_bigint_sign(a)) l |= (js_limb_t)(-1) << shift; r = js_bigint_extend(ctx, r, l); @@ -11439,7 +11616,7 @@ static JSBigInt *js_bigint_shr(JSContext *ctx, const JSBigInt *a, } /* no normalization is needed */ } else { - js_mp_shr(r->tab, a->tab + d, n1, shift, -a_sign); + mp_shr(r->tab, a->tab + d, n1, shift, -a_sign); r = js_bigint_normalize(ctx, r); } return r; @@ -11450,7 +11627,7 @@ static JSBigInt *js_bigint_pow(JSContext *ctx, const JSBigInt *a, JSBigInt *b) uint32_t e; int n_bits, i; JSBigInt *r, *r1; - + /* b must be >= 0 */ if (js_bigint_sign(b)) { JS_ThrowRangeError(ctx, "BigInt negative exponent"); @@ -11461,7 +11638,7 @@ static JSBigInt *js_bigint_pow(JSContext *ctx, const JSBigInt *a, JSBigInt *b) return js_bigint_new_si(ctx, 1); } else if (a->len == 1) { js_limb_t v; - bool is_neg; + BOOL is_neg; v = a->tab[0]; if (v <= 1) @@ -11560,12 +11737,22 @@ static uint64_t js_bigint_get_mant_exp(JSContext *ctx, } t[j] = v; } - + +#if JS_LIMB_BITS == 32 a1 = ((uint64_t)t[2] << 32) | t[1]; a0 = (uint64_t)t[0] << 32; +#else + a1 = t[1]; + a0 = t[0]; +#endif a0 |= (low_bits != 0); /* normalize */ - { + if (a1 == 0) { + /* JS_LIMB_BITS = 64 bit only */ + shift = 64; + a1 = a0; + a0 = 0; + } else { shift = clz64(a1); if (shift != 0) { a1 = (a1 << shift) | (a0 >> (64 - shift)); @@ -11628,7 +11815,7 @@ static JSBigInt *js_bigint_from_float64(JSContext *ctx, int *pres, double a1) uint64_t mant; JSBigIntBuf buf; JSBigInt *r; - + sgn = a >> 63; e = (a >> 52) & ((1 << 11) - 1); mant = a & (((uint64_t)1 << 52) - 1); @@ -11674,7 +11861,7 @@ static int js_bigint_float64_cmp(JSContext *ctx, const JSBigInt *a, { int b_sign, a_sign, e, f; uint64_t mant, b1, a_mant; - + b1 = float64_as_uint64(b); b_sign = b1 >> 63; e = (b1 >> 52) & ((1 << 11) - 1); @@ -11766,6 +11953,18 @@ static const js_limb_t js_pow_dec[JS_LIMB_DIGITS + 1] = { 10000000U, 100000000U, 1000000000U, +#if JS_LIMB_BITS == 64 + 10000000000U, + 100000000000U, + 1000000000000U, + 10000000000000U, + 100000000000000U, + 1000000000000000U, + 10000000000000000U, + 100000000000000000U, + 1000000000000000000U, + 10000000000000000000U, +#endif }; /* syntax: [-]digits in base radix. Return NULL if memory error. radix @@ -11778,7 +11977,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx, int is_neg, n_digits, n_limbs, len, log2_radix, n_bits, i; JSBigInt *r; js_limb_t v, c, h; - + is_neg = 0; if (*p == '-') { is_neg = 1; @@ -11814,7 +12013,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx, /* XXX: slow */ v = 0; for(i = 0; i < digits_per_limb; i++) { - c = js_to_digit(*p); + c = to_digit(*p); if (c >= radix) break; p++; @@ -11825,7 +12024,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx, if (len == 1 && r->tab[0] == 0) { r->tab[0] = v; } else { - h = js_mp_mul1(r->tab, r->tab, len, js_pow_dec[i], v); + h = mp_mul1(r->tab, r->tab, len, js_pow_dec[i], v); if (h != 0) { r->tab[len++] = h; } @@ -11837,12 +12036,12 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx, r->len = len; } else { unsigned int bit_pos, shift, pos; - + /* power of two base: no multiplication is needed */ r->len = n_limbs; memset(r->tab, 0, sizeof(r->tab[0]) * n_limbs); for(i = 0; i < n_digits; i++) { - c = js_to_digit(p[n_digits - 1 - i]); + c = to_digit(p[n_digits - 1 - i]); assert(c < radix); bit_pos = i * log2_radix; shift = bit_pos & (JS_LIMB_BITS - 1); @@ -11867,12 +12066,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx, } /* 2 <= base <= 36 */ -static char const digits[36] = { - '0','1','2','3','4','5','6','7','8','9', - 'a','b','c','d','e','f','g','h','i','j', - 'k','l','m','n','o','p','q','r','s','t', - 'u','v','w','x','y','z' -}; +static char const digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz"; /* special version going backwards */ /* XXX: use dtoa.c */ @@ -11897,7 +12091,7 @@ static char *js_u64toa(char *q, int64_t n, unsigned int base) } /* len >= 1. 2 <= radix <= 36 */ -static char *js_limb_to_a(char *q, js_limb_t n, unsigned int radix, int len) +static char *limb_to_a(char *q, js_limb_t n, unsigned int radix, int len) { int digit, i; @@ -11921,11 +12115,16 @@ static char *js_limb_to_a(char *q, js_limb_t n, unsigned int radix, int len) #define JS_RADIX_MAX 36 -static const uint8_t js_digits_per_limb_table[JS_RADIX_MAX - 1] = { +static const uint8_t digits_per_limb_table[JS_RADIX_MAX - 1] = { +#if JS_LIMB_BITS == 32 32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +#else +64,40,32,27,24,22,21,20,19,18,17,17,16,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,13,12,12,12,12,12,12, +#endif }; -static const js_limb_t js_radix_base_table[JS_RADIX_MAX - 1] = { +static const js_limb_t radix_base_table[JS_RADIX_MAX - 1] = { +#if JS_LIMB_BITS == 32 0x00000000, 0xcfd41b91, 0x00000000, 0x48c27395, 0x81bf1000, 0x75db9c97, 0x40000000, 0xcfd41b91, 0x3b9aca00, 0x8c8b6d2b, 0x19a10000, 0x309f1021, @@ -11935,6 +12134,17 @@ static const js_limb_t js_radix_base_table[JS_RADIX_MAX - 1] = { 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x81bf1000, +#else + 0x0000000000000000, 0xa8b8b452291fe821, 0x0000000000000000, 0x6765c793fa10079d, + 0x41c21cb8e1000000, 0x3642798750226111, 0x8000000000000000, 0xa8b8b452291fe821, + 0x8ac7230489e80000, 0x4d28cb56c33fa539, 0x1eca170c00000000, 0x780c7372621bd74d, + 0x1e39a5057d810000, 0x5b27ac993df97701, 0x0000000000000000, 0x27b95e997e21d9f1, + 0x5da0e1e53c5c8000, 0xd2ae3299c1c4aedb, 0x16bcc41e90000000, 0x2d04b7fdd9c0ef49, + 0x5658597bcaa24000, 0xa0e2073737609371, 0x0c29e98000000000, 0x14adf4b7320334b9, + 0x226ed36478bfa000, 0x383d9170b85ff80b, 0x5a3c23e39c000000, 0x8e65137388122bcd, + 0xdd41bb36d259e000, 0x0aee5720ee830681, 0x1000000000000000, 0x172588ad4f5f0981, + 0x211e44f7d02c1000, 0x2ee56725f06e5c71, 0x41c21cb8e1000000, +#endif }; static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) @@ -11948,9 +12158,9 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) JSBigInt *r, *tmp = NULL; char *buf, *q, *buf_end; int is_neg, n_bits, log2_radix, n_digits; - bool is_binary_radix; + BOOL is_binary_radix; JSValue res; - + assert(JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT); r = JS_VALUE_GET_PTR(val); if (r->len == 1 && r->tab[0] == 0) { @@ -11973,7 +12183,7 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) r = tmp; } log2_radix = 31 - clz32(radix); /* floor(log2(radix)) */ - n_bits = r->len * JS_LIMB_BITS - js_limb_clz(r->tab[r->len - 1]); + n_bits = r->len * JS_LIMB_BITS - js_limb_safe_clz(r->tab[r->len - 1]); /* n_digits is exact only if radix is a power of two. Otherwise it is >= the exact number of digits */ n_digits = (n_bits + log2_radix - 1) / log2_radix; @@ -11989,7 +12199,7 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) if (!is_binary_radix) { int len; js_limb_t radix_base, v; - radix_base = js_radix_base_table[radix - 2]; + radix_base = radix_base_table[radix - 2]; len = r->len; for(;;) { /* remove leading zero limbs */ @@ -12002,8 +12212,8 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) } break; } else { - v = js_mp_div1(r->tab, r->tab, len, radix_base, 0); - q = js_limb_to_a(q, v, radix, js_digits_per_limb_table[radix - 2]); + v = mp_div1(r->tab, r->tab, len, radix_base, 0); + q = limb_to_a(q, v, radix, digits_per_limb_table[radix - 2]); } } } else { @@ -12071,17 +12281,17 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, { const char *p, *p_start; int sep, is_neg; - bool is_float, has_legacy_octal; + BOOL is_float, has_legacy_octal; int atod_type = flags & ATOD_TYPE_MASK; char buf1[64], *buf; int i, j, len; - bool buf_allocated = false; + BOOL buf_allocated = FALSE; JSValue val; JSATODTempMem atod_mem; - + /* optional separator between digits */ sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256; - has_legacy_octal = false; + has_legacy_octal = FALSE; p = str; p_start = p; @@ -12114,7 +12324,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) { int i; - has_legacy_octal = true; + has_legacy_octal = TRUE; sep = 256; for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) continue; @@ -12126,44 +12336,46 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, goto no_prefix; } /* there must be a digit after the prefix */ - if (js_to_digit((uint8_t)*p) >= radix) + if (to_digit((uint8_t)*p) >= radix) goto fail; no_prefix: ; } else { no_radix_prefix: if (!(flags & ATOD_INT_ONLY) && (atod_type == ATOD_TYPE_FLOAT64) && - js__strstart(p, "Infinity", &p)) { + strstart(p, "Infinity", &p)) { double d = INF; if (is_neg) d = -d; - val = js_float64(d); + val = JS_NewFloat64(ctx, d); goto done; } } if (radix == 0) radix = 10; - is_float = false; + is_float = FALSE; p_start = p; - while (js_to_digit((uint8_t)*p) < radix + while (to_digit((uint8_t)*p) < radix || (*p == sep && (radix != 10 || p != p_start + 1 || p[-1] != '0') && - js_to_digit((uint8_t)p[1]) < radix)) { + to_digit((uint8_t)p[1]) < radix)) { p++; } - if (!(flags & ATOD_INT_ONLY) && radix == 10) { - if (*p == '.' && (p > p_start || js_to_digit((uint8_t)p[1]) < radix)) { - is_float = true; + if (!(flags & ATOD_INT_ONLY)) { + if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) { + is_float = TRUE; p++; if (*p == sep) goto fail; - while (js_to_digit((uint8_t)*p) < radix || - (*p == sep && js_to_digit((uint8_t)p[1]) < radix)) + while (to_digit((uint8_t)*p) < radix || + (*p == sep && to_digit((uint8_t)p[1]) < radix)) p++; } - if (p > p_start && (*p == 'e' || *p == 'E')) { + if (p > p_start && + (((*p == 'e' || *p == 'E') && radix == 10) || + ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) { const char *p1 = p + 1; - is_float = true; + is_float = TRUE; if (*p1 == '+') { p1++; } else if (*p1 == '-') { @@ -12180,13 +12392,13 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, goto fail; buf = buf1; - buf_allocated = false; + buf_allocated = FALSE; len = p - p_start; if (unlikely((len + 2) > sizeof(buf1))) { buf = js_malloc_rt(ctx->rt, len + 2); /* no exception raised */ if (!buf) goto mem_error; - buf_allocated = true; + buf_allocated = TRUE; } /* remove the separators and the radix prefixes */ j = 0; @@ -12202,6 +12414,14 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, if (*p == 'n') { p++; atod_type = ATOD_TYPE_BIG_INT; + } else { + if (is_float && radix != 10) + goto fail; + } + } else { + if (atod_type == ATOD_TYPE_FLOAT64) { + if (is_float && radix != 10) + goto fail; } } @@ -12212,7 +12432,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, d = js_atod(buf, NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY, &atod_mem); /* return int or float64 */ - val = js_number(d); + val = JS_NewFloat64(ctx, d); } break; case ATOD_TYPE_BIG_INT: @@ -12264,7 +12484,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, case JS_TAG_SHORT_BIG_INT: if (flag != TON_FLAG_NUMERIC) { JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert BigInt to number"); + return JS_ThrowTypeError(ctx, "cannot convert bigint to number"); } ret = val; break; @@ -12275,7 +12495,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, break; case JS_TAG_BOOL: case JS_TAG_NULL: - ret = js_int32(JS_VALUE_GET_INT(val)); + ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val)); break; case JS_TAG_UNDEFINED: ret = JS_NAN; @@ -12286,6 +12506,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, return JS_EXCEPTION; goto redo; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: { const char *str; const char *p; @@ -12336,7 +12557,7 @@ static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val) static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val) { - return JS_ToNumericFree(ctx, js_dup(val)); + return JS_ToNumericFree(ctx, JS_DupValue(ctx, val)); } static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, @@ -12344,7 +12565,7 @@ static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, { double d; uint32_t tag; - + val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) goto fail; @@ -12361,8 +12582,8 @@ static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, } *pres = d; return 0; -fail: - *pres = NAN; + fail: + *pres = JS_FLOAT64_NAN; return -1; } @@ -12384,12 +12605,12 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val) int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val) { - return JS_ToFloat64Free(ctx, pres, js_dup(val)); + return JS_ToFloat64Free(ctx, pres, JS_DupValue(ctx, val)); } -JSValue JS_ToNumber(JSContext *ctx, JSValueConst val) +static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val) { - return JS_ToNumberFree(ctx, js_dup(val)); + return JS_ToNumberFree(ctx, JS_DupValue(ctx, val)); } /* same as JS_ToNumber() but return 0 in case of NaN/Undefined */ @@ -12405,17 +12626,17 @@ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: - ret = js_int32(JS_VALUE_GET_INT(val)); + ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val)); break; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { - ret = js_int32(0); + ret = JS_NewInt32(ctx, 0); } else { /* convert -0 to +0 */ d = trunc(d) + 0.0; - ret = js_number(d); + ret = JS_NewFloat64(ctx, d); } } break; @@ -12473,15 +12694,15 @@ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val) return 0; } -static int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val) +int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val) { - return JS_ToInt32SatFree(ctx, pres, js_dup(val)); + return JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val)); } -static int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val, - int min, int max, int min_offset) +int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val, + int min, int max, int min_offset) { - int res = JS_ToInt32SatFree(ctx, pres, js_dup(val)); + int res = JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val)); if (res == 0) { if (*pres < min) { *pres += min_offset; @@ -12519,7 +12740,7 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val) } else { if (d < INT64_MIN) *pres = INT64_MIN; - else if (d >= 0x1p63) + else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */ *pres = INT64_MAX; else *pres = (int64_t)d; @@ -12538,13 +12759,13 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val) int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val) { - return JS_ToInt64SatFree(ctx, pres, js_dup(val)); + return JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val)); } int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val, int64_t min, int64_t max, int64_t neg_offset) { - int res = JS_ToInt64SatFree(ctx, pres, js_dup(val)); + int res = JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val)); if (res == 0) { if (*pres < 0) *pres += neg_offset; @@ -12591,8 +12812,7 @@ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val) ret = v << ((e - 1023) - 52); /* take the sign into account */ if (u.u64 >> 63) - if (ret != INT64_MIN) - ret = -ret; + ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } @@ -12612,12 +12832,12 @@ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val) int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val) { - return JS_ToInt64Free(ctx, pres, js_dup(val)); + return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val)); } int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val) { - if (JS_IsBigInt(val)) + if (JS_IsBigInt(ctx, val)) return JS_ToBigInt64(ctx, pres, val); else return JS_ToInt64(ctx, pres, val); @@ -12658,8 +12878,7 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) ret = v >> 32; /* take the sign into account */ if (u.u64 >> 63) - if (ret != INT32_MIN) - ret = -ret; + ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } @@ -12679,7 +12898,7 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val) { - return JS_ToInt32Free(ctx, pres, js_dup(val)); + return JS_ToInt32Free(ctx, pres, JS_DupValue(ctx, val)); } static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val) @@ -12730,7 +12949,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val) } static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, - JSValue val, bool is_array_ctor) + JSValue val, BOOL is_array_ctor) { uint32_t tag, len; @@ -12764,7 +12983,7 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, if (JS_IsException(val)) return -1; /* cannot recurse because val is a number */ - if (JS_ToArrayLengthFree(ctx, &len, val, true)) + if (JS_ToArrayLengthFree(ctx, &len, val, TRUE)) return -1; } else { /* legacy behavior: must do the conversion twice and compare */ @@ -12776,7 +12995,7 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, if (JS_IsException(val)) return -1; /* cannot recurse because val is a number */ - if (JS_ToArrayLengthFree(ctx, &len1, val, false)) + if (JS_ToArrayLengthFree(ctx, &len1, val, FALSE)) return -1; if (len1 != len) { fail: @@ -12793,7 +13012,7 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, #define MAX_SAFE_INTEGER (((int64_t)1 << 53) - 1) -static bool is_safe_integer(double d) +static BOOL is_safe_integer(double d) { return isfinite(d) && floor(d) == d && fabs(d) <= (double)MAX_SAFE_INTEGER; @@ -12828,13 +13047,13 @@ static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val) { double d; if (!JS_IsNumber(val)) - return false; + return FALSE; if (unlikely(JS_ToFloat64(ctx, &d, val))) return -1; return isfinite(d) && floor(d) == d; } -static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) +static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) { uint32_t tag; @@ -12860,7 +13079,7 @@ static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) return js_bigint_sign(p); } default: - return false; + return FALSE; } } @@ -12869,8 +13088,6 @@ static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val) return js_bigint_to_string1(ctx, val, 10); } -/*---- floating point number to string conversions ----*/ - static JSValue js_dtoa2(JSContext *ctx, double d, int radix, int n_digits, int flags) { @@ -12879,7 +13096,7 @@ static JSValue js_dtoa2(JSContext *ctx, JSValue res; JSDTOATempMem dtoa_mem; len_max = js_dtoa_max_len(d, radix, n_digits, flags); - + /* longer buffer may be used if radix != 10 */ if (len_max > sizeof(static_buf) - 1) { tmp_buf = js_malloc(ctx, len_max + 1); @@ -12896,20 +13113,24 @@ static JSValue js_dtoa2(JSContext *ctx, return res; } -JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, - bool is_ToPropertyKey) +static JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey) { uint32_t tag; char buf[32]; - size_t len; tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_STRING: - return js_dup(val); + return JS_DupValue(ctx, val); + case JS_TAG_STRING_ROPE: + return js_linearize_string_rope(ctx, JS_DupValue(ctx, val)); case JS_TAG_INT: - len = i32toa(buf, JS_VALUE_GET_INT(val)); - return js_new_string8_len(ctx, buf, len); + { + size_t len; + len = i32toa(buf, JS_VALUE_GET_INT(val)); + return js_new_string8_len(ctx, buf, len); + } + break; case JS_TAG_BOOL: return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ? JS_ATOM_true : JS_ATOM_false); @@ -12934,7 +13155,7 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, return js_new_string8(ctx, "[function bytecode]"); case JS_TAG_SYMBOL: if (is_ToPropertyKey) { - return js_dup(val); + return JS_DupValue(ctx, val); } else { return JS_ThrowTypeError(ctx, "cannot convert symbol to string"); } @@ -12944,8 +13165,6 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: return js_bigint_to_string(ctx, val); - case JS_TAG_UNINITIALIZED: - return js_new_string8(ctx, "[uninitialized]"); default: return js_new_string8(ctx, "[unsupported type]"); } @@ -12953,7 +13172,7 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, JSValue JS_ToString(JSContext *ctx, JSValueConst val) { - return JS_ToStringInternal(ctx, val, false); + return JS_ToStringInternal(ctx, val, FALSE); } static JSValue JS_ToStringFree(JSContext *ctx, JSValue val) @@ -12973,7 +13192,7 @@ static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val) JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val) { - return JS_ToStringInternal(ctx, val, true); + return JS_ToStringInternal(ctx, val, TRUE); } static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val) @@ -12984,27 +13203,71 @@ static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val) return JS_ToString(ctx, val); } -static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) +#define JS_PRINT_MAX_DEPTH 8 + +typedef struct { + JSRuntime *rt; + JSContext *ctx; /* may be NULL */ + JSPrintValueOptions options; + JSPrintValueWrite *write_func; + void *write_opaque; + int level; + JSObject *print_stack[JS_PRINT_MAX_DEPTH]; /* level values */ +} JSPrintValueState; + +static void js_print_value(JSPrintValueState *s, JSValueConst val); + +static void js_putc(JSPrintValueState *s, char c) { - JSValue val; - JSString *p; - int i; - uint32_t c; - StringBuffer b_s, *b = &b_s; - char buf[16]; + s->write_func(s->write_opaque, &c, 1); +} - val = JS_ToStringCheckObject(ctx, val1); - if (JS_IsException(val)) - return val; - p = JS_VALUE_GET_STRING(val); +static void js_puts(JSPrintValueState *s, const char *str) +{ + s->write_func(s->write_opaque, str, strlen(str)); +} - if (string_buffer_init(ctx, b, p->len + 2)) - goto fail; +static void __attribute__((format(printf, 2, 3))) js_printf(JSPrintValueState *s, const char *fmt, ...) +{ + va_list ap; + char buf[256]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + s->write_func(s->write_opaque, buf, strlen(buf)); +} - if (string_buffer_putc8(b, '\"')) - goto fail; - for(i = 0; i < p->len; ) { - c = string_getc(p, &i); +static void js_print_float64(JSPrintValueState *s, double d) +{ + JSDTOATempMem dtoa_mem; + char buf[32]; + int len; + len = js_dtoa(buf, d, 10, 0, JS_DTOA_FORMAT_FREE | JS_DTOA_MINUS_ZERO, &dtoa_mem); + s->write_func(s->write_opaque, buf, len); +} + +static uint32_t js_string_get_length(JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + JSString *p = JS_VALUE_GET_STRING(val); + return p->len; + } else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) { + JSStringRope *r = JS_VALUE_GET_PTR(val); + return r->len; + } else { + return 0; + } +} + +/* pretty print the first 'len' characters of 'p' */ +static void js_print_string1(JSPrintValueState *s, JSString *p, int len, int sep) +{ + uint8_t buf[UTF8_CHAR_LEN_MAX]; + int l, i, c, c1; + + for(i = 0; i < len; i++) { + c = string_get(p, i); switch(c) { case '\t': c = 't'; @@ -13021,188 +13284,528 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) case '\f': c = 'f'; goto quote; - case '\"': case '\\': quote: - if (string_buffer_putc8(b, '\\')) - goto fail; - if (string_buffer_putc8(b, c)) - goto fail; + js_putc(s, '\\'); + js_putc(s, c); break; default: - if (c < 32 || is_surrogate(c)) { - snprintf(buf, sizeof(buf), "\\u%04x", c); - if (string_buffer_write8(b, (uint8_t*)buf, 6)) - goto fail; + if (c == sep) + goto quote; + if (c >= 32 && c <= 126) { + js_putc(s, c); + } else if (c < 32 || + (c >= 0x7f && c <= 0x9f)) { + escape: + js_printf(s, "\\u%04x", c); } else { - if (string_buffer_putc(b, c)) - goto fail; + if (is_hi_surrogate(c)) { + if ((i + 1) >= len) + goto escape; + c1 = string_get(p, i + 1); + if (!is_lo_surrogate(c1)) + goto escape; + i++; + c = from_surrogate(c, c1); + } else if (is_lo_surrogate(c)) { + goto escape; + } + l = unicode_to_utf8(buf, c); + s->write_func(s->write_opaque, (char *)buf, l); } break; } } - if (string_buffer_putc8(b, '\"')) - goto fail; - JS_FreeValue(ctx, val); - return string_buffer_end(b); - fail: - JS_FreeValue(ctx, val); - string_buffer_free(b); - return JS_EXCEPTION; } -static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt) +static void js_print_string_rec(JSPrintValueState *s, JSValueConst val, + int sep, uint32_t pos) { - printf("%14s %4s %4s %14s %10s %s\n", - "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS"); + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + JSString *p = JS_VALUE_GET_STRING(val); + uint32_t len; + if (pos < s->options.max_string_length) { + len = min_uint32(p->len, s->options.max_string_length - pos); + js_print_string1(s, p, len, sep); + } + } else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) { + JSStringRope *r = JS_VALUE_GET_PTR(val); + js_print_string_rec(s, r->left, sep, pos); + js_print_string_rec(s, r->right, sep, pos + js_string_get_length(r->left)); + } else { + js_printf(s, "", (int)JS_VALUE_GET_TAG(val)); + } } -/* for debug only: dump an object without side effect */ -static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) +static void js_print_string(JSPrintValueState *s, JSValueConst val) { - uint32_t i; - char atom_buf[ATOM_GET_STR_BUF_SIZE]; - JSShape *sh; - JSShapeProperty *prs; - JSProperty *pr; - bool is_first = true; + int sep; + if (s->options.raw_dump && JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + JSString *p = JS_VALUE_GET_STRING(val); + js_printf(s, "%d", p->header.ref_count); + sep = (p->header.ref_count == 1) ? '\"' : '\''; + } else { + sep = '\"'; + } + js_putc(s, sep); + js_print_string_rec(s, val, sep, 0); + js_putc(s, sep); + if (js_string_get_length(val) > s->options.max_string_length) { + uint32_t n = js_string_get_length(val) - s->options.max_string_length; + js_printf(s, "... %u more character%s", n, n > 1 ? "s" : ""); + } +} - /* XXX: should encode atoms with special characters */ - sh = p->shape; /* the shape can be NULL while freeing an object */ - printf("%14p %4d ", - (void *)p, - p->header.ref_count); - if (sh) { - printf("%3d%c %14p ", - sh->header.ref_count, - " *"[sh->is_hashed], - (void *)sh->proto); +static void js_print_raw_string(JSPrintValueState *s, JSValueConst val) +{ + const char *cstr; + size_t len; + cstr = JS_ToCStringLen(s->ctx, &len, val); + if (cstr) { + s->write_func(s->write_opaque, cstr, len); + JS_FreeCString(s->ctx, cstr); + } +} + +static BOOL is_ascii_ident(const JSString *p) +{ + int i, c; + + if (p->len == 0) + return FALSE; + for(i = 0; i < p->len; i++) { + c = string_get(p, i); + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0))) + return FALSE; + } + return TRUE; +} + +static void js_print_atom(JSPrintValueState *s, JSAtom atom) +{ + int i; + if (__JS_AtomIsTaggedInt(atom)) { + js_printf(s, "%u", __JS_AtomToUInt32(atom)); + } else if (atom == JS_ATOM_NULL) { + js_puts(s, ""); } else { - printf("%3s %14s ", "-", "-"); + assert(atom < s->rt->atom_size); + JSString *p; + p = s->rt->atom_array[atom]; + if (is_ascii_ident(p)) { + for(i = 0; i < p->len; i++) { + js_putc(s, string_get(p, i)); + } + } else { + js_putc(s, '"'); + js_print_string1(s, p, p->len, '\"'); + js_putc(s, '"'); + } } - printf("%10s ", - JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name)); - if (p->is_exotic && p->fast_array) { - printf("[ "); - for(i = 0; i < p->u.array.count; i++) { - if (i != 0) - printf(", "); - switch (p->class_id) { - case JS_CLASS_ARRAY: - case JS_CLASS_ARGUMENTS: - JS_DumpValue(rt, p->u.array.u.values[i]); +} + +/* return 0 if invalid length */ +static uint32_t js_print_array_get_length(JSObject *p) +{ + JSProperty *pr; + JSShapeProperty *prs; + JSValueConst val; + + prs = find_own_property(&pr, p, JS_ATOM_length); + if (!prs) + return 0; + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) + return 0; + val = pr->u.value; + switch(JS_VALUE_GET_NORM_TAG(val)) { + case JS_TAG_INT: + return JS_VALUE_GET_INT(val); + case JS_TAG_FLOAT64: + return (uint32_t)JS_VALUE_GET_FLOAT64(val); + default: + return 0; + } +} + +static void js_print_comma(JSPrintValueState *s, int *pcomma_state) +{ + switch(*pcomma_state) { + case 0: + break; + case 1: + js_printf(s, ", "); + break; + case 2: + js_printf(s, " { "); + break; + } + *pcomma_state = 1; +} + +static void js_print_more_items(JSPrintValueState *s, int *pcomma_state, + uint32_t n) +{ + js_print_comma(s, pcomma_state); + js_printf(s, "... %u more item%s", n, n > 1 ? "s" : ""); +} + +/* similar to js_regexp_toString() but without side effect */ +static void js_print_regexp(JSPrintValueState *s, JSObject *p1) +{ + JSRegExp *re = &p1->u.regexp; + JSString *p; + int i, n, c, c2, bra, flags; + static const char regexp_flags[] = { 'g', 'i', 'm', 's', 'u', 'y', 'd', 'v' }; + + p = re->pattern; + js_putc(s, '/'); + if (p->len == 0) { + js_puts(s, "(?:)"); + } else { + bra = 0; + for (i = 0, n = p->len; i < n;) { + c2 = -1; + switch (c = string_get(p, i++)) { + case '\\': + if (i < n) + c2 = string_get(p, i++); + break; + case ']': + bra = 0; + break; + case '[': + if (!bra) { + if (i < n && string_get(p, i) == ']') + c2 = string_get(p, i++); + bra = 1; + } + break; + case '\n': + c = '\\'; + c2 = 'n'; + break; + case '\r': + c = '\\'; + c2 = 'r'; break; + case '/': + if (!bra) { + c = '\\'; + c2 = '/'; + } + break; + } + js_putc(s, c); + if (c2 >= 0) + js_putc(s, c2); + } + } + js_putc(s, '/'); + + flags = lre_get_flags(re->bytecode->u.str8); + for(i = 0; i < countof(regexp_flags); i++) { + if ((flags >> i) & 1) { + js_putc(s, regexp_flags[i]); + } + } +} + +/* similar to js_error_toString() but without side effect */ +static void js_print_error(JSPrintValueState *s, JSObject *p) +{ + const char *str; + size_t len; + + str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_name); + if (!str) { + js_puts(s, "Error"); + } else { + js_puts(s, str); + JS_FreeCString(s->ctx, str); + } + + str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_message); + if (str && str[0] != '\0') { + js_puts(s, ": "); + js_puts(s, str); + } + JS_FreeCString(s->ctx, str); + + /* dump the stack if present */ + str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_stack); + if (str) { + js_putc(s, '\n'); + + /* XXX: should remove the last '\n' in stack as + v8. SpiderMonkey does not do it */ + len = strlen(str); + if (len > 0 && str[len - 1] == '\n') + len--; + s->write_func(s->write_opaque, str, len); + + JS_FreeCString(s->ctx, str); + } +} + +static void js_print_object(JSPrintValueState *s, JSObject *p) +{ + JSRuntime *rt = s->rt; + JSShape *sh; + JSShapeProperty *prs; + JSProperty *pr; + int comma_state; + BOOL is_array; + uint32_t i; + + comma_state = 0; + is_array = FALSE; + if (p->class_id == JS_CLASS_ARRAY) { + is_array = TRUE; + js_printf(s, "[ "); + /* XXX: print array like properties even if not fast array */ + if (p->fast_array) { + uint32_t len, n, len1; + len = js_print_array_get_length(p); + + len1 = min_uint32(p->u.array.count, s->options.max_item_count); + for(i = 0; i < len1; i++) { + js_print_comma(s, &comma_state); + js_print_value(s, p->u.array.u.values[i]); + } + if (len1 < p->u.array.count) + js_print_more_items(s, &comma_state, p->u.array.count - len1); + if (p->u.array.count < len) { + n = len - p->u.array.count; + js_print_comma(s, &comma_state); + js_printf(s, "<%u empty item%s>", n, n > 1 ? "s" : ""); + } + } + } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && p->class_id <= JS_CLASS_FLOAT64_ARRAY) { + uint32_t size = 1 << typed_array_size_log2(p->class_id); + uint32_t len1; + int64_t v; + + js_print_atom(s, rt->class_array[p->class_id].class_name); + js_printf(s, "(%u) [ ", p->u.array.count); + + is_array = TRUE; + len1 = min_uint32(p->u.array.count, s->options.max_item_count); + for(i = 0; i < len1; i++) { + const uint8_t *ptr = p->u.array.u.uint8_ptr + i * size; + js_print_comma(s, &comma_state); + switch(p->class_id) { case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: + v = *ptr; + goto ta_int64; + case JS_CLASS_INT8_ARRAY: + v = *(int8_t *)ptr; + goto ta_int64; case JS_CLASS_INT16_ARRAY: + v = *(int16_t *)ptr; + goto ta_int64; case JS_CLASS_UINT16_ARRAY: + v = *(uint16_t *)ptr; + goto ta_int64; case JS_CLASS_INT32_ARRAY: + v = *(int32_t *)ptr; + goto ta_int64; case JS_CLASS_UINT32_ARRAY: + v = *(uint32_t *)ptr; + goto ta_int64; case JS_CLASS_BIG_INT64_ARRAY: + v = *(int64_t *)ptr; + ta_int64: + js_printf(s, "%" PRId64, v); + break; case JS_CLASS_BIG_UINT64_ARRAY: + js_printf(s, "%" PRIu64, *(uint64_t *)ptr); + break; case JS_CLASS_FLOAT16_ARRAY: + js_print_float64(s, fromfp16(*(uint16_t *)ptr)); + break; case JS_CLASS_FLOAT32_ARRAY: + js_print_float64(s, *(float *)ptr); + break; case JS_CLASS_FLOAT64_ARRAY: - { - int size = 1 << typed_array_size_log2(p->class_id); - const uint8_t *b = p->u.array.u.uint8_ptr + i * size; - while (size-- > 0) - printf("%02X", *b++); - } + js_print_float64(s, *(double *)ptr); break; } } - printf(" ] "); - } - + if (len1 < p->u.array.count) + js_print_more_items(s, &comma_state, p->u.array.count - len1); + } else if (p->class_id == JS_CLASS_BYTECODE_FUNCTION || + (rt->class_array[p->class_id].call != NULL && + p->class_id != JS_CLASS_PROXY)) { + js_printf(s, "[Function"); + /* XXX: allow dump without ctx */ + if (!s->options.raw_dump && s->ctx) { + const char *func_name_str; + js_putc(s, ' '); + func_name_str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_name); + if (!func_name_str || func_name_str[0] == '\0') + js_puts(s, "(anonymous)"); + else + js_puts(s, func_name_str); + JS_FreeCString(s->ctx, func_name_str); + } + js_printf(s, "]"); + comma_state = 2; + } else if (p->class_id == JS_CLASS_MAP || p->class_id == JS_CLASS_SET) { + JSMapState *ms = p->u.opaque; + struct list_head *el; + + if (!ms) + goto default_obj; + js_print_atom(s, rt->class_array[p->class_id].class_name); + js_printf(s, "(%u) { ", ms->record_count); + i = 0; + list_for_each(el, &ms->records) { + JSMapRecord *mr = list_entry(el, JSMapRecord, link); + js_print_comma(s, &comma_state); + if (mr->empty) + continue; + js_print_value(s, mr->key); + if (p->class_id == JS_CLASS_MAP) { + js_printf(s, " => "); + js_print_value(s, mr->value); + } + i++; + if (i >= s->options.max_item_count) + break; + } + if (i < ms->record_count) + js_print_more_items(s, &comma_state, ms->record_count - i); + } else if (p->class_id == JS_CLASS_REGEXP && s->ctx) { + js_print_regexp(s, p); + comma_state = 2; + } else if (p->class_id == JS_CLASS_DATE && s->ctx) { + /* get_date_string() has no side effect */ + JSValue str = get_date_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 0, NULL, 0x23); /* toISOString() */ + if (JS_IsException(str)) + goto default_obj; + js_print_raw_string(s, str); + JS_FreeValueRT(s->rt, str); + comma_state = 2; + } else if (p->class_id == JS_CLASS_ERROR && s->ctx) { + js_print_error(s, p); + comma_state = 2; + } else { + default_obj: + if (p->class_id != JS_CLASS_OBJECT) { + js_print_atom(s, rt->class_array[p->class_id].class_name); + js_printf(s, " "); + } + js_printf(s, "{ "); + } + + sh = p->shape; /* the shape can be NULL while freeing an object */ if (sh) { - printf("{ "); + uint32_t j; + + j = 0; for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->atom != JS_ATOM_NULL) { - pr = &p->prop[i]; - if (!is_first) - printf(", "); - printf("%s: ", - JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom)); - if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { - printf("[getset %p %p]", (void *)pr->u.getset.getter, - (void *)pr->u.getset.setter); - } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - printf("[varref %p]", (void *)pr->u.var_ref); - } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { - printf("[autoinit %p %d %p]", - (void *)js_autoinit_get_realm(pr), - js_autoinit_get_id(pr), - (void *)pr->u.init.opaque); - } else { - JS_DumpValue(rt, pr->u.value); + if (!(prs->flags & JS_PROP_ENUMERABLE) && + !s->options.show_hidden) { + continue; + } + if (j < s->options.max_item_count) { + pr = &p->prop[i]; + js_print_comma(s, &comma_state); + js_print_atom(s, prs->atom); + js_printf(s, ": "); + + /* XXX: autoinit property */ + if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { + if (s->options.raw_dump) { + js_printf(s, "[Getter %p Setter %p]", + pr->u.getset.getter, pr->u.getset.setter); + } else { + if (pr->u.getset.getter && pr->u.getset.setter) { + js_printf(s, "[Getter/Setter]"); + } else if (pr->u.getset.setter) { + js_printf(s, "[Setter]"); + } else { + js_printf(s, "[Getter]"); + } + } + } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { + if (s->options.raw_dump) { + js_printf(s, "[varref %p]", (void *)pr->u.var_ref); + } else { + js_print_value(s, *pr->u.var_ref->pvalue); + } + } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { + if (s->options.raw_dump) { + js_printf(s, "[autoinit %p %d %p]", + (void *)js_autoinit_get_realm(pr), + js_autoinit_get_id(pr), + (void *)pr->u.init.opaque); + } else { + /* XXX: could autoinit but need to restart + the iteration */ + js_printf(s, "[autoinit]"); + } + } else { + js_print_value(s, pr->u.value); + } } - is_first = false; + j++; } } - printf(" }"); + if (j > s->options.max_item_count) + js_print_more_items(s, &comma_state, j - s->options.max_item_count); } - - if (js_class_has_bytecode(p->class_id)) { + if (s->options.raw_dump && js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; - JSVarRef **var_refs; if (b->closure_var_count) { + JSVarRef **var_refs; var_refs = p->u.func.var_refs; - printf(" Closure:"); + + js_print_comma(s, &comma_state); + js_printf(s, "[[Closure]]: ["); for(i = 0; i < b->closure_var_count; i++) { - printf(" "); - JS_DumpValue(rt, var_refs[i]->value); - } - if (p->u.func.home_object) { - printf(" HomeObject: "); - JS_DumpValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object)); + if (i != 0) + js_printf(s, ", "); + js_print_value(s, var_refs[i]->value); } + js_printf(s, " ]"); + } + if (p->u.func.home_object) { + js_print_comma(s, &comma_state); + js_printf(s, "[[HomeObject]]: "); + js_print_value(s, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object)); } } - printf("\n"); -} -static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) -{ - if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { - JS_DumpObject(rt, (JSObject *)p); - } else { - printf("%14p %4d ", - (void *)p, - p->ref_count); - switch(p->gc_obj_type) { - case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: - printf("[function bytecode]"); - break; - case JS_GC_OBJ_TYPE_SHAPE: - printf("[shape]"); - break; - case JS_GC_OBJ_TYPE_VAR_REF: - printf("[var_ref]"); - break; - case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: - printf("[async_function]"); - break; - case JS_GC_OBJ_TYPE_JS_CONTEXT: - printf("[js_context]"); - break; - default: - printf("[unknown %d]", p->gc_obj_type); - break; + if (!is_array) { + if (comma_state != 2) { + js_printf(s, " }"); } - printf("\n"); + } else { + js_printf(s, " ]"); } } -static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val) +static int js_print_stack_index(JSPrintValueState *s, JSObject *p) +{ + int i; + for(i = 0; i < s->level; i++) + if (s->print_stack[i] == p) + return i; + return -1; +} + +static void js_print_value(JSPrintValueState *s, JSValueConst val) { uint32_t tag = JS_VALUE_GET_NORM_TAG(val); const char *str; switch(tag) { case JS_TAG_INT: - printf("%d", JS_VALUE_GET_INT(val)); + js_printf(s, "%d", JS_VALUE_GET_INT(val)); break; case JS_TAG_BOOL: if (JS_VALUE_GET_BOOL(val)) @@ -13222,106 +13825,267 @@ static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val) case JS_TAG_UNDEFINED: str = "undefined"; print_str: - printf("%s", str); + js_puts(s, str); break; case JS_TAG_FLOAT64: - printf("%.14g", JS_VALUE_GET_FLOAT64(val)); + js_print_float64(s, JS_VALUE_GET_FLOAT64(val)); break; case JS_TAG_SHORT_BIG_INT: - printf("%" PRId64 "n", (int64_t)JS_VALUE_GET_SHORT_BIG_INT(val)); + js_printf(s, "%" PRId64 "n", (int64_t)JS_VALUE_GET_SHORT_BIG_INT(val)); break; case JS_TAG_BIG_INT: - { - JSBigInt *p = JS_VALUE_GET_PTR(val); + if (!s->options.raw_dump && s->ctx) { + JSValue str = js_bigint_to_string(s->ctx, val); + if (JS_IsException(str)) + goto raw_bigint; + js_print_raw_string(s, str); + js_putc(s, 'n'); + JS_FreeValueRT(s->rt, str); + } else { + JSBigInt *p; int sgn, i; + raw_bigint: + p = JS_VALUE_GET_PTR(val); /* In order to avoid allocations we just dump the limbs */ sgn = js_bigint_sign(p); if (sgn) - printf("BigInt.asIntN(%d,", p->len * JS_LIMB_BITS); - printf("0x"); + js_printf(s, "BigInt.asIntN(%d,", p->len * JS_LIMB_BITS); + js_printf(s, "0x"); for(i = p->len - 1; i >= 0; i--) { if (i != p->len - 1) - printf("_"); - printf("%08x", p->tab[i]); + js_putc(s, '_'); +#if JS_LIMB_BITS == 32 + js_printf(s, "%08x", p->tab[i]); +#else + js_printf(s, "%016" PRIx64, p->tab[i]); +#endif } - printf("n"); + js_putc(s, 'n'); if (sgn) - printf(")"); + js_putc(s, ')'); } break; case JS_TAG_STRING: - { - JSString *p; - p = JS_VALUE_GET_STRING(val); - JS_DumpString(rt, p); + case JS_TAG_STRING_ROPE: + if (s->options.raw_dump && tag == JS_TAG_STRING_ROPE) { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + js_printf(s, "[rope len=%d depth=%d]", r->len, r->depth); + } else { + js_print_string(s, val); } break; case JS_TAG_FUNCTION_BYTECODE: { JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); - char buf[ATOM_GET_STR_BUF_SIZE]; - if (b->func_name) { - printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); - } else { - printf("[bytecode (anonymous)]"); - } + js_puts(s, "[bytecode "); + js_print_atom(s, b->func_name); + js_putc(s, ']'); } break; case JS_TAG_OBJECT: { JSObject *p = JS_VALUE_GET_OBJ(val); - JSAtom atom = rt->class_array[p->class_id].class_name; - char atom_buf[ATOM_GET_STR_BUF_SIZE]; - printf("[%s %p]", - JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p); + int idx; + idx = js_print_stack_index(s, p); + if (idx >= 0) { + js_printf(s, "[circular %d]", idx); + } else if (s->level < s->options.max_depth) { + s->print_stack[s->level++] = p; + js_print_object(s, JS_VALUE_GET_OBJ(val)); + s->level--; + } else { + JSAtom atom = s->rt->class_array[p->class_id].class_name; + js_putc(s, '['); + js_print_atom(s, atom); + if (s->options.raw_dump) { + js_printf(s, " %p", (void *)p); + } + js_putc(s, ']'); + } } break; case JS_TAG_SYMBOL: { JSAtomStruct *p = JS_VALUE_GET_PTR(val); - char atom_buf[ATOM_GET_STR_BUF_SIZE]; - printf("Symbol(%s)", - JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p))); + js_puts(s, "Symbol("); + js_print_atom(s, js_get_atom_index(s->rt, p)); + js_putc(s, ')'); } break; case JS_TAG_MODULE: - printf("[module]"); + js_puts(s, "[module]"); break; default: - printf("[unknown tag %d]", tag); + js_printf(s, "[unknown tag %d]", tag); break; } } -bool JS_IsArray(JSValueConst val) +void JS_PrintValueSetDefaultOptions(JSPrintValueOptions *options) { - if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { - JSObject *p = JS_VALUE_GET_OBJ(val); - return p->class_id == JS_CLASS_ARRAY; + memset(options, 0, sizeof(*options)); + options->max_depth = 2; + options->max_string_length = 1000; + options->max_item_count = 100; +} + +static void JS_PrintValueInternal(JSRuntime *rt, JSContext *ctx, + JSPrintValueWrite *write_func, void *write_opaque, + JSValueConst val, const JSPrintValueOptions *options) +{ + JSPrintValueState ss, *s = &ss; + if (options) + s->options = *options; + else + JS_PrintValueSetDefaultOptions(&s->options); + if (s->options.max_depth <= 0) + s->options.max_depth = JS_PRINT_MAX_DEPTH; + else + s->options.max_depth = min_int(s->options.max_depth, JS_PRINT_MAX_DEPTH); + if (s->options.max_string_length == 0) + s->options.max_string_length = UINT32_MAX; + if (s->options.max_item_count == 0) + s->options.max_item_count = UINT32_MAX; + s->rt = rt; + s->ctx = ctx; + s->write_func = write_func; + s->write_opaque = write_opaque; + s->level = 0; + js_print_value(s, val); +} + +void JS_PrintValueRT(JSRuntime *rt, JSPrintValueWrite *write_func, void *write_opaque, + JSValueConst val, const JSPrintValueOptions *options) +{ + JS_PrintValueInternal(rt, NULL, write_func, write_opaque, val, options); +} + +void JS_PrintValue(JSContext *ctx, JSPrintValueWrite *write_func, void *write_opaque, + JSValueConst val, const JSPrintValueOptions *options) +{ + JS_PrintValueInternal(ctx->rt, ctx, write_func, write_opaque, val, options); +} + +static void js_dump_value_write(void *opaque, const char *buf, size_t len) +{ + FILE *fo = opaque; + fwrite(buf, 1, len, fo); +} + +static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom) +{ + JSPrintValueState ss, *s = &ss; + memset(s, 0, sizeof(*s)); + s->rt = ctx->rt; + s->ctx = ctx; + s->write_func = js_dump_value_write; + s->write_opaque = stdout; + js_print_atom(s, atom); +} + +static __maybe_unused void JS_DumpValue(JSContext *ctx, const char *str, JSValueConst val) +{ + printf("%s=", str); + JS_PrintValue(ctx, js_dump_value_write, stdout, val, NULL); + printf("\n"); +} + +static __maybe_unused void JS_DumpValueRT(JSRuntime *rt, const char *str, JSValueConst val) +{ + printf("%s=", str); + JS_PrintValueRT(rt, js_dump_value_write, stdout, val, NULL); + printf("\n"); +} + +static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt) +{ + printf("%14s %4s %4s %14s %s\n", + "ADDRESS", "REFS", "SHRF", "PROTO", "CONTENT"); +} + +/* for debug only: dump an object without side effect */ +static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) +{ + JSShape *sh; + JSPrintValueOptions options; + + /* XXX: should encode atoms with special characters */ + sh = p->shape; /* the shape can be NULL while freeing an object */ + printf("%14p %4d ", + (void *)p, + p->header.ref_count); + if (sh) { + printf("%3d%c %14p ", + sh->header.ref_count, + " *"[sh->is_hashed], + (void *)sh->proto); + } else { + printf("%3s %14s ", "-", "-"); } - return false; + + JS_PrintValueSetDefaultOptions(&options); + options.max_depth = 1; + options.show_hidden = TRUE; + options.raw_dump = TRUE; + JS_PrintValueRT(rt, js_dump_value_write, stdout, JS_MKPTR(JS_TAG_OBJECT, p), &options); + + printf("\n"); } -/* return -1 if exception (proxy case) or true/false */ -static int js_is_array(JSContext *ctx, JSValueConst val) +static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) { - JSObject *p; + if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { + JS_DumpObject(rt, (JSObject *)p); + } else { + printf("%14p %4d ", + (void *)p, + p->ref_count); + switch(p->gc_obj_type) { + case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: + printf("[function bytecode]"); + break; + case JS_GC_OBJ_TYPE_SHAPE: + printf("[shape]"); + break; + case JS_GC_OBJ_TYPE_VAR_REF: + printf("[var_ref]"); + break; + case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: + printf("[async_function]"); + break; + case JS_GC_OBJ_TYPE_JS_CONTEXT: + printf("[js_context]"); + break; + case JS_GC_OBJ_TYPE_MODULE: + printf("[module]"); + break; + default: + printf("[unknown %d]", p->gc_obj_type); + break; + } + printf("\n"); + } +} + +/* return -1 if exception (proxy case) or TRUE/FALSE */ +// TODO: should take flags to make proxy resolution and exceptions optional +int JS_IsArray(JSContext *ctx, JSValueConst val) +{ + if (js_resolve_proxy(ctx, &val, TRUE)) + return -1; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(val); - if (unlikely(p->class_id == JS_CLASS_PROXY)) - return js_proxy_isArray(ctx, val); - else - return p->class_id == JS_CLASS_ARRAY; + JSObject *p = JS_VALUE_GET_OBJ(val); + return p->class_id == JS_CLASS_ARRAY; } else { - return false; + return FALSE; } } -static double js_math_pow(double a, double b) +static double js_pow(double a, double b) { if (unlikely(!isfinite(b)) && fabs(a) == 1) { /* not compatible with IEEE 754 */ - return NAN; + return JS_FLOAT64_NAN; } else { return pow(a, b); } @@ -13329,6 +14093,9 @@ static double js_math_pow(double a, double b) JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) { +#if JS_SHORT_BIG_INT_BITS == 64 + return __JS_NewShortBigInt(ctx, v); +#else if (v >= JS_SHORT_BIG_INT_MIN && v <= JS_SHORT_BIG_INT_MAX) { return __JS_NewShortBigInt(ctx, v); } else { @@ -13338,6 +14105,7 @@ JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) return JS_EXCEPTION; return JS_MKPTR(JS_TAG_BIG_INT, p); } +#endif } JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) @@ -13387,7 +14155,7 @@ static JSValue JS_StringToBigIntErr(JSContext *ctx, JSValue val) { val = JS_StringToBigInt(ctx, val); if (JS_VALUE_IS_NAN(val)) - return JS_ThrowSyntaxError(ctx, "invalid BigInt literal"); + return JS_ThrowSyntaxError(ctx, "invalid bigint literal"); return val; } @@ -13411,6 +14179,7 @@ static JSValue JS_ToBigIntFree(JSContext *ctx, JSValue val) val = __JS_NewShortBigInt(ctx, JS_VALUE_GET_INT(val)); break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: val = JS_StringToBigIntErr(ctx, val); if (JS_IsException(val)) return val; @@ -13430,10 +14199,10 @@ static JSValue JS_ToBigIntFree(JSContext *ctx, JSValue val) static JSValue JS_ToBigInt(JSContext *ctx, JSValueConst val) { - return JS_ToBigIntFree(ctx, js_dup(val)); + return JS_ToBigIntFree(ctx, JS_DupValue(ctx, val)); } -/* XXX: merge with JS_ToInt64Free with a specific flag */ +/* XXX: merge with JS_ToInt64Free with a specific flag ? */ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) { uint64_t res; @@ -13449,8 +14218,10 @@ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) JSBigInt *p = JS_VALUE_GET_PTR(val); /* return the value mod 2^64 */ res = p->tab[0]; +#if JS_LIMB_BITS == 32 if (p->len >= 2) res |= (uint64_t)p->tab[1] << 32; +#endif JS_FreeValue(ctx, val); } *pres = res; @@ -13459,12 +14230,7 @@ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) { - return JS_ToBigInt64Free(ctx, pres, js_dup(val)); -} - -int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValueConst val) -{ - return JS_ToBigInt64Free(ctx, (int64_t *)pres, js_dup(val)); + return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val)); } static no_inline __exception int js_unary_arith_slow(JSContext *ctx, @@ -13500,7 +14266,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, break; case OP_neg: if (v64 == 0) { - sp[-1] = js_float64(-0.0); + sp[-1] = __JS_NewFloat64(ctx, -0.0); return 0; } else { v64 = -v64; @@ -13509,7 +14275,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, default: abort(); } - sp[-1] = js_int64(v64); + sp[-1] = JS_NewInt64(ctx, v64); } break; case JS_TAG_SHORT_BIG_INT: @@ -13597,7 +14363,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, default: abort(); } - sp[-1] = js_float64(d); + sp[-1] = __JS_NewFloat64(ctx, d); } break; } @@ -13620,7 +14386,7 @@ static __exception int js_post_inc_slow(JSContext *ctx, return -1; } sp[-1] = op1; - sp[0] = js_dup(op1); + sp[0] = JS_DupValue(ctx, op1); return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec); } @@ -13645,7 +14411,7 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp) int32_t v1; if (unlikely(JS_ToInt32Free(ctx, &v1, op1))) goto exception; - sp[-1] = js_int32(~v1); + sp[-1] = JS_NewInt32(ctx, ~v1); } return 0; exception: @@ -13739,28 +14505,28 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s case OP_mul: v = (int64_t)v1 * (int64_t)v2; if (v == 0 && (v1 | v2) < 0) { - sp[-2] = js_float64(-0.0); + sp[-2] = __JS_NewFloat64(ctx, -0.0); return 0; } break; case OP_div: - sp[-2] = js_number((double)v1 / (double)v2); + sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2); return 0; case OP_mod: if (v1 < 0 || v2 <= 0) { - sp[-2] = js_number(fmod(v1, v2)); + sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2)); return 0; } else { v = (int64_t)v1 % (int64_t)v2; } break; case OP_pow: - sp[-2] = js_number(js_math_pow(v1, v2)); + sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2)); return 0; default: abort(); } - sp[-2] = js_int64(v); + sp[-2] = JS_NewInt64(ctx, v); } else if ((tag1 == JS_TAG_SHORT_BIG_INT || tag1 == JS_TAG_BIG_INT) && (tag2 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT)) { JSBigInt *p1, *p2, *r; @@ -13786,10 +14552,10 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s r = js_bigint_mul(ctx, p1, p2); break; case OP_div: - r = js_bigint_divrem(ctx, p1, p2, false); + r = js_bigint_divrem(ctx, p1, p2, FALSE); break; case OP_mod: - r = js_bigint_divrem(ctx, p1, p2, true); + r = js_bigint_divrem(ctx, p1, p2, TRUE); break; case OP_pow: r = js_bigint_pow(ctx, p1, p2); @@ -13826,12 +14592,12 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s dr = fmod(d1, d2); break; case OP_pow: - dr = js_math_pow(d1, d2); + dr = js_pow(d1, d2); break; default: abort(); } - sp[-2] = js_float64(dr); + sp[-2] = __JS_NewFloat64(ctx, dr); } return 0; exception: @@ -13840,6 +14606,11 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s return -1; } +static inline BOOL tag_is_string(uint32_t tag) +{ + return tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE; +} + static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) { JSValue op1, op2; @@ -13855,7 +14626,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) double d1, d2; d1 = JS_VALUE_GET_FLOAT64(op1); d2 = JS_VALUE_GET_FLOAT64(op2); - sp[-2] = js_float64(d1 + d2); + sp[-2] = __JS_NewFloat64(ctx, d1 + d2); return 0; } /* fast path for short bigint */ @@ -13875,7 +14646,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) } return 0; } - + if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) { op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { @@ -13892,7 +14663,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) tag2 = JS_VALUE_GET_NORM_TAG(op2); } - if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) { + if (tag_is_string(tag1) || tag_is_string(tag2)) { sp[-2] = JS_ConcatString(ctx, op1, op2); if (JS_IsException(sp[-2])) goto exception; @@ -13918,7 +14689,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); v = (int64_t)v1 + (int64_t)v2; - sp[-2] = js_int64(v); + sp[-2] = JS_NewInt64(ctx, v); } else if ((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) && (tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT)) { JSBigInt *p1, *p2, *r; @@ -13947,7 +14718,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) } if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; - sp[-2] = js_float64(d1 + d2); + sp[-2] = __JS_NewFloat64(ctx, d1 + d2); } return 0; exception: @@ -14108,7 +14879,7 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, default: abort(); } - sp[-2] = js_int32(r); + sp[-2] = JS_NewInt32(ctx, r); } return 0; exception: @@ -14122,7 +14893,7 @@ static JSBigInt *JS_ToBigIntBuf(JSContext *ctx, JSBigIntBuf *buf1, JSValue op1) { JSBigInt *p1; - + switch(JS_VALUE_GET_TAG(op1)) { case JS_TAG_INT: p1 = js_bigint_set_si(buf1, JS_VALUE_GET_INT(op1)); @@ -14147,7 +14918,7 @@ static int js_compare_bigint(JSContext *ctx, OPCodeEnum op, int res, val, tag1, tag2; JSBigIntBuf buf1, buf2; JSBigInt *p1, *p2; - + tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); if ((tag1 == JS_TAG_SHORT_BIG_INT || tag1 == JS_TAG_INT) && @@ -14177,7 +14948,7 @@ static int js_compare_bigint(JSContext *ctx, OPCodeEnum op, unordered: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - return false; + return FALSE; } } else { p1 = JS_ToBigIntBuf(ctx, &buf1, op1); @@ -14221,7 +14992,6 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, op2 = sp[-1]; tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); - op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -14235,11 +15005,13 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); - if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { - JSString *p1, *p2; - p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - res = js_string_compare(p1, p2); + if (tag_is_string(tag1) && tag_is_string(tag2)) { + if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { + res = js_string_compare(ctx, JS_VALUE_GET_STRING(op1), + JS_VALUE_GET_STRING(op2)); + } else { + res = js_string_rope_compare(ctx, op1, op2, FALSE); + } switch(op) { case OP_lt: res = (res < 0); @@ -14263,23 +15035,23 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, goto float64_compare; } else { if ((((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) && - tag2 == JS_TAG_STRING) || + tag_is_string(tag2)) || ((tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) && - tag1 == JS_TAG_STRING))) { - if (tag1 == JS_TAG_STRING) { + tag_is_string(tag1)))) { + if (tag_is_string(tag1)) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op1) != JS_TAG_SHORT_BIG_INT) goto invalid_bigint_string; } - if (tag2 == JS_TAG_STRING) { + if (tag_is_string(tag2)) { op2 = JS_StringToBigInt(ctx, op2); if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op2) != JS_TAG_SHORT_BIG_INT) { invalid_bigint_string: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - res = false; + res = FALSE; goto done; } } @@ -14335,7 +15107,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, } } done: - sp[-2] = js_bool(res); + sp[-2] = JS_NewBool(ctx, res); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14343,15 +15115,15 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, return -1; } -static bool tag_is_number(uint32_t tag) +static BOOL tag_is_number(uint32_t tag) { - return (tag == JS_TAG_INT || + return (tag == JS_TAG_INT || tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT); } static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, - bool is_neq) + BOOL is_neq) { JSValue op1, op2; int res; @@ -14383,33 +15155,34 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, res = (d1 == d2); } else { res = js_compare_bigint(ctx, OP_eq, op1, op2); - if (res < 0) - goto exception; } } else if (tag1 == tag2) { res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) || (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) { - res = true; - } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) || - (tag2 == JS_TAG_STRING && tag_is_number(tag1))) { + res = TRUE; + } else if (tag_is_string(tag1) && tag_is_string(tag2)) { + /* needed when comparing strings and ropes */ + res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); + } else if ((tag_is_string(tag1) && tag_is_number(tag2)) || + (tag_is_string(tag2) && tag_is_number(tag1))) { if (tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) { - if (tag1 == JS_TAG_STRING) { + if (tag_is_string(tag1)) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op1) != JS_TAG_SHORT_BIG_INT) goto invalid_bigint_string; } - if (tag2 == JS_TAG_STRING) { + if (tag_is_string(tag2)) { op2 = JS_StringToBigInt(ctx, op2); if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op2) != JS_TAG_SHORT_BIG_INT ) { invalid_bigint_string: JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - res = false; + res = FALSE; goto done; } } @@ -14425,17 +15198,17 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, goto exception; } } - res = js_strict_eq(ctx, op1, op2); + res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } else if (tag1 == JS_TAG_BOOL) { - op1 = js_int32(JS_VALUE_GET_INT(op1)); + op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1)); goto redo; } else if (tag2 == JS_TAG_BOOL) { - op2 = js_int32(JS_VALUE_GET_INT(op2)); + op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2)); goto redo; } else if ((tag1 == JS_TAG_OBJECT && - (tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) || + (tag_is_number(tag2) || tag_is_string(tag2) || tag2 == JS_TAG_SYMBOL)) || (tag2 == JS_TAG_OBJECT && - (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) { + (tag_is_number(tag1) || tag_is_string(tag1) || tag1 == JS_TAG_SYMBOL))) { op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -14453,15 +15226,15 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) || (JS_IsHTMLDDA(ctx, op2) && (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) { - res = true; + res = TRUE; } else { - res = false; + res = FALSE; } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); } done: - sp[-2] = js_bool(res ^ is_neq); + sp[-2] = JS_NewBool(ctx, res ^ is_neq); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14486,12 +15259,11 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) JS_FreeValue(ctx, op1); goto exception; } - if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT || JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT || JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT || JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT) { - JS_ThrowTypeError(ctx, "BigInt operands are forbidden for >>>"); + JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>"); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); goto exception; @@ -14500,7 +15272,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) JS_ToUint32Free(ctx, &v1, op1); JS_ToUint32Free(ctx, &v2, op2); r = v1 >> (v2 & 0x1f); - sp[-2] = js_uint32(r); + sp[-2] = JS_NewUint32(ctx, r); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14508,10 +15280,11 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) return -1; } -static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, +/* XXX: Should take JSValueConst arguments */ +static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode) { - bool res; + BOOL res; int tag1, tag2; double d1, d2; @@ -14520,7 +15293,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, switch(tag1) { case JS_TAG_BOOL: if (tag1 != tag2) { - res = false; + res = FALSE; } else { res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2); goto done_no_free; @@ -14531,14 +15304,15 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, res = (tag1 == tag2); break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: { - JSString *p1, *p2; - if (tag1 != tag2) { - res = false; + if (!tag_is_string(tag2)) { + res = FALSE; + } else if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { + res = (js_string_compare(ctx, JS_VALUE_GET_STRING(op1), + JS_VALUE_GET_STRING(op2)) == 0); } else { - p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - res = js_string_eq(p1, p2); + res = (js_string_rope_compare(ctx, op1, op2, TRUE) == 0); } } break; @@ -14546,7 +15320,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, { JSAtomStruct *p1, *p2; if (tag1 != tag2) { - res = false; + res = FALSE; } else { p1 = JS_VALUE_GET_PTR(op1); p2 = JS_VALUE_GET_PTR(op2); @@ -14556,7 +15330,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, break; case JS_TAG_OBJECT: if (tag1 != tag2) - res = false; + res = FALSE; else res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2); break; @@ -14569,7 +15343,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, d2 = JS_VALUE_GET_FLOAT64(op2); goto number_test; } else { - res = false; + res = FALSE; } break; case JS_TAG_FLOAT64: @@ -14579,7 +15353,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, } else if (tag2 == JS_TAG_INT) { d2 = JS_VALUE_GET_INT(op2); } else { - res = false; + res = FALSE; break; } number_test: @@ -14607,10 +15381,10 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, if (tag2 != JS_TAG_SHORT_BIG_INT && tag2 != JS_TAG_BIG_INT) { - res = false; + res = FALSE; break; } - + if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else @@ -14623,7 +15397,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, } break; default: - res = false; + res = FALSE; break; } JS_FreeValue(ctx, op1); @@ -14632,27 +15406,48 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, return res; } -static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2) +static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); + return js_strict_eq2(ctx, + JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), + JS_EQ_STRICT); } -static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) +BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE); + return js_strict_eq(ctx, op1, op2); } -static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) +static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE_ZERO); + return js_strict_eq2(ctx, + JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), + JS_EQ_SAME_VALUE); +} + +BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_same_value(ctx, op1, op2); +} + +static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_strict_eq2(ctx, + JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), + JS_EQ_SAME_VALUE_ZERO); +} + +BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_same_value_zero(ctx, op1, op2); } static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, - bool is_neq) + BOOL is_neq) { - bool res; - res = js_strict_eq(ctx, sp[-2], sp[-1]); - sp[-2] = js_bool(res ^ is_neq); + BOOL res; + res = js_strict_eq2(ctx, sp[-2], sp[-1], JS_EQ_STRICT); + sp[-2] = JS_NewBool(ctx, res ^ is_neq); return 0; } @@ -14678,7 +15473,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = js_bool(ret); + sp[-2] = JS_NewBool(ctx, ret); return 0; } @@ -14686,8 +15481,10 @@ static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp) { JSValue op1, op2; int ret; + op1 = sp[-2]; /* object */ op2 = sp[-1]; /* field name or method function */ + if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) { JS_ThrowTypeError(ctx, "invalid 'in' operand"); return -1; @@ -14713,11 +15510,11 @@ static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp) } JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = js_bool(ret); + sp[-2] = JS_NewBool(ctx, ret); return 0; } -static __exception int js_has_unscopable(JSContext *ctx, JSValue obj, +static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj, JSAtom atom) { JSValue arr, val; @@ -14738,7 +15535,7 @@ static __exception int js_has_unscopable(JSContext *ctx, JSValue obj, static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) { JSValue op1, op2; - int ret; + BOOL ret; op1 = sp[-2]; op2 = sp[-1]; @@ -14747,11 +15544,11 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) return ret; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = js_bool(ret); + sp[-2] = JS_NewBool(ctx, ret); return 0; } -static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) +static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1) { JSAtom atom; uint32_t tag; @@ -14773,6 +15570,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) atom = JS_ATOM_boolean; break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: atom = JS_ATOM_string; break; case JS_TAG_OBJECT: @@ -14818,15 +15616,18 @@ static __exception int js_operator_delete(JSContext *ctx, JSValue *sp) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = js_bool(ret); + sp[-2] = JS_NewBool(ctx, ret); return 0; } +/* XXX: not 100% compatible, but mozilla seems to use a similar + implementation to ensure that caller in non strict mode does not + throw (ES5 compatibility) */ static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (!b || b->is_strict_mode || !b->has_prototype) { + if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype || argc >= 1) { return JS_ThrowTypeError(ctx, "invalid property access"); } return JS_UNDEFINED; @@ -14836,20 +15637,23 @@ static JSValue js_function_proto_fileName(JSContext *ctx, JSValueConst this_val) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (b) { - return JS_AtomToString(ctx, b->filename); + if (b && b->has_debug) { + return JS_AtomToString(ctx, b->debug.filename); } return JS_UNDEFINED; } -static JSValue js_function_proto_int32(JSContext *ctx, - JSValueConst this_val, - int magic) +static JSValue js_function_proto_lineNumber(JSContext *ctx, + JSValueConst this_val, int is_col) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (b) { - int *field = (int *) ((char *)b + magic); - return js_int32(*field); + if (b && b->has_debug) { + int line_num, col_num; + line_num = find_line_num(ctx, b, -1, &col_num); + if (is_col) + return JS_NewInt32(ctx, col_num); + else + return JS_NewInt32(ctx, line_num); } return JS_UNDEFINED; } @@ -14857,8 +15661,7 @@ static JSValue js_function_proto_int32(JSContext *ctx, static int js_arguments_define_own_property(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValueConst val, - JSValueConst getter, - JSValueConst setter, int flags) + JSValueConst getter, JSValueConst setter, int flags) { JSObject *p; uint32_t idx; @@ -14894,35 +15697,34 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) /* add the length field (cannot fail) */ pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (!pr) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - pr->u.value = js_int32(argc); + if (unlikely(!pr)) + goto fail; + pr->u.value = JS_NewInt32(ctx, argc); /* initialize the fast array part */ tab = NULL; if (argc > 0) { tab = js_malloc(ctx, sizeof(tab[0]) * argc); - if (!tab) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } + if (!tab) + goto fail; for(i = 0; i < argc; i++) { - tab[i] = js_dup(argv[i]); + tab[i] = JS_DupValue(ctx, argv[i]); } } p->u.array.u.values = tab; p->u.array.count = argc; JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - js_dup(ctx->array_proto_values), + JS_DupValue(ctx, ctx->array_proto_values), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); /* add callee property to throw a TypeError in strict mode */ JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED, ctx->throw_type_error, ctx->throw_type_error, JS_PROP_HAS_GET | JS_PROP_HAS_SET); return val; + fail: + JS_FreeValue(ctx, val); + return JS_EXCEPTION; } #define GLOBAL_VAR_OFFSET 0x40000000 @@ -14947,13 +15749,13 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, /* add the length field (cannot fail) */ pr = add_property(ctx, p, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (!pr) + if (unlikely(!pr)) goto fail; - pr->u.value = js_int32(argc); + pr->u.value = JS_NewInt32(ctx, argc); for(i = 0; i < arg_count; i++) { JSVarRef *var_ref; - var_ref = get_var_ref(ctx, sf, i, true); + var_ref = get_var_ref(ctx, sf, i, TRUE); if (!var_ref) goto fail; pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); @@ -14968,17 +15770,17 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, be normal properties */ for(i = arg_count; i < argc; i++) { if (JS_DefinePropertyValueUint32(ctx, val, i, - js_dup(argv[i]), + JS_DupValue(ctx, argv[i]), JS_PROP_C_W_E) < 0) goto fail; } JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - js_dup(ctx->array_proto_values), + JS_DupValue(ctx, ctx->array_proto_values), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); /* callee returns this function in non strict mode */ JS_DefinePropertyValue(ctx, val, JS_ATOM_callee, - js_dup(ctx->rt->current_stack_frame->cur_func), + JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); return val; fail: @@ -14988,10 +15790,10 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) { - JSObject *p; + JSObject *p, *p1; JSPropertyEnum *tab_atom; int i; - JSValue enum_obj, obj1; + JSValue enum_obj; JSForInIterator *it; uint32_t tag, tab_atom_count; @@ -15011,43 +15813,19 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - it->is_array = false; + it->is_array = FALSE; it->obj = obj; it->idx = 0; - p = JS_VALUE_GET_OBJ(enum_obj); - p->u.for_in_iterator = it; + it->tab_atom = NULL; + it->atom_count = 0; + it->in_prototype_chain = FALSE; + p1 = JS_VALUE_GET_OBJ(enum_obj); + p1->u.for_in_iterator = it; if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) return enum_obj; - /* fast path: assume no enumerable properties in the prototype chain */ - obj1 = js_dup(obj); - for(;;) { - obj1 = JS_GetPrototypeFree(ctx, obj1); - if (JS_IsNull(obj1)) - break; - if (JS_IsException(obj1)) - goto fail; - if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, - JS_VALUE_GET_OBJ(obj1), - JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) { - JS_FreeValue(ctx, obj1); - goto fail; - } - js_free_prop_enum(ctx, tab_atom, tab_atom_count); - if (tab_atom_count != 0) { - JS_FreeValue(ctx, obj1); - goto slow_path; - } - /* must check for timeout to avoid infinite loop */ - if (js_poll_interrupts(ctx)) { - JS_FreeValue(ctx, obj1); - goto fail; - } - } - p = JS_VALUE_GET_OBJ(obj); - if (p->fast_array) { JSShape *sh; JSShapeProperty *prs; @@ -15058,71 +15836,102 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) goto normal_case; } /* for fast arrays, we only store the number of elements */ - it->is_array = true; - it->array_length = p->u.array.count; + it->is_array = TRUE; + it->atom_count = p->u.array.count; } else { normal_case: if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, - JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) - goto fail; - for(i = 0; i < tab_atom_count; i++) { - JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0); + JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { + JS_FreeValue(ctx, enum_obj); + return JS_EXCEPTION; } - js_free_prop_enum(ctx, tab_atom, tab_atom_count); + it->tab_atom = tab_atom; + it->atom_count = tab_atom_count; } return enum_obj; +} - slow_path: - /* non enumerable properties hide the enumerables ones in the - prototype chain */ - obj1 = js_dup(obj); +/* obj -> enum_obj */ +static __exception int js_for_in_start(JSContext *ctx, JSValue *sp) +{ + sp[-1] = build_for_in_iterator(ctx, sp[-1]); + if (JS_IsException(sp[-1])) + return -1; + return 0; +} + +/* return -1 if exception, 0 if slow case, 1 if the enumeration is finished */ +static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx, + JSValueConst enum_obj) +{ + JSObject *p; + JSForInIterator *it; + JSPropertyEnum *tab_atom; + uint32_t tab_atom_count, i; + JSValue obj1; + + p = JS_VALUE_GET_OBJ(enum_obj); + it = p->u.for_in_iterator; + + /* check if there are enumerable properties in the prototype chain (fast path) */ + obj1 = JS_DupValue(ctx, it->obj); for(;;) { + obj1 = JS_GetPrototypeFree(ctx, obj1); + if (JS_IsNull(obj1)) + break; + if (JS_IsException(obj1)) + goto fail; if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, JS_VALUE_GET_OBJ(obj1), - JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { + JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) { JS_FreeValue(ctx, obj1); goto fail; } - for(i = 0; i < tab_atom_count; i++) { - JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL, - (tab_atom[i].is_enumerable ? - JS_PROP_ENUMERABLE : 0)); + JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count); + if (tab_atom_count != 0) { + JS_FreeValue(ctx, obj1); + goto slow_path; } - js_free_prop_enum(ctx, tab_atom, tab_atom_count); - obj1 = JS_GetPrototypeFree(ctx, obj1); - if (JS_IsNull(obj1)) - break; - if (JS_IsException(obj1)) - goto fail; /* must check for timeout to avoid infinite loop */ if (js_poll_interrupts(ctx)) { JS_FreeValue(ctx, obj1); goto fail; } } - return enum_obj; + JS_FreeValue(ctx, obj1); + return 1; - fail: - JS_FreeValue(ctx, enum_obj); - return JS_EXCEPTION; -} + slow_path: + /* add the visited properties, even if they are not enumerable */ + if (it->is_array) { + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, + JS_VALUE_GET_OBJ(it->obj), + JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { + goto fail; + } + it->is_array = FALSE; + it->tab_atom = tab_atom; + it->atom_count = tab_atom_count; + } -/* obj -> enum_obj */ -static __exception int js_for_in_start(JSContext *ctx, JSValue *sp) -{ - sp[-1] = build_for_in_iterator(ctx, sp[-1]); - if (JS_IsException(sp[-1])) - return -1; + for(i = 0; i < it->atom_count; i++) { + if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0) + goto fail; + } return 0; + fail: + return -1; } /* enum_obj -> enum_obj value done */ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) { - JSValue enum_obj; + JSValueConst enum_obj; JSObject *p; JSAtom prop; JSForInIterator *it; + JSPropertyEnum *tab_atom; + uint32_t tab_atom_count; int ret; enum_obj = sp[-1]; @@ -15135,34 +15944,68 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) it = p->u.for_in_iterator; for(;;) { - if (it->is_array) { - if (it->idx >= it->array_length) - goto done; - prop = __JS_AtomFromUInt32(it->idx); - it->idx++; + if (it->idx >= it->atom_count) { + if (JS_IsNull(it->obj) || JS_IsUndefined(it->obj)) + goto done; /* not an object */ + /* no more property in the current object: look in the prototype */ + if (!it->in_prototype_chain) { + ret = js_for_in_prepare_prototype_chain_enum(ctx, enum_obj); + if (ret < 0) + return -1; + if (ret) + goto done; + it->in_prototype_chain = TRUE; + } + it->obj = JS_GetPrototypeFree(ctx, it->obj); + if (JS_IsException(it->obj)) + return -1; + if (JS_IsNull(it->obj)) + goto done; /* no more prototype */ + + /* must check for timeout to avoid infinite loop */ + if (js_poll_interrupts(ctx)) + return -1; + + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, + JS_VALUE_GET_OBJ(it->obj), + JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { + return -1; + } + JS_FreePropertyEnum(ctx, it->tab_atom, it->atom_count); + it->tab_atom = tab_atom; + it->atom_count = tab_atom_count; + it->idx = 0; } else { - JSShape *sh = p->shape; - JSShapeProperty *prs; - if (it->idx >= sh->prop_count) - goto done; - prs = get_shape_prop(sh) + it->idx; - prop = prs->atom; - it->idx++; - if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE)) - continue; - } - // check if the property was deleted unless we're dealing with a proxy - JSValue obj = it->obj; - if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { - JSObject *p = JS_VALUE_GET_OBJ(obj); - if (p->class_id == JS_CLASS_PROXY) + if (it->is_array) { + prop = __JS_AtomFromUInt32(it->idx); + it->idx++; + } else { + BOOL is_enumerable; + prop = it->tab_atom[it->idx].atom; + is_enumerable = it->tab_atom[it->idx].is_enumerable; + it->idx++; + if (it->in_prototype_chain) { + /* slow case: we are in the prototype chain */ + ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(enum_obj), prop); + if (ret < 0) + return ret; + if (ret) + continue; /* already visited */ + /* add to the visited property list */ + if (JS_DefinePropertyValue(ctx, enum_obj, prop, JS_NULL, + JS_PROP_ENUMERABLE) < 0) + return -1; + } + if (!is_enumerable) + continue; + } + /* check if the property was deleted */ + ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(it->obj), prop); + if (ret < 0) + return ret; + if (ret) break; } - ret = JS_HasProperty(ctx, obj, prop); - if (ret < 0) - return ret; - if (ret) - break; } /* return the property */ sp[0] = JS_AtomToValue(ctx, prop); @@ -15190,7 +16033,7 @@ static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj, return enum_obj; } -static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, bool is_async) +static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async) { JSValue method, ret, sync_iter; @@ -15261,13 +16104,14 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj, *pdone = 2; return obj; fail: - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } +/* Note: always return JS_UNDEFINED when *pdone = TRUE. */ static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, JSValueConst method, - int argc, JSValueConst *argv, int *pdone) + int argc, JSValueConst *argv, BOOL *pdone) { JSValue obj, value, done_val; int done; @@ -15276,11 +16120,11 @@ static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, if (JS_IsException(obj)) goto fail; if (likely(done == 0)) { - *pdone = false; + *pdone = FALSE; return obj; } else if (done != 2) { JS_FreeValue(ctx, obj); - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } else { done_val = JS_GetProperty(ctx, obj, JS_ATOM_done); @@ -15296,13 +16140,13 @@ static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, } fail: JS_FreeValue(ctx, obj); - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } /* return < 0 in case of exception */ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj, - bool is_exception_pending) + BOOL is_exception_pending) { JSValue method, ret, ex_obj; int res; @@ -15342,7 +16186,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj, /* obj -> enum_rec (3 slots) */ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp, - bool is_async) + BOOL is_async) { JSValue op1, obj, method; op1 = sp[-1]; @@ -15385,15 +16229,30 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset) } } sp[0] = value; - sp[1] = js_bool(done); + sp[1] = JS_NewBool(ctx, done); + return 0; +} + +static __exception int js_for_await_of_next(JSContext *ctx, JSValue *sp) +{ + JSValue obj, iter, next; + + sp[-1] = JS_UNDEFINED; /* disable the catch offset so that + exceptions do not close the iterator */ + iter = sp[-3]; + next = sp[-2]; + obj = JS_Call(ctx, next, iter, 0, NULL); + if (JS_IsException(obj)) + return -1; + sp[0] = obj; return 0; } -static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj, - int *pdone) +static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj, + BOOL *pdone) { JSValue done_val, value; - int done; + BOOL done; done_val = JS_GetProperty(ctx, obj, JS_ATOM_done); if (JS_IsException(done_val)) goto fail; @@ -15404,14 +16263,14 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj, *pdone = done; return value; fail: - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) { JSValue obj, value; - int done; + BOOL done; obj = sp[-1]; if (!JS_IsObject(obj)) { JS_ThrowTypeError(ctx, "iterator must return an object"); @@ -15421,14 +16280,17 @@ static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) if (JS_IsException(value)) return -1; JS_FreeValue(ctx, obj); + /* put again the catch offset so that exceptions close the + iterator */ + sp[-2] = JS_NewCatchOffset(ctx, 0); sp[-1] = value; - sp[0] = js_bool(done); + sp[0] = JS_NewBool(ctx, done); return 0; } static JSValue js_create_iterator_result(JSContext *ctx, JSValue val, - bool done) + BOOL done) { JSValue obj; obj = JS_NewObject(ctx); @@ -15441,7 +16303,7 @@ static JSValue js_create_iterator_result(JSContext *ctx, goto fail; } if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done, - js_bool(done), JS_PROP_C_W_E) < 0) { + JS_NewBool(ctx, done), JS_PROP_C_W_E) < 0) { fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -15451,25 +16313,25 @@ static JSValue js_create_iterator_result(JSContext *ctx, static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic); + BOOL *pdone, int magic); static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); -static bool js_is_fast_array(JSContext *ctx, JSValue obj) +static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj) { /* Try and handle fast arrays explicitly */ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); if (p->class_id == JS_CLASS_ARRAY && p->fast_array) { - return true; + return TRUE; } } - return false; + return FALSE; } /* Access an Array's internal JSValue array if available */ -static bool js_get_fast_array(JSContext *ctx, JSValue obj, +static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp) { /* Try and handle fast arrays explicitly */ @@ -15478,10 +16340,10 @@ static bool js_get_fast_array(JSContext *ctx, JSValue obj, if (p->class_id == JS_CLASS_ARRAY && p->fast_array) { *countp = p->u.array.count; *arrpp = p->u.array.u.values; - return true; + return TRUE; } } - return false; + return FALSE; } static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) @@ -15490,6 +16352,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) int is_array_iterator; JSValue *arrp; uint32_t i, count32, pos; + JSCFunctionType ft; if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) { JS_ThrowInternalError(ctx, "invalid index for append"); @@ -15507,14 +16370,12 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator); if (JS_IsException(iterator)) return -1; - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft = { .generic_magic = js_create_array_iterator }; - is_array_iterator = JS_IsCFunction(ctx, iterator, - ft.generic, + ft.generic_magic = js_create_array_iterator; + is_array_iterator = JS_IsCFunction(ctx, iterator, ft.generic, JS_ITERATOR_KIND_VALUE); JS_FreeValue(ctx, iterator); - enumobj = JS_GetIterator(ctx, sp[-1], false); + enumobj = JS_GetIterator(ctx, sp[-1], FALSE); if (JS_IsException(enumobj)) return -1; method = JS_GetProperty(ctx, enumobj, JS_ATOM_next); @@ -15522,11 +16383,11 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) JS_FreeValue(ctx, enumobj); return -1; } - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft2 = { .iterator_next = js_array_iterator_next }; + + ft.iterator_next = js_array_iterator_next; if (is_array_iterator - && JS_IsCFunction(ctx, method, ft2.generic, 0) - && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) { + && JS_IsCFunction(ctx, method, ft.generic, 0) + && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) { uint32_t len; if (js_get_length32(ctx, &len, sp[-1])) goto exception; @@ -15537,13 +16398,13 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) /* Handle fast arrays explicitly */ for (i = 0; i < count32; i++) { if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, - js_dup(arrp[i]), JS_PROP_C_W_E) < 0) + JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0) goto exception; } } else { general_case: for (;;) { - int done; + BOOL done; value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done); if (JS_IsException(value)) goto exception; @@ -15556,23 +16417,23 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) } } /* Note: could raise an error if too many elements */ - sp[-2] = js_int32(pos); + sp[-2] = JS_NewInt32(ctx, pos); JS_FreeValue(ctx, enumobj); JS_FreeValue(ctx, method); return 0; exception: - JS_IteratorClose(ctx, enumobj, true); + JS_IteratorClose(ctx, enumobj, TRUE); JS_FreeValue(ctx, enumobj); JS_FreeValue(ctx, method); return -1; } static __exception int JS_CopyDataProperties(JSContext *ctx, - JSValue target, - JSValue source, - JSValue excluded, - bool setprop) + JSValueConst target, + JSValueConst source, + JSValueConst excluded, + BOOL setprop) { JSPropertyEnum *tab_atom; JSValue val; @@ -15581,7 +16442,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, JSObject *pexcl = NULL; int ret, gpn_flags; JSPropertyDescriptor desc; - bool is_enumerable; + BOOL is_enumerable; if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT) return 0; @@ -15636,10 +16497,10 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, if (ret < 0) goto exception; } - js_free_prop_enum(ctx, tab_atom, tab_atom_count); + JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count); return 0; exception: - js_free_prop_enum(ctx, tab_atom, tab_atom_count); + JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count); return -1; } @@ -15650,7 +16511,7 @@ static JSValueConst JS_GetActiveFunction(JSContext *ctx) } static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, - int var_idx, bool is_arg) + int var_idx, BOOL is_arg) { JSVarRef *var_ref; struct list_head *el; @@ -15662,7 +16523,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, pvalue = &sf->var_buf[var_idx]; list_for_each(el, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); + var_ref = list_entry(el, JSVarRef, var_ref_link); if (var_ref->pvalue == pvalue) { var_ref->header.ref_count++; return var_ref; @@ -15673,10 +16534,24 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, if (!var_ref) return NULL; var_ref->header.ref_count = 1; - var_ref->is_detached = false; - list_add_tail(&var_ref->header.link, &sf->var_ref_list); + add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + var_ref->is_detached = FALSE; + list_add_tail(&var_ref->var_ref_link, &sf->var_ref_list); + if (sf->js_mode & JS_MODE_ASYNC) { + /* The stack frame is detached and may be destroyed at any + time so its reference count must be increased. Calling + close_var_refs() when destroying the stack frame is not + possible because it would change the graph between the GC + objects. Another solution could be to temporarily detach + the JSVarRef of async functions during the GC. It would + have the advantage of allowing the release of unused stack + frames in a cycle. */ + var_ref->async_func = container_of(sf, JSAsyncFunctionState, frame); + var_ref->async_func->header.ref_count++; + } else { + var_ref->async_func = NULL; + } var_ref->pvalue = pvalue; - var_ref->value = JS_UNDEFINED; return var_ref; } @@ -15729,8 +16604,10 @@ static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; + set_cycle_flag(ctx, obj); + set_cycle_flag(ctx, this_val); ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor, - js_dup(this_val), + JS_DupValue(ctx, this_val), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (ret < 0) { JS_FreeValue(ctx, obj); @@ -15789,7 +16666,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, /* add the 'prototype' property: delay instantiation to avoid creating cycles for every javascript function. The prototype object is created on the fly when first accessed */ - JS_SetConstructorBit(ctx, func_obj, true); + JS_SetConstructorBit(ctx, func_obj, TRUE); JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype, JS_AUTOINIT_ID_PROTOTYPE, NULL, JS_PROP_WRITABLE); @@ -15806,7 +16683,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, static int js_op_define_class(JSContext *ctx, JSValue *sp, JSAtom class_name, int class_flags, JSVarRef **cur_var_refs, - JSStackFrame *sf, bool is_computed_name) + JSStackFrame *sf, BOOL is_computed_name) { JSValue bfunc, parent_class, proto = JS_UNDEFINED; JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED; @@ -15818,7 +16695,7 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE) { if (JS_IsNull(parent_class)) { parent_proto = JS_NULL; - parent_class = js_dup(ctx->function_proto); + parent_class = JS_DupValue(ctx, ctx->function_proto); } else { if (!JS_IsConstructor(ctx, parent_class)) { JS_ThrowTypeError(ctx, "parent class must be constructor"); @@ -15834,8 +16711,8 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, } } else { /* parent_class is JS_UNDEFINED in this case */ - parent_proto = js_dup(ctx->class_proto[JS_CLASS_OBJECT]); - parent_class = js_dup(ctx->function_proto); + parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]); + parent_class = JS_DupValue(ctx, ctx->function_proto); } proto = JS_NewObjectProto(ctx, parent_proto); if (JS_IsException(proto)) @@ -15852,10 +16729,10 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, if (JS_IsException(ctor)) goto fail; js_method_set_home_object(ctx, ctor, proto); - JS_SetConstructorBit(ctx, ctor, true); + JS_SetConstructorBit(ctx, ctor, TRUE); JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length, - js_int32(b->defined_arg_count), + JS_NewInt32(ctx, b->defined_arg_count), JS_PROP_CONFIGURABLE); if (is_computed_name) { @@ -15870,14 +16747,16 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, /* the constructor property must be first. It can be overriden by computed property names */ if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, - js_dup(ctor), + JS_DupValue(ctx, ctor), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_THROW) < 0) goto fail; /* set the prototype property */ if (JS_DefinePropertyValue(ctx, ctor, JS_ATOM_prototype, - js_dup(proto), JS_PROP_THROW) < 0) + JS_DupValue(ctx, proto), JS_PROP_THROW) < 0) goto fail; + set_cycle_flag(ctx, ctor); + set_cycle_flag(ctx, proto); JS_FreeValue(ctx, parent_proto); JS_FreeValue(ctx, parent_class); @@ -15902,12 +16781,14 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) JSVarRef *var_ref; list_for_each_safe(el, el1, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); - var_ref->value = js_dup(*var_ref->pvalue); + var_ref = list_entry(el, JSVarRef, var_ref_link); + /* no need to unlink var_ref->var_ref_link as the list is never used afterwards */ + if (var_ref->async_func) + async_func_free(rt, var_ref->async_func); + var_ref->value = JS_DupValueRT(rt, *var_ref->pvalue); var_ref->pvalue = &var_ref->value; /* the reference is no longer to a local variable */ - var_ref->is_detached = true; - add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + var_ref->is_detached = TRUE; } } @@ -15919,14 +16800,15 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx) pvalue = &sf->var_buf[var_idx]; list_for_each_safe(el, el1, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); + var_ref = list_entry(el, JSVarRef, var_ref_link); if (var_ref->pvalue == pvalue) { - var_ref->value = js_dup(*var_ref->pvalue); + list_del(&var_ref->var_ref_link); + if (var_ref->async_func) + async_func_free(ctx->rt, var_ref->async_func); + var_ref->value = JS_DupValue(ctx, *var_ref->pvalue); var_ref->pvalue = &var_ref->value; - list_del(&var_ref->header.link); /* the reference is no longer to a local variable */ - var_ref->is_detached = true; - add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + var_ref->is_detached = TRUE; } } } @@ -15959,9 +16841,8 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, sf->prev_frame = prev_sf; rt->current_stack_frame = sf; ctx = p->u.cfunc.realm; /* change the current realm */ - - sf->is_strict_mode = false; - sf->cur_func = unsafe_unconst(func_obj); + sf->js_mode = 0; + sf->cur_func = JS_VALUE_CONST_CAST(func_obj); sf->arg_count = argc; arg_buf = argv; @@ -15974,7 +16855,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, arg_buf[i] = JS_UNDEFINED; sf->arg_count = arg_count; } - sf->arg_buf = (JSValue *)arg_buf; + sf->arg_buf = (JSValue*)arg_buf; func = p->u.cfunc.c_function; switch(cproto) { @@ -16028,7 +16909,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ret_val = JS_EXCEPTION; break; } - ret_val = js_number(func.f_f(d1)); + ret_val = JS_NewFloat64(ctx, func.f_f(d1)); } break; case JS_CFUNC_f_f_f: @@ -16043,7 +16924,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ret_val = JS_EXCEPTION; break; } - ret_val = js_number(func.f_f_f(d1, d2)); + ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2)); } break; case JS_CFUNC_iterator_next: @@ -16106,67 +16987,46 @@ typedef enum { OP_SPECIAL_OBJECT_HOME_OBJECT, OP_SPECIAL_OBJECT_VAR_OBJECT, OP_SPECIAL_OBJECT_IMPORT_META, - OP_SPECIAL_OBJECT_NULL_PROTO, } OPSpecialObjectEnum; -#define FUNC_RET_AWAIT 0 -#define FUNC_RET_YIELD 1 -#define FUNC_RET_YIELD_STAR 2 - -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* -static void dump_single_byte_code(JSContext *ctx, const uint8_t *pc, - JSFunctionBytecode *b, int start_pos); -static void print_func_name(JSFunctionBytecode *b); -#endif - -static bool needs_backtrace(JSValue exc) -{ - JSObject *p; - - if (JS_VALUE_GET_TAG(exc) != JS_TAG_OBJECT) - return false; - p = JS_VALUE_GET_OBJ(exc); - if (p->class_id != JS_CLASS_ERROR) - return false; - return !find_own_property1(p, JS_ATOM_stack); -} +#define FUNC_RET_AWAIT 0 +#define FUNC_RET_YIELD 1 +#define FUNC_RET_YIELD_STAR 2 +#define FUNC_RET_INITIAL_YIELD 3 /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSValueConst this_obj, JSValueConst new_target, - int argc, JSValueConst *argv, int flags) + int argc, JSValue *argv, int flags) { JSRuntime *rt = caller_ctx->rt; JSContext *ctx; JSObject *p; JSFunctionBytecode *b; JSStackFrame sf_s, *sf = &sf_s; - uint8_t *pc; + const uint8_t *pc; int opcode, arg_allocated_size, i; JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval; JSVarRef **var_refs; size_t alloca_size; -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP -#define DUMP_BYTECODE_OR_DONT(pc) \ - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP)) dump_single_byte_code(ctx, pc, b, 0); -#else -#define DUMP_BYTECODE_OR_DONT(pc) -#endif - #if !DIRECT_DISPATCH -#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) switch (opcode = *pc++) +#define SWITCH(pc) switch (opcode = *pc++) #define CASE(op) case op #define DEFAULT default #define BREAK break #else - __extension__ static const void * const dispatch_table[256] = { + static const void * const dispatch_table[256] = { #define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id, +#if SHORT_OPCODES #define def(id, size, n_pop, n_push, f) +#else +#define def(id, size, n_pop, n_push, f) && case_default, +#endif #include "quickjs-opcode.h" [ OP_COUNT ... 255 ] = &&case_default }; -#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) __extension__ ({ goto *dispatch_table[opcode = *pc++]; }); +#define SWITCH(pc) goto *dispatch_table[opcode = *pc++]; #define CASE(op) case_ ## op #define DEFAULT case_default #define BREAK SWITCH(pc) @@ -16206,10 +17066,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, call_func = rt->class_array[p->class_id].call; if (!call_func) { not_a_function: - return JS_ThrowTypeErrorNotAFunction(caller_ctx); + return JS_ThrowTypeError(caller_ctx, "not a function"); } return call_func(caller_ctx, func_obj, this_obj, argc, - argv, flags); + (JSValueConst *)argv, flags); } b = p->u.func.function_bytecode; @@ -16224,10 +17084,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (js_check_stack_overflow(rt, alloca_size)) return JS_ThrowStackOverflow(caller_ctx); - sf->is_strict_mode = b->is_strict_mode; - arg_buf = (JSValue *)argv; + sf->js_mode = b->js_mode; + arg_buf = argv; sf->arg_count = argc; - sf->cur_func = unsafe_unconst(func_obj); + sf->cur_func = JS_VALUE_CONST_CAST(func_obj); init_list_head(&sf->var_ref_list); var_refs = p->u.func.var_refs; @@ -16236,7 +17096,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int n = min_int(argc, b->arg_count); arg_buf = local_buf; for(i = 0; i < n; i++) - arg_buf[i] = js_dup(argv[i]); + arg_buf[i] = JS_DupValue(caller_ctx, argv[i]); for(; i < b->arg_count; i++) arg_buf[i] = JS_UNDEFINED; sf->arg_count = b->arg_count; @@ -16251,17 +17111,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, stack_buf = var_buf + b->var_count; sp = stack_buf; pc = b->byte_code_buf; - /* sf->cur_pc must we set to pc before any recursive calls to JS_CallInternal. */ - sf->cur_pc = NULL; sf->prev_frame = rt->current_stack_frame; rt->current_stack_frame = sf; ctx = b->realm; /* set the current realm */ -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STEP - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STEP)) - print_func_name(b); -#endif - restart: for(;;) { int call_argc; @@ -16269,7 +17122,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, SWITCH(pc) { CASE(OP_push_i32): - *sp++ = js_int32(get_u32(pc)); + *sp++ = JS_NewInt32(ctx, get_u32(pc)); pc += 4; BREAK; CASE(OP_push_bigint_i32): @@ -16277,9 +17130,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, pc += 4; BREAK; CASE(OP_push_const): - *sp++ = js_dup(b->cpool[get_u32(pc)]); + *sp++ = JS_DupValue(ctx, b->cpool[get_u32(pc)]); pc += 4; BREAK; +#if SHORT_OPCODES CASE(OP_push_minus1): CASE(OP_push_0): CASE(OP_push_1): @@ -16289,26 +17143,26 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_push_5): CASE(OP_push_6): CASE(OP_push_7): - *sp++ = js_int32(opcode - OP_push_0); + *sp++ = JS_NewInt32(ctx, opcode - OP_push_0); BREAK; CASE(OP_push_i8): - *sp++ = js_int32(get_i8(pc)); + *sp++ = JS_NewInt32(ctx, get_i8(pc)); pc += 1; BREAK; CASE(OP_push_i16): - *sp++ = js_int32(get_i16(pc)); + *sp++ = JS_NewInt32(ctx, get_i16(pc)); pc += 2; BREAK; CASE(OP_push_const8): - *sp++ = js_dup(b->cpool[*pc++]); + *sp++ = JS_DupValue(ctx, b->cpool[*pc++]); BREAK; CASE(OP_fclosure8): - *sp++ = js_closure(ctx, js_dup(b->cpool[*pc++]), var_refs, sf); + *sp++ = js_closure(ctx, JS_DupValue(ctx, b->cpool[*pc++]), var_refs, sf); if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; CASE(OP_push_empty_string): - *sp++ = js_empty_string(rt); + *sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string); BREAK; CASE(OP_get_length): { @@ -16322,6 +17176,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-1] = val; } BREAK; +#endif CASE(OP_push_atom_value): *sp++ = JS_AtomToValue(ctx, get_u32(pc)); pc += 4; @@ -16336,12 +17191,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, /* OP_push_this is only called at the start of a function */ { JSValue val; - if (!b->is_strict_mode) { + if (!(b->js_mode & JS_MODE_STRICT)) { uint32_t tag = JS_VALUE_GET_TAG(this_obj); if (likely(tag == JS_TAG_OBJECT)) goto normal_this; if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) { - val = js_dup(ctx->global_obj); + val = JS_DupValue(ctx, ctx->global_obj); } else { val = JS_ToObject(ctx, this_obj); if (JS_IsException(val)) @@ -16349,7 +17204,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } } else { normal_this: - val = js_dup(this_obj); + val = JS_DupValue(ctx, this_obj); } *sp++ = val; } @@ -16370,21 +17225,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int arg = *pc++; switch(arg) { case OP_SPECIAL_OBJECT_ARGUMENTS: - *sp++ = js_build_arguments(ctx, argc, argv); + *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS: - *sp++ = js_build_mapped_arguments(ctx, argc, argv, + *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv, sf, min_int(argc, b->arg_count)); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_THIS_FUNC: - *sp++ = js_dup(sf->cur_func); + *sp++ = JS_DupValue(ctx, sf->cur_func); break; case OP_SPECIAL_OBJECT_NEW_TARGET: - *sp++ = js_dup(new_target); + *sp++ = JS_DupValue(ctx, new_target); break; case OP_SPECIAL_OBJECT_HOME_OBJECT: { @@ -16393,7 +17248,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(!p1)) *sp++ = JS_UNDEFINED; else - *sp++ = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); + *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); } break; case OP_SPECIAL_OBJECT_VAR_OBJECT: @@ -16406,11 +17261,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(JS_IsException(sp[-1]))) goto exception; break; - case OP_SPECIAL_OBJECT_NULL_PROTO: - *sp++ = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OBJECT); - if (unlikely(JS_IsException(sp[-1]))) - goto exception; - break; default: abort(); } @@ -16418,11 +17268,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_rest): { - int i, n, first = get_u16(pc); + int first = get_u16(pc); pc += 2; - i = min_int(first, argc); - n = argc - i; - *sp++ = js_create_array(ctx, n, &argv[i]); + first = min_int(first, argc); + *sp++ = js_create_array(ctx, argc - first, (JSValueConst *)(argv + first)); if (unlikely(JS_IsException(sp[-1]))) goto exception; } @@ -16444,36 +17293,36 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; BREAK; CASE(OP_dup): - sp[0] = js_dup(sp[-1]); + sp[0] = JS_DupValue(ctx, sp[-1]); sp++; BREAK; CASE(OP_dup2): /* a b -> a b a b */ - sp[0] = js_dup(sp[-2]); - sp[1] = js_dup(sp[-1]); + sp[0] = JS_DupValue(ctx, sp[-2]); + sp[1] = JS_DupValue(ctx, sp[-1]); sp += 2; BREAK; CASE(OP_dup3): /* a b c -> a b c a b c */ - sp[0] = js_dup(sp[-3]); - sp[1] = js_dup(sp[-2]); - sp[2] = js_dup(sp[-1]); + sp[0] = JS_DupValue(ctx, sp[-3]); + sp[1] = JS_DupValue(ctx, sp[-2]); + sp[2] = JS_DupValue(ctx, sp[-1]); sp += 3; BREAK; CASE(OP_dup1): /* a b -> a a b */ sp[0] = sp[-1]; - sp[-1] = js_dup(sp[-2]); + sp[-1] = JS_DupValue(ctx, sp[-2]); sp++; BREAK; CASE(OP_insert2): /* obj a -> a obj a (dup_x1) */ sp[0] = sp[-1]; sp[-1] = sp[-2]; - sp[-2] = js_dup(sp[0]); + sp[-2] = JS_DupValue(ctx, sp[0]); sp++; BREAK; CASE(OP_insert3): /* obj prop a -> a obj prop a (dup_x2) */ sp[0] = sp[-1]; sp[-1] = sp[-2]; sp[-2] = sp[-3]; - sp[-3] = js_dup(sp[0]); + sp[-3] = JS_DupValue(ctx, sp[0]); sp++; BREAK; CASE(OP_insert4): /* this obj prop a -> a this obj prop a */ @@ -16481,7 +17330,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-1] = sp[-2]; sp[-2] = sp[-3]; sp[-3] = sp[-4]; - sp[-4] = js_dup(sp[0]); + sp[-4] = JS_DupValue(ctx, sp[0]); sp++; BREAK; CASE(OP_perm3): /* obj a b -> a obj b (213) */ @@ -16572,19 +17421,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_fclosure): { - JSValue bfunc = js_dup(b->cpool[get_u32(pc)]); + JSValue bfunc = JS_DupValue(ctx, b->cpool[get_u32(pc)]); pc += 4; *sp++ = js_closure(ctx, bfunc, var_refs, sf); if (unlikely(JS_IsException(sp[-1]))) goto exception; } BREAK; +#if SHORT_OPCODES CASE(OP_call0): CASE(OP_call1): CASE(OP_call2): CASE(OP_call3): call_argc = opcode - OP_call0; goto has_call_argc; +#endif CASE(OP_call): CASE(OP_tail_call): { @@ -16595,8 +17446,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED, - JS_UNDEFINED, call_argc, - vc(call_argv), 0); + JS_UNDEFINED, call_argc, call_argv, 0); if (unlikely(JS_IsException(ret_val))) goto exception; if (opcode == OP_tail_call) @@ -16614,8 +17464,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallConstructorInternal(ctx, call_argv[-2], - call_argv[-1], call_argc, - vc(call_argv), 0); + call_argv[-1], + call_argc, call_argv, 0); if (unlikely(JS_IsException(ret_val))) goto exception; for(i = -2; i < call_argc; i++) @@ -16632,8 +17482,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, call_argv = sp - call_argc; sf->cur_pc = pc; ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2], - JS_UNDEFINED, call_argc, - vc(call_argv), 0); + JS_UNDEFINED, call_argc, call_argv, 0); if (unlikely(JS_IsException(ret_val))) goto exception; if (opcode == OP_tail_call_method) @@ -16645,16 +17494,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_array_from): - { - call_argc = get_u16(pc); - pc += 2; - call_argv = sp - call_argc; - ret_val = JS_NewArrayFrom(ctx, call_argc, call_argv); - sp -= call_argc; - if (unlikely(JS_IsException(ret_val))) - goto exception; - *sp++ = ret_val; - } + call_argc = get_u16(pc); + pc += 2; + ret_val = js_create_array_free(ctx, call_argc, sp - call_argc); + sp -= call_argc; + if (unlikely(JS_IsException(ret_val))) + goto exception; + *sp++ = ret_val; BREAK; CASE(OP_apply): @@ -16664,7 +17510,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, pc += 2; sf->cur_pc = pc; - ret_val = js_function_apply(ctx, sp[-3], 2, vc(&sp[-2]), magic); + ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic); if (unlikely(JS_IsException(ret_val))) goto exception; JS_FreeValue(ctx, sp[-3]); @@ -16682,7 +17528,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto done; CASE(OP_check_ctor_return): - /* return true if 'this' should be returned */ + /* return TRUE if 'this' should be returned */ if (!JS_IsObject(sp[-1])) { if (!JS_IsUndefined(sp[-1])) { JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined"); @@ -16710,7 +17556,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, super = JS_GetPrototype(ctx, func_obj); if (JS_IsException(super)) goto exception; - ret = JS_CallConstructor2(ctx, super, new_target, argc, argv); + ret = JS_CallConstructor2(ctx, super, new_target, argc, (JSValueConst *)argv); JS_FreeValue(ctx, super); if (JS_IsException(ret)) goto exception; @@ -16773,10 +17619,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_eval): { - JSValue obj; + JSValueConst obj; int scope_idx; call_argc = get_u16(pc); - scope_idx = get_u16(pc + 2) - 1; + scope_idx = get_u16(pc + 2) + ARG_SCOPE_END; pc += 4; call_argv = sp - call_argc; sf->cur_pc = pc; @@ -16789,8 +17635,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_EVAL_TYPE_DIRECT, scope_idx); } else { ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED, - JS_UNDEFINED, call_argc, - vc(call_argv), 0); + JS_UNDEFINED, call_argc, call_argv, 0); } if (unlikely(JS_IsException(ret_val))) goto exception; @@ -16806,9 +17651,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int scope_idx; uint32_t len; JSValue *tab; - JSValue obj; + JSValueConst obj; - scope_idx = get_u16(pc) - 1; + scope_idx = get_u16(pc) + ARG_SCOPE_END; pc += 2; sf->cur_pc = pc; tab = build_arg_list(ctx, &len, sp[-1]); @@ -16822,7 +17667,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj, JS_EVAL_TYPE_DIRECT, scope_idx); } else { - ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len, vc(tab)); + ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len, + (JSValueConst *)tab); } free_arg_list(ctx, tab, len); if (unlikely(JS_IsException(ret_val))) @@ -16845,6 +17691,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_super): { JSValue proto; + sf->cur_pc = pc; proto = JS_GetPrototype(ctx, sp[-1]); if (JS_IsException(proto)) goto exception; @@ -16857,28 +17704,16 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; sf->cur_pc = pc; - val = js_dynamic_import(ctx, sp[-1]); + val = js_dynamic_import(ctx, sp[-2], sp[-1]); if (JS_IsException(val)) goto exception; + JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-1]); + sp--; sp[-1] = val; } BREAK; - CASE(OP_check_var): - { - int ret; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - - ret = JS_CheckGlobalVar(ctx, atom); - if (ret < 0) - goto exception; - *sp++ = js_bool(ret); - } - BREAK; - CASE(OP_get_var_undef): CASE(OP_get_var): { @@ -16911,26 +17746,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; - CASE(OP_put_var_strict): - { - int ret; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - sf->cur_pc = pc; - - /* sp[-2] is JS_TRUE or JS_FALSE */ - if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) { - JS_ThrowReferenceErrorNotDefined(ctx, atom); - goto exception; - } - ret = JS_SetGlobalVar(ctx, atom, sp[-1], 2); - sp -= 2; - if (unlikely(ret < 0)) - goto exception; - } - BREAK; - CASE(OP_check_define_var): { JSAtom atom; @@ -16938,6 +17753,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_CheckDefineGlobalVar(ctx, atom, flags)) goto exception; } @@ -16949,6 +17765,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_DefineGlobalVar(ctx, atom, flags)) goto exception; } @@ -16960,6 +17777,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_DefineGlobalFunction(ctx, atom, sp[-1], flags)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -16972,7 +17790,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - sp[0] = js_dup(var_buf[idx]); + sp[0] = JS_DupValue(ctx, var_buf[idx]); sp++; } BREAK; @@ -16990,7 +17808,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - set_value(ctx, &var_buf[idx], js_dup(sp[-1])); + set_value(ctx, &var_buf[idx], JS_DupValue(ctx, sp[-1])); } BREAK; CASE(OP_get_arg): @@ -16998,7 +17816,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - sp[0] = js_dup(arg_buf[idx]); + sp[0] = JS_DupValue(ctx, arg_buf[idx]); sp++; } BREAK; @@ -17016,58 +17834,52 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - set_value(ctx, &arg_buf[idx], js_dup(sp[-1])); + set_value(ctx, &arg_buf[idx], JS_DupValue(ctx, sp[-1])); } BREAK; - CASE(OP_get_loc8): *sp++ = js_dup(var_buf[*pc++]); BREAK; +#if SHORT_OPCODES + CASE(OP_get_loc8): *sp++ = JS_DupValue(ctx, var_buf[*pc++]); BREAK; CASE(OP_put_loc8): set_value(ctx, &var_buf[*pc++], *--sp); BREAK; - CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], js_dup(sp[-1])); BREAK; - - // Observation: get_loc0 and get_loc1 are individually very - // frequent opcodes _and_ they are very often paired together, - // making them ideal candidates for opcode fusion. - CASE(OP_get_loc0_loc1): - *sp++ = js_dup(var_buf[0]); - *sp++ = js_dup(var_buf[1]); - BREAK; + CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], JS_DupValue(ctx, sp[-1])); BREAK; - CASE(OP_get_loc0): *sp++ = js_dup(var_buf[0]); BREAK; - CASE(OP_get_loc1): *sp++ = js_dup(var_buf[1]); BREAK; - CASE(OP_get_loc2): *sp++ = js_dup(var_buf[2]); BREAK; - CASE(OP_get_loc3): *sp++ = js_dup(var_buf[3]); BREAK; + CASE(OP_get_loc0): *sp++ = JS_DupValue(ctx, var_buf[0]); BREAK; + CASE(OP_get_loc1): *sp++ = JS_DupValue(ctx, var_buf[1]); BREAK; + CASE(OP_get_loc2): *sp++ = JS_DupValue(ctx, var_buf[2]); BREAK; + CASE(OP_get_loc3): *sp++ = JS_DupValue(ctx, var_buf[3]); BREAK; CASE(OP_put_loc0): set_value(ctx, &var_buf[0], *--sp); BREAK; CASE(OP_put_loc1): set_value(ctx, &var_buf[1], *--sp); BREAK; CASE(OP_put_loc2): set_value(ctx, &var_buf[2], *--sp); BREAK; CASE(OP_put_loc3): set_value(ctx, &var_buf[3], *--sp); BREAK; - CASE(OP_set_loc0): set_value(ctx, &var_buf[0], js_dup(sp[-1])); BREAK; - CASE(OP_set_loc1): set_value(ctx, &var_buf[1], js_dup(sp[-1])); BREAK; - CASE(OP_set_loc2): set_value(ctx, &var_buf[2], js_dup(sp[-1])); BREAK; - CASE(OP_set_loc3): set_value(ctx, &var_buf[3], js_dup(sp[-1])); BREAK; - CASE(OP_get_arg0): *sp++ = js_dup(arg_buf[0]); BREAK; - CASE(OP_get_arg1): *sp++ = js_dup(arg_buf[1]); BREAK; - CASE(OP_get_arg2): *sp++ = js_dup(arg_buf[2]); BREAK; - CASE(OP_get_arg3): *sp++ = js_dup(arg_buf[3]); BREAK; + CASE(OP_set_loc0): set_value(ctx, &var_buf[0], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_loc1): set_value(ctx, &var_buf[1], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_loc2): set_value(ctx, &var_buf[2], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_loc3): set_value(ctx, &var_buf[3], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_get_arg0): *sp++ = JS_DupValue(ctx, arg_buf[0]); BREAK; + CASE(OP_get_arg1): *sp++ = JS_DupValue(ctx, arg_buf[1]); BREAK; + CASE(OP_get_arg2): *sp++ = JS_DupValue(ctx, arg_buf[2]); BREAK; + CASE(OP_get_arg3): *sp++ = JS_DupValue(ctx, arg_buf[3]); BREAK; CASE(OP_put_arg0): set_value(ctx, &arg_buf[0], *--sp); BREAK; CASE(OP_put_arg1): set_value(ctx, &arg_buf[1], *--sp); BREAK; CASE(OP_put_arg2): set_value(ctx, &arg_buf[2], *--sp); BREAK; CASE(OP_put_arg3): set_value(ctx, &arg_buf[3], *--sp); BREAK; - CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], js_dup(sp[-1])); BREAK; - CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], js_dup(sp[-1])); BREAK; - CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], js_dup(sp[-1])); BREAK; - CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], js_dup(sp[-1])); BREAK; - CASE(OP_get_var_ref0): *sp++ = js_dup(*var_refs[0]->pvalue); BREAK; - CASE(OP_get_var_ref1): *sp++ = js_dup(*var_refs[1]->pvalue); BREAK; - CASE(OP_get_var_ref2): *sp++ = js_dup(*var_refs[2]->pvalue); BREAK; - CASE(OP_get_var_ref3): *sp++ = js_dup(*var_refs[3]->pvalue); BREAK; + CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_get_var_ref0): *sp++ = JS_DupValue(ctx, *var_refs[0]->pvalue); BREAK; + CASE(OP_get_var_ref1): *sp++ = JS_DupValue(ctx, *var_refs[1]->pvalue); BREAK; + CASE(OP_get_var_ref2): *sp++ = JS_DupValue(ctx, *var_refs[2]->pvalue); BREAK; + CASE(OP_get_var_ref3): *sp++ = JS_DupValue(ctx, *var_refs[3]->pvalue); BREAK; CASE(OP_put_var_ref0): set_value(ctx, var_refs[0]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref1): set_value(ctx, var_refs[1]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref2): set_value(ctx, var_refs[2]->pvalue, *--sp); BREAK; CASE(OP_put_var_ref3): set_value(ctx, var_refs[3]->pvalue, *--sp); BREAK; - CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, js_dup(sp[-1])); BREAK; - CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, js_dup(sp[-1])); BREAK; - CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, js_dup(sp[-1])); BREAK; - CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, js_dup(sp[-1])); BREAK; + CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK; +#endif CASE(OP_get_var_ref): { @@ -17076,7 +17888,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; val = *var_refs[idx]->pvalue; - sp[0] = js_dup(val); + sp[0] = JS_DupValue(ctx, val); sp++; } BREAK; @@ -17094,7 +17906,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - set_value(ctx, var_refs[idx]->pvalue, js_dup(sp[-1])); + set_value(ctx, var_refs[idx]->pvalue, JS_DupValue(ctx, sp[-1])); } BREAK; CASE(OP_get_var_ref_check): @@ -17105,10 +17917,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, pc += 2; val = *var_refs[idx]->pvalue; if (unlikely(JS_IsUninitialized(val))) { - JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); + JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE); goto exception; } - sp[0] = js_dup(val); + sp[0] = JS_DupValue(ctx, val); sp++; } BREAK; @@ -17118,7 +17930,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) { - JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); + JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE); goto exception; } set_value(ctx, var_refs[idx]->pvalue, sp[-1]); @@ -17131,7 +17943,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) { - JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, true); + JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE); goto exception; } set_value(ctx, var_refs[idx]->pvalue, sp[-1]); @@ -17152,11 +17964,23 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(var_buf[idx]))) { - JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, - false); + JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE); goto exception; } - sp[0] = js_dup(var_buf[idx]); + sp[0] = JS_DupValue(ctx, var_buf[idx]); + sp++; + } + BREAK; + CASE(OP_get_loc_checkthis): + { + int idx; + idx = get_u16(pc); + pc += 2; + if (unlikely(JS_IsUninitialized(var_buf[idx]))) { + JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, FALSE); + goto exception; + } + sp[0] = JS_DupValue(ctx, var_buf[idx]); sp++; } BREAK; @@ -17166,8 +17990,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; if (unlikely(JS_IsUninitialized(var_buf[idx]))) { - JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, - false); + JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); @@ -17180,8 +18003,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, idx = get_u16(pc); pc += 2; if (unlikely(!JS_IsUninitialized(var_buf[idx]))) { - JS_ThrowReferenceError(caller_ctx, - "'this' can be initialized only once"); + JS_ThrowReferenceError(ctx, "'this' can be initialized only once"); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); @@ -17234,6 +18056,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; if (JS_GetGlobalVarRef(ctx, atom, sp)) goto exception; @@ -17246,6 +18069,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(js_poll_interrupts(ctx))) goto exception; BREAK; +#if SHORT_OPCODES CASE(OP_goto16): pc += (int16_t)get_u16(pc); if (unlikely(js_poll_interrupts(ctx))) @@ -17256,6 +18080,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(js_poll_interrupts(ctx))) goto exception; BREAK; +#endif CASE(OP_if_true): { int res; @@ -17283,6 +18108,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op1 = sp[-1]; pc += 4; + /* quick and dirty test for JS_TAG_INT, JS_TAG_BOOL, JS_TAG_NULL and JS_TAG_UNDEFINED */ if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) { res = JS_VALUE_GET_INT(op1); } else { @@ -17296,6 +18122,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } BREAK; +#if SHORT_OPCODES CASE(OP_if_true8): { int res; @@ -17336,6 +18163,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } BREAK; +#endif CASE(OP_catch): { int32_t diff; @@ -17350,7 +18178,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int32_t diff; diff = get_u32(pc); /* XXX: should have a different tag to avoid security flaw */ - sp[0] = js_int32(pc + 4 - b->byte_code_buf); + sp[0] = JS_NewInt32(ctx, pc + 4 - b->byte_code_buf); sp++; pc += diff; } @@ -17386,7 +18214,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_for_of_start): sf->cur_pc = pc; - if (js_for_of_start(ctx, sp, false)) + if (js_for_of_start(ctx, sp, FALSE)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); @@ -17401,9 +18229,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp += 2; } BREAK; + CASE(OP_for_await_of_next): + sf->cur_pc = pc; + if (js_for_await_of_next(ctx, sp)) + goto exception; + sp++; + BREAK; CASE(OP_for_await_of_start): sf->cur_pc = pc; - if (js_for_of_start(ctx, sp, true)) + if (js_for_of_start(ctx, sp, TRUE)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); @@ -17428,7 +18262,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; if (!JS_IsUndefined(sp[-1])) { sf->cur_pc = pc; - if (JS_IteratorClose(ctx, sp[-1], false)) + if (JS_IteratorClose(ctx, sp[-1], FALSE)) goto exception; JS_FreeValue(ctx, sp[-1]); } @@ -17457,7 +18291,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue ret; sf->cur_pc = pc; - ret = JS_Call(ctx, sp[-3], sp[-4], 1, vc(sp - 1)); + ret = JS_Call(ctx, sp[-3], sp[-4], + 1, (JSValueConst *)(sp - 1)); if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -17469,7 +18304,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, /* stack: iter_obj next catch_offset val */ { JSValue method, ret; - bool ret_flag; + BOOL ret_flag; int flags; flags = *pc++; sf->cur_pc = pc; @@ -17478,7 +18313,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (JS_IsException(method)) goto exception; if (JS_IsUndefined(method) || JS_IsNull(method)) { - ret_flag = true; + ret_flag = TRUE; } else { if (flags & 2) { /* no argument */ @@ -17486,15 +18321,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, 0, NULL); } else { ret = JS_CallFree(ctx, method, sp[-4], - 1, vc(sp - 1)); + 1, (JSValueConst *)(sp - 1)); } if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret; - ret_flag = false; + ret_flag = FALSE; } - sp[0] = js_bool(ret_flag); + sp[0] = JS_NewBool(ctx, ret_flag); sp += 1; } BREAK; @@ -17510,54 +18345,108 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } else { res = JS_ToBoolFree(ctx, op1); } - sp[-1] = js_bool(!res); + sp[-1] = JS_NewBool(ctx, !res); } BREAK; - CASE(OP_get_field): - { - JSValue val; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - sf->cur_pc = pc; - val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); - if (unlikely(JS_IsException(val))) - goto exception; - JS_FreeValue(ctx, sp[-1]); - sp[-1] = val; +#define GET_FIELD_INLINE(name, keep) \ + { \ + JSValue val, obj; \ + JSAtom atom; \ + JSObject *p; \ + JSProperty *pr; \ + JSShapeProperty *prs; \ + \ + atom = get_u32(pc); \ + pc += 4; \ + \ + obj = sp[-1]; \ + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { \ + p = JS_VALUE_GET_OBJ(obj); \ + for(;;) { \ + prs = find_own_property(&pr, p, atom); \ + if (prs) { \ + /* found */ \ + if (unlikely(prs->flags & JS_PROP_TMASK)) \ + goto name ## _slow_path; \ + val = JS_DupValue(ctx, pr->u.value); \ + break; \ + } \ + if (unlikely(p->is_exotic)) { \ + /* XXX: should avoid the slow path for arrays \ + and typed arrays by ensuring that 'prop' is \ + not numeric */ \ + obj = JS_MKPTR(JS_TAG_OBJECT, p); \ + goto name ## _slow_path; \ + } \ + p = p->shape->proto; \ + if (!p) { \ + val = JS_UNDEFINED; \ + break; \ + } \ + } \ + } else { \ + name ## _slow_path: \ + sf->cur_pc = pc; \ + val = JS_GetPropertyInternal(ctx, obj, atom, sp[-1], 0); \ + if (unlikely(JS_IsException(val))) \ + goto exception; \ + } \ + if (keep) { \ + *sp++ = val; \ + } else { \ + JS_FreeValue(ctx, sp[-1]); \ + sp[-1] = val; \ + } \ } + + + CASE(OP_get_field): + GET_FIELD_INLINE(get_field, 0); BREAK; CASE(OP_get_field2): - { - JSValue val; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - sf->cur_pc = pc; - val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); - if (unlikely(JS_IsException(val))) - goto exception; - *sp++ = val; - } - BREAK; + GET_FIELD_INLINE(get_field2, 1); + BREAK; CASE(OP_put_field): { int ret; + JSValue obj; JSAtom atom; + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; + atom = get_u32(pc); pc += 4; - sf->cur_pc = pc; - ret = JS_SetPropertyInternal2(ctx, - sp[-2], atom, - sp[-1], sp[-2], - JS_PROP_THROW_STRICT); - JS_FreeValue(ctx, sp[-2]); - sp -= 2; - if (unlikely(ret < 0)) - goto exception; + + obj = sp[-2]; + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, atom); + if (!prs) + goto put_field_slow_path; + if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | + JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { + /* fast path */ + set_value(ctx, &pr->u.value, sp[-1]); + } else { + goto put_field_slow_path; + } + JS_FreeValue(ctx, obj); + sp -= 2; + } else { + put_field_slow_path: + sf->cur_pc = pc; + ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-1], obj, + JS_PROP_THROW_STRICT); + JS_FreeValue(ctx, obj); + sp -= 2; + if (unlikely(ret < 0)) + goto exception; + } + } BREAK; @@ -17578,7 +18467,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_private_field): { JSValue val; - sf->cur_pc = pc; + val = JS_GetPrivateField(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-1]); JS_FreeValue(ctx, sp[-2]); @@ -17592,7 +18481,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_put_private_field): { int ret; - sf->cur_pc = pc; ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]); JS_FreeValue(ctx, sp[-3]); JS_FreeValue(ctx, sp[-1]); @@ -17651,9 +18539,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_set_proto): { JSValue proto; + sf->cur_pc = pc; proto = sp[-1]; if (JS_IsObject(proto) || JS_IsNull(proto)) { - if (JS_SetPrototypeInternal(ctx, sp[-2], proto, true) < 0) + if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0) goto exception; } JS_FreeValue(ctx, proto); @@ -17667,10 +18556,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_define_method_computed): { JSValue getter, setter, value; - JSValue obj; + JSValueConst obj; JSAtom atom; int flags, ret, op_flags; - bool is_computed; + BOOL is_computed; #define OP_DEFINE_METHOD_METHOD 0 #define OP_DEFINE_METHOD_GETTER 1 #define OP_DEFINE_METHOD_SETTER 2 @@ -17739,46 +18628,129 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; - CASE(OP_get_array_el): - { - JSValue val; - - sf->cur_pc = pc; - val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); - JS_FreeValue(ctx, sp[-2]); - sp[-2] = val; - sp--; - if (unlikely(JS_IsException(val))) - goto exception; +#define GET_ARRAY_EL_INLINE(name, keep) \ + { \ + JSValue val, obj, prop; \ + JSObject *p; \ + uint32_t idx; \ + \ + obj = sp[-2]; \ + prop = sp[-1]; \ + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT && \ + JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) { \ + p = JS_VALUE_GET_OBJ(obj); \ + idx = JS_VALUE_GET_INT(prop); \ + if (unlikely(p->class_id != JS_CLASS_ARRAY)) \ + goto name ## _slow_path; \ + if (unlikely(idx >= p->u.array.count)) \ + goto name ## _slow_path; \ + val = JS_DupValue(ctx, p->u.array.u.values[idx]); \ + } else { \ + name ## _slow_path: \ + sf->cur_pc = pc; \ + val = JS_GetPropertyValue(ctx, obj, prop); \ + if (unlikely(JS_IsException(val))) { \ + if (keep) \ + sp[-1] = JS_UNDEFINED; \ + else \ + sp--; \ + goto exception; \ + } \ + } \ + if (keep) { \ + sp[-1] = val; \ + } else { \ + JS_FreeValue(ctx, obj); \ + sp[-2] = val; \ + sp--; \ + } \ } + + CASE(OP_get_array_el): + GET_ARRAY_EL_INLINE(get_array_el, 0); BREAK; CASE(OP_get_array_el2): + GET_ARRAY_EL_INLINE(get_array_el2, 1); + BREAK; + + CASE(OP_get_array_el3): { JSValue val; + JSObject *p; + uint32_t idx; - sf->cur_pc = pc; - val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); - sp[-1] = val; - if (unlikely(JS_IsException(val))) - goto exception; + if (likely(JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT && + JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_INT)) { + p = JS_VALUE_GET_OBJ(sp[-2]); + idx = JS_VALUE_GET_INT(sp[-1]); + if (unlikely(p->class_id != JS_CLASS_ARRAY)) + goto get_array_el3_slow_path; + if (unlikely(idx >= p->u.array.count)) + goto get_array_el3_slow_path; + val = JS_DupValue(ctx, p->u.array.u.values[idx]); + } else { + get_array_el3_slow_path: + switch (JS_VALUE_GET_TAG(sp[-1])) { + case JS_TAG_INT: + case JS_TAG_STRING: + case JS_TAG_SYMBOL: + /* undefined and null are tested in JS_GetPropertyValue() */ + break; + default: + /* must be tested before JS_ToPropertyKey */ + if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) { + JS_ThrowTypeError(ctx, "value has no property"); + goto exception; + } + sf->cur_pc = pc; + ret_val = JS_ToPropertyKey(ctx, sp[-1]); + if (JS_IsException(ret_val)) + goto exception; + JS_FreeValue(ctx, sp[-1]); + sp[-1] = ret_val; + break; + } + sf->cur_pc = pc; + val = JS_GetPropertyValue(ctx, sp[-2], JS_DupValue(ctx, sp[-1])); + if (unlikely(JS_IsException(val))) + goto exception; + } + *sp++ = val; } BREAK; - + CASE(OP_get_ref_value): { JSValue val; + JSAtom atom; + int ret; + sf->cur_pc = pc; + atom = JS_ValueToAtom(ctx, sp[-1]); + if (atom == JS_ATOM_NULL) + goto exception; if (unlikely(JS_IsUndefined(sp[-2]))) { - JSAtom atom = JS_ValueToAtom(ctx, sp[-1]); - if (atom != JS_ATOM_NULL) { - JS_ThrowReferenceErrorNotDefined(ctx, atom); + JS_ThrowReferenceErrorNotDefined(ctx, atom); + JS_FreeAtom(ctx, atom); + goto exception; + } + ret = JS_HasProperty(ctx, sp[-2], atom); + if (unlikely(ret <= 0)) { + if (ret < 0) { JS_FreeAtom(ctx, atom); + goto exception; } - goto exception; + if (is_strict_mode(ctx)) { + JS_ThrowReferenceErrorNotDefined(ctx, atom); + JS_FreeAtom(ctx, atom); + goto exception; + } + val = JS_UNDEFINED; + } else { + val = JS_GetProperty(ctx, sp[-2], atom); } - val = JS_GetPropertyValue(ctx, sp[-2], - js_dup(sp[-1])); + JS_FreeAtom(ctx, atom); if (unlikely(JS_IsException(val))) goto exception; sp[0] = val; @@ -17794,7 +18766,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = JS_ValueToAtom(ctx, sp[-1]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; - val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], false); + val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], FALSE); JS_FreeAtom(ctx, atom); if (unlikely(JS_IsException(val))) goto exception; @@ -17809,36 +18781,87 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_put_array_el): { int ret; - sf->cur_pc = pc; - ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); - JS_FreeValue(ctx, sp[-3]); - sp -= 3; - if (unlikely(ret < 0)) - goto exception; + JSObject *p; + uint32_t idx; + + if (likely(JS_VALUE_GET_TAG(sp[-3]) == JS_TAG_OBJECT && + JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_INT)) { + p = JS_VALUE_GET_OBJ(sp[-3]); + idx = JS_VALUE_GET_INT(sp[-2]); + if (unlikely(p->class_id != JS_CLASS_ARRAY)) + goto put_array_el_slow_path; + if (unlikely(idx >= (uint32_t)p->u.array.count)) { + uint32_t new_len, array_len; + if (unlikely(idx != (uint32_t)p->u.array.count || + !p->fast_array || + !p->extensible || + p->shape->proto != JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) || + !ctx->std_array_prototype)) { + goto put_array_el_slow_path; + } + if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) != JS_TAG_INT)) + goto put_array_el_slow_path; + /* cannot overflow otherwise the length would not be an integer */ + new_len = idx + 1; + if (unlikely(new_len > p->u.array.u1.size)) + goto put_array_el_slow_path; + array_len = JS_VALUE_GET_INT(p->prop[0].u.value); + if (new_len > array_len) { + if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) + goto put_array_el_slow_path; + p->prop[0].u.value = JS_NewInt32(ctx, new_len); + } + p->u.array.count = new_len; + p->u.array.u.values[idx] = sp[-1]; + } else { + set_value(ctx, &p->u.array.u.values[idx], sp[-1]); + } + JS_FreeValue(ctx, sp[-3]); + sp -= 3; + } else { + put_array_el_slow_path: + sf->cur_pc = pc; + ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); + JS_FreeValue(ctx, sp[-3]); + sp -= 3; + if (unlikely(ret < 0)) + goto exception; + } } BREAK; CASE(OP_put_ref_value): { - int ret, flags; + int ret; + JSAtom atom; sf->cur_pc = pc; - flags = JS_PROP_THROW_STRICT; + atom = JS_ValueToAtom(ctx, sp[-2]); + if (unlikely(atom == JS_ATOM_NULL)) + goto exception; if (unlikely(JS_IsUndefined(sp[-3]))) { if (is_strict_mode(ctx)) { - JSAtom atom = JS_ValueToAtom(ctx, sp[-2]); - if (atom != JS_ATOM_NULL) { - JS_ThrowReferenceErrorNotDefined(ctx, atom); - JS_FreeAtom(ctx, atom); - } + JS_ThrowReferenceErrorNotDefined(ctx, atom); + JS_FreeAtom(ctx, atom); goto exception; } else { - sp[-3] = js_dup(ctx->global_obj); + sp[-3] = JS_DupValue(ctx, ctx->global_obj); } - } else { - if (is_strict_mode(ctx)) - flags |= JS_PROP_NO_ADD; } - ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], flags); + ret = JS_HasProperty(ctx, sp[-3], atom); + if (unlikely(ret <= 0)) { + if (unlikely(ret < 0)) { + JS_FreeAtom(ctx, atom); + goto exception; + } + if (is_strict_mode(ctx)) { + JS_ThrowReferenceErrorNotDefined(ctx, atom); + JS_FreeAtom(ctx, atom); + goto exception; + } + } + ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-3], JS_PROP_THROW_STRICT); + JS_FreeAtom(ctx, atom); + JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-3]); sp -= 3; if (unlikely(ret < 0)) @@ -17858,10 +18881,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; - ret = JS_SetPropertyInternal2(ctx, - sp[-3], atom, - sp[-1], sp[-4], - JS_PROP_THROW_STRICT); + ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-4], + JS_PROP_THROW_STRICT); JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, sp[-4]); JS_FreeValue(ctx, sp[-3]); @@ -17875,7 +18896,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_define_array_el): { int ret; - ret = JS_DefinePropertyValueValue(ctx, sp[-3], js_dup(sp[-2]), sp[-1], + ret = JS_DefinePropertyValueValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1], JS_PROP_C_W_E | JS_PROP_THROW); sp -= 1; if (unlikely(ret < 0)) @@ -17919,12 +18940,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto add_slow; - sp[-2] = js_int32(r); + sp[-2] = JS_NewInt32(ctx, r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) + - JS_VALUE_GET_FLOAT64(op2)); + sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + + JS_VALUE_GET_FLOAT64(op2)); + sp--; + } else if (JS_IsString(op1) && JS_IsString(op2)) { + sp[-2] = JS_ConcatString(ctx, op1, op2); sp--; + if (JS_IsException(sp[-1])) + goto exception; } else { add_slow: sf->cur_pc = pc; @@ -17936,40 +18962,45 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_add_loc): { + JSValue op2; JSValue *pv; int idx; idx = *pc; pc += 1; + op2 = sp[-1]; pv = &var_buf[idx]; - if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) { + if (likely(JS_VALUE_IS_BOTH_INT(*pv, op2))) { int64_t r; - r = (int64_t)JS_VALUE_GET_INT(*pv) + - JS_VALUE_GET_INT(sp[-1]); + r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto add_loc_slow; - *pv = js_int32(r); + *pv = JS_NewInt32(ctx, r); + sp--; + } else if (JS_VALUE_IS_BOTH_FLOAT(*pv, op2)) { + *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) + + JS_VALUE_GET_FLOAT64(op2)); sp--; - } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { - JSValue op1; - op1 = sp[-1]; + } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING && + JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { sp--; sf->cur_pc = pc; - op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); - if (JS_IsException(op1)) - goto exception; - op1 = JS_ConcatString(ctx, js_dup(*pv), op1); - if (JS_IsException(op1)) - goto exception; - set_value(ctx, pv, op1); + if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) { + JS_FreeValue(ctx, op2); + } else { + op2 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op2); + if (JS_IsException(op2)) + goto exception; + set_value(ctx, pv, op2); + } } else { JSValue ops[2]; add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ sf->cur_pc = pc; - ops[0] = js_dup(*pv); - ops[1] = sp[-1]; + ops[0] = JS_DupValue(ctx, *pv); + ops[1] = op2; sp--; if (js_add_slow(ctx, ops + 2)) goto exception; @@ -17987,11 +19018,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto binary_arith_slow; - sp[-2] = js_int32(r); + sp[-2] = JS_NewInt32(ctx, r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) - - JS_VALUE_GET_FLOAT64(op2)); + sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) - + JS_VALUE_GET_FLOAT64(op2)); sp--; } else { goto binary_arith_slow; @@ -18019,12 +19050,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, d = -0.0; goto mul_fp_res; } - sp[-2] = js_int32(r); + sp[-2] = JS_NewInt32(ctx, r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2); mul_fp_res: - sp[-2] = js_float64(d); + sp[-2] = __JS_NewFloat64(ctx, d); sp--; } else { goto binary_arith_slow; @@ -18040,7 +19071,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int v1, v2; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); - sp[-2] = js_number((double)v1 / (double)v2); + sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2); sp--; } else { goto binary_arith_slow; @@ -18061,7 +19092,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(v1 < 0 || v2 <= 0)) goto binary_arith_slow; r = v1 % v2; - sp[-2] = js_int32(r); + sp[-2] = JS_NewInt32(ctx, r); sp--; } else { goto binary_arith_slow; @@ -18109,11 +19140,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, d = -(double)val; goto neg_fp_res; } - sp[-1] = js_int32(-val); + sp[-1] = JS_NewInt32(ctx, -val); } else if (JS_TAG_IS_FLOAT64(tag)) { d = -JS_VALUE_GET_FLOAT64(op1); neg_fp_res: - sp[-1] = js_float64(d); + sp[-1] = __JS_NewFloat64(ctx, d); } else { sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) @@ -18130,7 +19161,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MAX)) goto inc_slow; - sp[-1] = js_int32(val + 1); + sp[-1] = JS_NewInt32(ctx, val + 1); } else { inc_slow: sf->cur_pc = pc; @@ -18148,7 +19179,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MIN)) goto dec_slow; - sp[-1] = js_int32(val - 1); + sp[-1] = JS_NewInt32(ctx, val - 1); } else { dec_slow: sf->cur_pc = pc; @@ -18158,11 +19189,42 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_post_inc): + { + JSValue op1; + int val; + op1 = sp[-1]; + if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + val = JS_VALUE_GET_INT(op1); + if (unlikely(val == INT32_MAX)) + goto post_inc_slow; + sp[0] = JS_NewInt32(ctx, val + 1); + } else { + post_inc_slow: + sf->cur_pc = pc; + if (js_post_inc_slow(ctx, sp, opcode)) + goto exception; + } + sp++; + } + BREAK; CASE(OP_post_dec): - sf->cur_pc = pc; - if (js_post_inc_slow(ctx, sp, opcode)) - goto exception; - sp++; + { + JSValue op1; + int val; + op1 = sp[-1]; + if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + val = JS_VALUE_GET_INT(op1); + if (unlikely(val == INT32_MIN)) + goto post_dec_slow; + sp[0] = JS_NewInt32(ctx, val - 1); + } else { + post_dec_slow: + sf->cur_pc = pc; + if (js_post_inc_slow(ctx, sp, opcode)) + goto exception; + } + sp++; + } BREAK; CASE(OP_inc_loc): { @@ -18177,13 +19239,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MAX)) goto inc_loc_slow; - var_buf[idx] = js_int32(val + 1); + var_buf[idx] = JS_NewInt32(ctx, val + 1); } else { inc_loc_slow: sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ - op1 = js_dup(op1); + op1 = JS_DupValue(ctx, op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc)) goto exception; set_value(ctx, &var_buf[idx], op1); @@ -18203,13 +19265,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, val = JS_VALUE_GET_INT(op1); if (unlikely(val == INT32_MIN)) goto dec_loc_slow; - var_buf[idx] = js_int32(val - 1); + var_buf[idx] = JS_NewInt32(ctx, val - 1); } else { dec_loc_slow: sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ - op1 = js_dup(op1); + op1 = JS_DupValue(ctx, op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec)) goto exception; set_value(ctx, &var_buf[idx], op1); @@ -18221,7 +19283,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSValue op1; op1 = sp[-1]; if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { - sp[-1] = js_int32(~JS_VALUE_GET_INT(op1)); + sp[-1] = JS_NewInt32(ctx, ~JS_VALUE_GET_INT(op1)); } else { sf->cur_pc = pc; if (js_not_slow(ctx, sp)) @@ -18238,8 +19300,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { uint32_t v1, v2; v1 = JS_VALUE_GET_INT(op1); - v2 = JS_VALUE_GET_INT(op2) & 0x1f; - sp[-2] = js_int32(v1 << v2); + v2 = JS_VALUE_GET_INT(op2); + v2 &= 0x1f; + sp[-2] = JS_NewInt32(ctx, v1 << v2); sp--; } else { sf->cur_pc = pc; @@ -18258,7 +19321,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, uint32_t v2; v2 = JS_VALUE_GET_INT(op2); v2 &= 0x1f; - sp[-2] = js_uint32((uint32_t)JS_VALUE_GET_INT(op1) >> v2); + sp[-2] = JS_NewUint32(ctx, + (uint32_t)JS_VALUE_GET_INT(op1) >> + v2); sp--; } else { sf->cur_pc = pc; @@ -18276,10 +19341,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { uint32_t v2; v2 = JS_VALUE_GET_INT(op2); - if (unlikely(v2 > 0x1f)) { - v2 &= 0x1f; - } - sp[-2] = js_int32((int)JS_VALUE_GET_INT(op1) >> v2); + v2 &= 0x1f; + sp[-2] = JS_NewInt32(ctx, + (int)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { sf->cur_pc = pc; @@ -18295,7 +19359,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { - sp[-2] = js_int32(JS_VALUE_GET_INT(op1) & JS_VALUE_GET_INT(op2)); + sp[-2] = JS_NewInt32(ctx, + JS_VALUE_GET_INT(op1) & + JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; @@ -18311,7 +19377,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { - sp[-2] = js_int32(JS_VALUE_GET_INT(op1) | JS_VALUE_GET_INT(op2)); + sp[-2] = JS_NewInt32(ctx, + JS_VALUE_GET_INT(op1) | + JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; @@ -18327,7 +19395,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op1 = sp[-2]; op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { - sp[-2] = js_int32(JS_VALUE_GET_INT(op1) ^ JS_VALUE_GET_INT(op2)); + sp[-2] = JS_NewInt32(ctx, + JS_VALUE_GET_INT(op1) ^ + JS_VALUE_GET_INT(op2)); sp--; } else { sf->cur_pc = pc; @@ -18346,7 +19416,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op1 = sp[-2]; \ op2 = sp[-1]; \ if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { \ - sp[-2] = js_bool(JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ + sp[-2] = JS_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ sp--; \ } else { \ sf->cur_pc = pc; \ @@ -18373,6 +19443,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; BREAK; CASE(OP_private_in): + sf->cur_pc = pc; if (js_operator_private_in(ctx, sp)) goto exception; sp--; @@ -18407,12 +19478,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; - sf->cur_pc = pc; + ret = JS_DeleteGlobalVar(ctx, atom); if (unlikely(ret < 0)) goto exception; - *sp++ = js_bool(ret); + *sp++ = JS_NewBool(ctx, ret); } BREAK; @@ -18444,33 +19515,22 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; - CASE(OP_to_propkey2): - /* must be tested first */ - if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) { - JS_ThrowTypeError(ctx, "value has no property"); - goto exception; - } - switch (JS_VALUE_GET_TAG(sp[-1])) { - case JS_TAG_INT: - case JS_TAG_STRING: - case JS_TAG_SYMBOL: - break; - default: - sf->cur_pc = pc; - ret_val = JS_ToPropertyKey(ctx, sp[-1]); +#if 0 + CASE(OP_to_string): + if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_STRING) { + ret_val = JS_ToString(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; JS_FreeValue(ctx, sp[-1]); sp[-1] = ret_val; - break; } BREAK; +#endif CASE(OP_with_get_var): CASE(OP_with_put_var): CASE(OP_with_delete_var): CASE(OP_with_make_ref): CASE(OP_with_get_ref): - CASE(OP_with_get_ref_undef): { JSAtom atom; int32_t diff; @@ -18496,14 +19556,35 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } switch (opcode) { case OP_with_get_var: - val = JS_GetProperty(ctx, obj, atom); - if (unlikely(JS_IsException(val))) - goto exception; + /* in Object Environment Records, GetBindingValue() calls HasProperty() */ + ret = JS_HasProperty(ctx, obj, atom); + if (unlikely(ret <= 0)) { + if (ret < 0) + goto exception; + if (is_strict_mode(ctx)) { + JS_ThrowReferenceErrorNotDefined(ctx, atom); + goto exception; + } + val = JS_UNDEFINED; + } else { + val = JS_GetProperty(ctx, obj, atom); + if (unlikely(JS_IsException(val))) + goto exception; + } set_value(ctx, &sp[-1], val); break; - case OP_with_put_var: - /* XXX: check if strict mode */ - ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], + case OP_with_put_var: /* used e.g. in for in/of */ + /* in Object Environment Records, SetMutableBinding() calls HasProperty() */ + ret = JS_HasProperty(ctx, obj, atom); + if (unlikely(ret <= 0)) { + if (ret < 0) + goto exception; + if (is_strict_mode(ctx)) { + JS_ThrowReferenceErrorNotDefined(ctx, atom); + goto exception; + } + } + ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], obj, JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-1]); sp -= 2; @@ -18515,7 +19596,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(ret < 0)) goto exception; JS_FreeValue(ctx, sp[-1]); - sp[-1] = js_bool(ret); + sp[-1] = JS_NewBool(ctx, ret); break; case OP_with_make_ref: /* produce a pair object/propname on the stack */ @@ -18523,18 +19604,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, break; case OP_with_get_ref: /* produce a pair object/method on the stack */ - val = JS_GetProperty(ctx, obj, atom); - if (unlikely(JS_IsException(val))) - goto exception; - *sp++ = val; - break; - case OP_with_get_ref_undef: - /* produce a pair undefined/function on the stack */ - val = JS_GetProperty(ctx, obj, atom); - if (unlikely(JS_IsException(val))) + /* in Object Environment Records, GetBindingValue() calls HasProperty() */ + ret = JS_HasProperty(ctx, obj, atom); + if (unlikely(ret < 0)) goto exception; - JS_FreeValue(ctx, sp[-1]); - sp[-1] = JS_UNDEFINED; + if (!ret) { + val = JS_UNDEFINED; + } else { + val = JS_GetProperty(ctx, obj, atom); + if (unlikely(JS_IsException(val))) + goto exception; + } *sp++ = val; break; } @@ -18549,19 +19629,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_await): - ret_val = js_int32(FUNC_RET_AWAIT); + ret_val = JS_NewInt32(ctx, FUNC_RET_AWAIT); goto done_generator; CASE(OP_yield): - ret_val = js_int32(FUNC_RET_YIELD); + ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD); goto done_generator; CASE(OP_yield_star): CASE(OP_async_yield_star): - ret_val = js_int32(FUNC_RET_YIELD_STAR); + ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR); goto done_generator; CASE(OP_return_async): - CASE(OP_initial_yield): ret_val = JS_UNDEFINED; goto done_generator; + CASE(OP_initial_yield): + ret_val = JS_NewInt32(ctx, FUNC_RET_INITIAL_YIELD); + goto done_generator; CASE(OP_nop): BREAK; @@ -18572,6 +19654,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } else { goto free_and_set_false; } +#if SHORT_OPCODES CASE(OP_is_undefined): if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED) { goto set_true; @@ -18600,6 +19683,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } free_and_set_true: JS_FreeValue(ctx, sp[-1]); +#endif set_true: sp[-1] = JS_TRUE; BREAK; @@ -18615,13 +19699,14 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } } exception: - if (needs_backtrace(rt->current_exception) - || JS_IsUndefined(ctx->error_back_trace)) { + if (is_backtrace_needed(ctx, rt->current_exception)) { + /* add the backtrace information now (it is not done + before if the exception happens in a bytecode + operation */ sf->cur_pc = pc; - build_backtrace(ctx, rt->current_exception, JS_UNDEFINED, - NULL, 0, 0, 0); + build_backtrace(ctx, rt->current_exception, NULL, 0, 0, 0); } - if (!JS_IsUncatchableError(ctx, rt->current_exception)) { + if (!rt->current_exception_is_uncatchable) { while (sp > stack_buf) { JSValue val = *--sp; JS_FreeValue(ctx, val); @@ -18631,12 +19716,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, /* enumerator: close it with a throw */ JS_FreeValue(ctx, sp[-1]); /* drop the next method */ sp--; - JS_IteratorClose(ctx, sp[-1], true); + JS_IteratorClose(ctx, sp[-1], TRUE); } else { *sp++ = rt->current_exception; rt->current_exception = JS_UNINITIALIZED; - JS_FreeValueRT(rt, ctx->error_back_trace); - ctx->error_back_trace = JS_UNDEFINED; pc = b->byte_code_buf + pos; goto restart; } @@ -18670,14 +19753,14 @@ JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) { return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, - argc, argv, JS_CALL_FLAG_COPY_ARGV); + argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); } static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) { JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, - argc, argv, JS_CALL_FLAG_COPY_ARGV); + argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); JS_FreeValue(ctx, func_obj); return res; } @@ -18739,7 +19822,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, JSContext *realm; if (JS_IsUndefined(ctor)) { - proto = js_dup(ctx->class_proto[class_id]); + proto = JS_DupValue(ctx, ctx->class_proto[class_id]); } else { proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype); if (JS_IsException(proto)) @@ -18749,7 +19832,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, realm = JS_GetFunctionRealm(ctx, ctor); if (!realm) return JS_EXCEPTION; - proto = js_dup(realm->class_proto[class_id]); + proto = JS_DupValue(ctx, realm->class_proto[class_id]); } } obj = JS_NewObjectProtoClass(ctx, proto, class_id); @@ -18761,8 +19844,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, static JSValue JS_CallConstructorInternal(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, - int argc, JSValueConst *argv, - int flags) + int argc, JSValue *argv, int flags) { JSObject *p; JSFunctionBytecode *b; @@ -18780,10 +19862,10 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx, call_func = ctx->rt->class_array[p->class_id].call; if (!call_func) { not_a_function: - return JS_ThrowTypeErrorNotAFunction(ctx); + return JS_ThrowTypeError(ctx, "not a function"); } return call_func(ctx, func_obj, new_target, argc, - argv, flags); + (JSValueConst *)argv, flags); } b = p->u.func.function_bytecode; @@ -18812,7 +19894,7 @@ JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, int argc, JSValueConst *argv) { return JS_CallConstructorInternal(ctx, func_obj, new_target, - argc, argv, + argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); } @@ -18820,7 +19902,7 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, int argc, JSValueConst *argv) { return JS_CallConstructorInternal(ctx, func_obj, func_obj, - argc, argv, + argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); } @@ -18843,70 +19925,57 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, } /* JSAsyncFunctionState (used by generator and async functions) */ -static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, - JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv) +static JSAsyncFunctionState *async_func_init(JSContext *ctx, + JSValueConst func_obj, JSValueConst this_obj, + int argc, JSValueConst *argv) { + JSAsyncFunctionState *s; JSObject *p; JSFunctionBytecode *b; JSStackFrame *sf; int local_count, i, arg_buf_len, n; + s = js_mallocz(ctx, sizeof(*s)); + if (!s) + return NULL; + s->header.ref_count = 1; + add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION); + sf = &s->frame; init_list_head(&sf->var_ref_list); p = JS_VALUE_GET_OBJ(func_obj); b = p->u.func.function_bytecode; - sf->is_strict_mode = b->is_strict_mode; + sf->js_mode = b->js_mode | JS_MODE_ASYNC; sf->cur_pc = b->byte_code_buf; arg_buf_len = max_int(b->arg_count, argc); local_count = arg_buf_len + b->var_count + b->stack_size; sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1)); - if (!sf->arg_buf) - return -1; - sf->cur_func = js_dup(func_obj); - s->this_val = js_dup(this_obj); + if (!sf->arg_buf) { + js_free(ctx, s); + return NULL; + } + sf->cur_func = JS_DupValue(ctx, func_obj); + s->this_val = JS_DupValue(ctx, this_obj); s->argc = argc; sf->arg_count = arg_buf_len; sf->var_buf = sf->arg_buf + arg_buf_len; sf->cur_sp = sf->var_buf + b->var_count; for(i = 0; i < argc; i++) - sf->arg_buf[i] = js_dup(argv[i]); + sf->arg_buf[i] = JS_DupValue(ctx, argv[i]); n = arg_buf_len + b->var_count; for(i = argc; i < n; i++) sf->arg_buf[i] = JS_UNDEFINED; - return 0; -} - -static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, - JS_MarkFunc *mark_func) -{ - JSStackFrame *sf; - JSValue *sp; - - sf = &s->frame; - JS_MarkValue(rt, sf->cur_func, mark_func); - JS_MarkValue(rt, s->this_val, mark_func); - if (sf->cur_sp) { - /* if the function is running, cur_sp is not known so we - cannot mark the stack. Marking the variables is not needed - because a running function cannot be part of a removable - cycle */ - for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) - JS_MarkValue(rt, *sp, mark_func); - } + s->resolving_funcs[0] = JS_UNDEFINED; + s->resolving_funcs[1] = JS_UNDEFINED; + s->is_completed = FALSE; + return s; } -static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) +static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s) { - JSStackFrame *sf; + JSStackFrame *sf = &s->frame; JSValue *sp; - sf = &s->frame; - - /* close the closure variables. */ - close_var_refs(rt, sf); - if (sf->arg_buf) { /* cannot free the function if it is running */ assert(sf->cur_sp != NULL); @@ -18914,6 +19983,7 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) JS_FreeValueRT(rt, *sp); } js_free_rt(rt, sf->arg_buf); + sf->arg_buf = NULL; } JS_FreeValueRT(rt, sf->cur_func); JS_FreeValueRT(rt, s->this_val); @@ -18921,18 +19991,66 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) { - JSValue func_obj; + JSRuntime *rt = ctx->rt; + JSStackFrame *sf = &s->frame; + JSValue func_obj, ret; - if (js_check_stack_overflow(ctx->rt, 0)) - return JS_ThrowStackOverflow(ctx); + assert(!s->is_completed); + if (js_check_stack_overflow(ctx->rt, 0)) { + ret = JS_ThrowStackOverflow(ctx); + } else { + /* the tag does not matter provided it is not an object */ + func_obj = JS_MKPTR(JS_TAG_INT, s); + ret = JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED, + s->argc, sf->arg_buf, JS_CALL_FLAG_GENERATOR); + } + if (JS_IsException(ret) || JS_IsUndefined(ret)) { + if (JS_IsUndefined(ret)) { + ret = sf->cur_sp[-1]; + sf->cur_sp[-1] = JS_UNDEFINED; + } + /* end of execution */ + s->is_completed = TRUE; + + /* close the closure variables. */ + close_var_refs(rt, sf); - /* the tag does not matter provided it is not an object */ - func_obj = JS_MKPTR(JS_TAG_INT, s); - return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED, - s->argc, vc(s->frame.arg_buf), - JS_CALL_FLAG_GENERATOR); + async_func_free_frame(rt, s); + } + return ret; } +static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) +{ + /* cannot close the closure variables here because it would + potentially modify the object graph */ + if (!s->is_completed) { + async_func_free_frame(rt, s); + } + + JS_FreeValueRT(rt, s->resolving_funcs[0]); + JS_FreeValueRT(rt, s->resolving_funcs[1]); + + remove_gc_object(&s->header); + if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && s->header.ref_count != 0) { + list_add_tail(&s->header.link, &rt->gc_zero_ref_count_list); + } else { + js_free_rt(rt, s); + } +} + +static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) +{ + if (--s->header.ref_count == 0) { + if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) { + list_del(&s->header.link); + list_add(&s->header.link, &rt->gc_zero_ref_count_list); + if (rt->gc_phase == JS_GC_PHASE_NONE) { + free_zero_refcount(rt); + } + } + } +} /* Generators */ @@ -18946,18 +20064,21 @@ typedef enum JSGeneratorStateEnum { typedef struct JSGeneratorData { JSGeneratorStateEnum state; - JSAsyncFunctionState func_state; + JSAsyncFunctionState *func_state; } JSGeneratorData; static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s) { if (s->state == JS_GENERATOR_STATE_COMPLETED) return; - async_func_free(rt, &s->func_state); + if (s->func_state) { + async_func_free(rt, s->func_state); + s->func_state = NULL; + } s->state = JS_GENERATOR_STATE_COMPLETED; } -static void js_generator_finalizer(JSRuntime *rt, JSValueConst obj) +static void js_generator_finalizer(JSRuntime *rt, JSValue obj) { JSGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_GENERATOR); @@ -18978,9 +20099,9 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val, JSObject *p = JS_VALUE_GET_OBJ(val); JSGeneratorData *s = p->u.generator_data; - if (!s || s->state == JS_GENERATOR_STATE_COMPLETED) + if (!s || !s->func_state) return; - async_func_mark(rt, &s->func_state, mark_func); + mark_func(rt, &s->func_state->header); } /* XXX: use enum */ @@ -18990,19 +20111,19 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val, static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic) + BOOL *pdone, int magic) { JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR); JSStackFrame *sf; JSValue ret, func_ret; - *pdone = true; + *pdone = TRUE; if (!s) return JS_ThrowTypeError(ctx, "not a generator"); - sf = &s->func_state.frame; switch(s->state) { default: case JS_GENERATOR_STATE_SUSPENDED_START: + sf = &s->func_state->frame; if (magic == GEN_MAGIC_NEXT) { goto exec_no_arg; } else { @@ -19012,28 +20133,29 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, break; case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR: case JS_GENERATOR_STATE_SUSPENDED_YIELD: + sf = &s->func_state->frame; /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */ - ret = js_dup(argv[0]); + ret = JS_DupValue(ctx, argv[0]); if (magic == GEN_MAGIC_THROW && s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) { JS_Throw(ctx, ret); - s->func_state.throw_flag = true; + s->func_state->throw_flag = TRUE; } else { sf->cur_sp[-1] = ret; - sf->cur_sp[0] = js_int32(magic); + sf->cur_sp[0] = JS_NewInt32(ctx, magic); sf->cur_sp++; exec_no_arg: - s->func_state.throw_flag = false; + s->func_state->throw_flag = FALSE; } s->state = JS_GENERATOR_STATE_EXECUTING; - func_ret = async_func_resume(ctx, &s->func_state); + func_ret = async_func_resume(ctx, s->func_state); s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD; - if (JS_IsException(func_ret)) { - /* finalize the execution in case of exception */ + if (s->func_state->is_completed) { + /* finalize the execution in case of exception or normal return */ free_generator_stack(ctx, s); return func_ret; - } - if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) { + } else { + assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT); /* get the returned yield value at the top of the stack */ ret = sf->cur_sp[-1]; sf->cur_sp[-1] = JS_UNDEFINED; @@ -19042,14 +20164,8 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, /* return (value, done) object */ *pdone = 2; } else { - *pdone = false; + *pdone = FALSE; } - } else { - /* end of iterator */ - ret = sf->cur_sp[-1]; - sf->cur_sp[-1] = JS_UNDEFINED; - JS_FreeValue(ctx, func_ret); - free_generator_stack(ctx, s); } break; case JS_GENERATOR_STATE_COMPLETED: @@ -19061,10 +20177,10 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; break; case GEN_MAGIC_RETURN: - ret = js_dup(argv[0]); + ret = JS_DupValue(ctx, argv[0]); break; case GEN_MAGIC_THROW: - ret = JS_Throw(ctx, js_dup(argv[0])); + ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0])); break; } break; @@ -19087,13 +20203,14 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, if (!s) return JS_EXCEPTION; s->state = JS_GENERATOR_STATE_SUSPENDED_START; - if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { + s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv); + if (!s->func_state) { s->state = JS_GENERATOR_STATE_COMPLETED; goto fail; } /* execute the function up to 'OP_initial_yield' */ - func_ret = async_func_resume(ctx, &s->func_state); + func_ret = async_func_resume(ctx, s->func_state); if (JS_IsException(func_ret)) goto fail; JS_FreeValue(ctx, func_ret); @@ -19101,7 +20218,7 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR); if (JS_IsException(obj)) goto fail; - JS_SetOpaqueInternal(obj, s); + JS_SetOpaque(obj, s); return obj; fail: free_generator_stack_rt(ctx->rt, s); @@ -19111,37 +20228,12 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, /* AsyncFunction */ -static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s) -{ - if (s->is_active) { - async_func_free(rt, &s->func_state); - s->is_active = false; - } -} - -static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s) -{ - js_async_function_terminate(rt, s); - JS_FreeValueRT(rt, s->resolving_funcs[0]); - JS_FreeValueRT(rt, s->resolving_funcs[1]); - remove_gc_object(&s->header); - js_free_rt(rt, s); -} - -static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s) -{ - if (--s->header.ref_count == 0) { - js_async_function_free0(rt, s); - } -} - -static void js_async_function_resolve_finalizer(JSRuntime *rt, - JSValueConst val) +static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); - JSAsyncFunctionData *s = p->u.async_function_data; + JSAsyncFunctionState *s = p->u.async_function_data; if (s) { - js_async_function_free(rt, s); + async_func_free(rt, s); } } @@ -19149,14 +20241,14 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); - JSAsyncFunctionData *s = p->u.async_function_data; + JSAsyncFunctionState *s = p->u.async_function_data; if (s) { mark_func(rt, &s->header); } } static int js_async_function_resolve_create(JSContext *ctx, - JSAsyncFunctionData *s, + JSAsyncFunctionState *s, JSValue *resolving_funcs) { int i; @@ -19178,73 +20270,59 @@ static int js_async_function_resolve_create(JSContext *ctx, return 0; } -static bool js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s) +static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s) { - bool is_success = true; JSValue func_ret, ret2; - func_ret = async_func_resume(ctx, &s->func_state); - if (JS_IsException(func_ret)) { - fail: - if (unlikely(JS_IsUncatchableError(ctx, ctx->rt->current_exception))) { - is_success = false; - } else { - JSValue error = JS_GetException(ctx); + func_ret = async_func_resume(ctx, s); + if (s->is_completed) { + if (JS_IsException(func_ret)) { + JSValue error; + fail: + error = JS_GetException(ctx); ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED, - 1, vc(&error)); + 1, (JSValueConst *)&error); JS_FreeValue(ctx, error); - resolved: - if (unlikely(JS_IsException(ret2))) { - if (JS_IsUncatchableError(ctx, ctx->rt->current_exception)) { - is_success = false; - } else { - abort(); /* BUG */ - } - } - JS_FreeValue(ctx, ret2); + JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */ + } else { + /* normal return */ + ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED, + 1, (JSValueConst *)&func_ret); + JS_FreeValue(ctx, func_ret); + JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */ } - js_async_function_terminate(ctx->rt, s); } else { - JSValue value; - value = s->func_state.frame.cur_sp[-1]; - s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; - if (JS_IsUndefined(func_ret)) { - /* function returned */ - ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED, - 1, vc(&value)); - JS_FreeValue(ctx, value); - goto resolved; - } else { - JSValue promise, resolving_funcs[2], resolving_funcs1[2]; - int i, res; + JSValue value, promise, resolving_funcs[2], resolving_funcs1[2]; + int i, res; - /* await */ - JS_FreeValue(ctx, func_ret); /* not used */ - promise = js_promise_resolve(ctx, ctx->promise_ctor, - 1, vc(&value), 0); - JS_FreeValue(ctx, value); - if (JS_IsException(promise)) - goto fail; - if (js_async_function_resolve_create(ctx, s, resolving_funcs)) { - JS_FreeValue(ctx, promise); - goto fail; - } + value = s->frame.cur_sp[-1]; + s->frame.cur_sp[-1] = JS_UNDEFINED; - /* Note: no need to create 'thrownawayCapability' as in - the spec */ - for(i = 0; i < 2; i++) - resolving_funcs1[i] = JS_UNDEFINED; - res = perform_promise_then(ctx, promise, - vc(resolving_funcs), - vc(resolving_funcs1)); + /* await */ + JS_FreeValue(ctx, func_ret); /* not used */ + promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, (JSValueConst *)&value, 0); + JS_FreeValue(ctx, value); + if (JS_IsException(promise)) + goto fail; + if (js_async_function_resolve_create(ctx, s, resolving_funcs)) { JS_FreeValue(ctx, promise); - for(i = 0; i < 2; i++) - JS_FreeValue(ctx, resolving_funcs[i]); - if (res) - goto fail; + goto fail; } + + /* Note: no need to create 'thrownawayCapability' as in + the spec */ + for(i = 0; i < 2; i++) + resolving_funcs1[i] = JS_UNDEFINED; + res = perform_promise_then(ctx, promise, + (JSValueConst *)resolving_funcs, + (JSValueConst *)resolving_funcs1); + JS_FreeValue(ctx, promise); + for(i = 0; i < 2; i++) + JS_FreeValue(ctx, resolving_funcs[i]); + if (res) + goto fail; } - return is_success; } static JSValue js_async_function_resolve_call(JSContext *ctx, @@ -19254,23 +20332,22 @@ static JSValue js_async_function_resolve_call(JSContext *ctx, int flags) { JSObject *p = JS_VALUE_GET_OBJ(func_obj); - JSAsyncFunctionData *s = p->u.async_function_data; - bool is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE; + JSAsyncFunctionState *s = p->u.async_function_data; + BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE; JSValueConst arg; if (argc > 0) arg = argv[0]; else arg = JS_UNDEFINED; - s->func_state.throw_flag = is_reject; + s->throw_flag = is_reject; if (is_reject) { - JS_Throw(ctx, js_dup(arg)); + JS_Throw(ctx, JS_DupValue(ctx, arg)); } else { /* return value of await */ - s->func_state.frame.cur_sp[-1] = js_dup(arg); + s->frame.cur_sp[-1] = JS_DupValue(ctx, arg); } - if (!js_async_function_resume(ctx, s)) - return JS_EXCEPTION; + js_async_function_resume(ctx, s); return JS_UNDEFINED; } @@ -19279,33 +20356,21 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, int argc, JSValueConst *argv, int flags) { JSValue promise; - JSAsyncFunctionData *s; + JSAsyncFunctionState *s; - s = js_mallocz(ctx, sizeof(*s)); + s = async_func_init(ctx, func_obj, this_obj, argc, argv); if (!s) return JS_EXCEPTION; - s->header.ref_count = 1; - add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION); - s->is_active = false; - s->resolving_funcs[0] = JS_UNDEFINED; - s->resolving_funcs[1] = JS_UNDEFINED; promise = JS_NewPromiseCapability(ctx, s->resolving_funcs); - if (JS_IsException(promise)) - goto fail; - - if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { - fail: - JS_FreeValue(ctx, promise); - js_async_function_free(ctx->rt, s); + if (JS_IsException(promise)) { + async_func_free(ctx->rt, s); return JS_EXCEPTION; } - s->is_active = true; - if (!js_async_function_resume(ctx, s)) - goto fail; + js_async_function_resume(ctx, s); - js_async_function_free(ctx->rt, s); + async_func_free(ctx->rt, s); return promise; } @@ -19334,7 +20399,8 @@ typedef struct JSAsyncGeneratorRequest { typedef struct JSAsyncGeneratorData { JSObject *generator; /* back pointer to the object (const) */ JSAsyncGeneratorStateEnum state; - JSAsyncFunctionState func_state; + /* func_state is NULL is state AWAITING_RETURN and COMPLETED */ + JSAsyncFunctionState *func_state; struct list_head queue; /* list of JSAsyncGeneratorRequest.link */ } JSAsyncGeneratorData; @@ -19352,14 +20418,12 @@ static void js_async_generator_free(JSRuntime *rt, JS_FreeValueRT(rt, req->resolving_funcs[1]); js_free_rt(rt, req); } - if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED && - s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) { - async_func_free(rt, &s->func_state); - } + if (s->func_state) + async_func_free(rt, s->func_state); js_free_rt(rt, s); } -static void js_async_generator_finalizer(JSRuntime *rt, JSValueConst obj) +static void js_async_generator_finalizer(JSRuntime *rt, JSValue obj) { JSAsyncGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_ASYNC_GENERATOR); @@ -19382,9 +20446,8 @@ static void js_async_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, req->resolving_funcs[0], mark_func); JS_MarkValue(rt, req->resolving_funcs[1], mark_func); } - if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED && - s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) { - async_func_mark(rt, &s->func_state, mark_func); + if (s->func_state) { + mark_func(rt, &s->func_state->header); } } } @@ -19392,19 +20455,19 @@ static void js_async_generator_mark(JSRuntime *rt, JSValueConst val, static JSValue js_async_generator_resolve_function(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data); + int magic, JSValue *func_data); static int js_async_generator_resolve_function_create(JSContext *ctx, - JSValue generator, + JSValueConst generator, JSValue *resolving_funcs, - bool is_resume_next) + BOOL is_resume_next) { int i; JSValue func; for(i = 0; i < 2; i++) { func = JS_NewCFunctionData(ctx, js_async_generator_resolve_function, 1, - i + is_resume_next * 2, 1, vc(&generator)); + i + is_resume_next * 2, 1, &generator); if (JS_IsException(func)) { if (i == 1) JS_FreeValue(ctx, resolving_funcs[0]); @@ -19417,18 +20480,18 @@ static int js_async_generator_resolve_function_create(JSContext *ctx, static int js_async_generator_await(JSContext *ctx, JSAsyncGeneratorData *s, - JSValue value) + JSValueConst value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int i, res; promise = js_promise_resolve(ctx, ctx->promise_ctor, - 1, vc(&value), 0); + 1, &value, 0); if (JS_IsException(promise)) goto fail; if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), - resolving_funcs, false)) { + resolving_funcs, FALSE)) { JS_FreeValue(ctx, promise); goto fail; } @@ -19438,8 +20501,8 @@ static int js_async_generator_await(JSContext *ctx, for(i = 0; i < 2; i++) resolving_funcs1[i] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, - vc(resolving_funcs), - vc(resolving_funcs1)); + (JSValueConst *)resolving_funcs, + (JSValueConst *)resolving_funcs1); JS_FreeValue(ctx, promise); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); @@ -19473,10 +20536,10 @@ static void js_async_generator_resolve_or_reject(JSContext *ctx, static void js_async_generator_resolve(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst value, - bool done) + BOOL done) { JSValue result; - result = js_create_iterator_result(ctx, js_dup(value), done); + result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done); /* XXX: better exception handling ? */ js_async_generator_resolve_or_reject(ctx, s, result, 0); JS_FreeValue(ctx, result); @@ -19494,25 +20557,26 @@ static void js_async_generator_complete(JSContext *ctx, { if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) { s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; - async_func_free(ctx->rt, &s->func_state); + async_func_free(ctx->rt, s->func_state); + s->func_state = NULL; } } static int js_async_generator_completed_return(JSContext *ctx, JSAsyncGeneratorData *s, - JSValue value) + JSValueConst value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int res; // Can fail looking up JS_ATOM_constructor when is_reject==0. - promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&value), + promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &value, /*is_reject*/0); // A poisoned .constructor property is observable and the resulting // exception should be delivered to the catch handler. if (JS_IsException(promise)) { JSValue err = JS_GetException(ctx); - promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&err), + promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err, /*is_reject*/1); JS_FreeValue(ctx, err); if (JS_IsException(promise)) @@ -19521,15 +20585,15 @@ static int js_async_generator_completed_return(JSContext *ctx, if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs1, - true)) { + TRUE)) { JS_FreeValue(ctx, promise); return -1; } resolving_funcs[0] = JS_UNDEFINED; resolving_funcs[1] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, - vc(resolving_funcs1), - vc(resolving_funcs)); + (JSValueConst *)resolving_funcs1, + (JSValueConst *)resolving_funcs); JS_FreeValue(ctx, resolving_funcs1[0]); JS_FreeValue(ctx, resolving_funcs1[1]); JS_FreeValue(ctx, promise); @@ -19561,7 +20625,7 @@ static void js_async_generator_resume_next(JSContext *ctx, break; case JS_ASYNC_GENERATOR_STATE_COMPLETED: if (next->completion_type == GEN_MAGIC_NEXT) { - js_async_generator_resolve(ctx, s, JS_UNDEFINED, true); + js_async_generator_resolve(ctx, s, JS_UNDEFINED, TRUE); } else if (next->completion_type == GEN_MAGIC_RETURN) { s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN; js_async_generator_completed_return(ctx, s, next->result); @@ -19571,34 +20635,42 @@ static void js_async_generator_resume_next(JSContext *ctx, goto done; case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD: case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR: - value = js_dup(next->result); + value = JS_DupValue(ctx, next->result); if (next->completion_type == GEN_MAGIC_THROW && s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) { JS_Throw(ctx, value); - s->func_state.throw_flag = true; + s->func_state->throw_flag = TRUE; } else { /* 'yield' returns a value. 'yield *' also returns a value in case the 'throw' method is called */ - s->func_state.frame.cur_sp[-1] = value; - s->func_state.frame.cur_sp[0] = - js_int32(next->completion_type); - s->func_state.frame.cur_sp++; + s->func_state->frame.cur_sp[-1] = value; + s->func_state->frame.cur_sp[0] = + JS_NewInt32(ctx, next->completion_type); + s->func_state->frame.cur_sp++; exec_no_arg: - s->func_state.throw_flag = false; + s->func_state->throw_flag = FALSE; } s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING; resume_exec: - func_ret = async_func_resume(ctx, &s->func_state); - if (JS_IsException(func_ret)) { - value = JS_GetException(ctx); - js_async_generator_complete(ctx, s); - js_async_generator_reject(ctx, s, value); - JS_FreeValue(ctx, value); - } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) { + func_ret = async_func_resume(ctx, s->func_state); + if (s->func_state->is_completed) { + if (JS_IsException(func_ret)) { + value = JS_GetException(ctx); + js_async_generator_complete(ctx, s); + js_async_generator_reject(ctx, s, value); + JS_FreeValue(ctx, value); + } else { + /* end of function */ + js_async_generator_complete(ctx, s); + js_async_generator_resolve(ctx, s, func_ret, TRUE); + JS_FreeValue(ctx, func_ret); + } + } else { int func_ret_code, ret; - value = s->func_state.frame.cur_sp[-1]; - s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; + assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT); func_ret_code = JS_VALUE_GET_INT(func_ret); + value = s->func_state->frame.cur_sp[-1]; + s->func_state->frame.cur_sp[-1] = JS_UNDEFINED; switch(func_ret_code) { case FUNC_RET_YIELD: case FUNC_RET_YIELD_STAR: @@ -19606,7 +20678,7 @@ static void js_async_generator_resume_next(JSContext *ctx, s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR; else s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD; - js_async_generator_resolve(ctx, s, value, false); + js_async_generator_resolve(ctx, s, value, FALSE); JS_FreeValue(ctx, value); break; case FUNC_RET_AWAIT: @@ -19614,21 +20686,13 @@ static void js_async_generator_resume_next(JSContext *ctx, JS_FreeValue(ctx, value); if (ret < 0) { /* exception: throw it */ - s->func_state.throw_flag = true; + s->func_state->throw_flag = TRUE; goto resume_exec; } goto done; default: abort(); } - } else { - assert(JS_IsUndefined(func_ret)); - /* end of function */ - value = s->func_state.frame.cur_sp[-1]; - s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; - js_async_generator_complete(ctx, s); - js_async_generator_resolve(ctx, s, value, true); - JS_FreeValue(ctx, value); } break; default: @@ -19641,9 +20705,9 @@ static void js_async_generator_resume_next(JSContext *ctx, static JSValue js_async_generator_resolve_function(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) + int magic, JSValue *func_data) { - bool is_reject = magic & 1; + BOOL is_reject = magic & 1; JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR); JSValueConst arg = argv[0]; @@ -19657,17 +20721,17 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx, if (is_reject) { js_async_generator_reject(ctx, s, arg); } else { - js_async_generator_resolve(ctx, s, arg, true); + js_async_generator_resolve(ctx, s, arg, TRUE); } } else { /* restart function execution after await() */ assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING); - s->func_state.throw_flag = is_reject; + s->func_state->throw_flag = is_reject; if (is_reject) { - JS_Throw(ctx, js_dup(arg)); + JS_Throw(ctx, JS_DupValue(ctx, arg)); } else { /* return value of await */ - s->func_state.frame.cur_sp[-1] = js_dup(arg); + s->func_state->frame.cur_sp[-1] = JS_DupValue(ctx, arg); } js_async_generator_resume_next(ctx, s); } @@ -19691,7 +20755,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, JS_ThrowTypeError(ctx, "not an AsyncGenerator object"); err = JS_GetException(ctx); res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, - 1, vc(&err)); + 1, (JSValueConst *)&err); JS_FreeValue(ctx, err); JS_FreeValue(ctx, res2); JS_FreeValue(ctx, resolving_funcs[0]); @@ -19702,8 +20766,8 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, if (!req) goto fail; req->completion_type = magic; - req->result = js_dup(argv[0]); - req->promise = js_dup(promise); + req->result = JS_DupValue(ctx, argv[0]); + req->promise = JS_DupValue(ctx, promise); req->resolving_funcs[0] = resolving_funcs[0]; req->resolving_funcs[1] = resolving_funcs[1]; list_add_tail(&req->link, &s->queue); @@ -19718,8 +20782,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_async_generator_function_call(JSContext *ctx, - JSValueConst func_obj, +static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, int flags) @@ -19732,14 +20795,12 @@ static JSValue js_async_generator_function_call(JSContext *ctx, return JS_EXCEPTION; s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START; init_list_head(&s->queue); - if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { - s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; + s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv); + if (!s->func_state) goto fail; - } - /* execute the function up to 'OP_initial_yield' (no yield nor await are possible) */ - func_ret = async_func_resume(ctx, &s->func_state); + func_ret = async_func_resume(ctx, s->func_state); if (JS_IsException(func_ret)) goto fail; JS_FreeValue(ctx, func_ret); @@ -19748,7 +20809,7 @@ static JSValue js_async_generator_function_call(JSContext *ctx, if (JS_IsException(obj)) goto fail; s->generator = JS_VALUE_GET_OBJ(obj); - JS_SetOpaqueInternal(obj, s); + JS_SetOpaque(obj, s); return obj; fail: js_async_generator_free(ctx->rt, s); @@ -19873,7 +20934,7 @@ typedef struct BlockEnv { int label_finally; /* -1 if none */ int scope_level; uint8_t has_iterator : 1; - uint8_t is_regular_stmt : 1; // i.e. not a loop statement + uint8_t is_regular_stmt : 1; /* i.e. not a loop statement */ } BlockEnv; typedef struct JSGlobalVar { @@ -19907,11 +20968,18 @@ typedef struct LabelSlot { RelocEntry *first_reloc; } LabelSlot; -typedef struct SourceLocSlot { +typedef struct LineNumberSlot { uint32_t pc; + uint32_t source_pos; +} LineNumberSlot; + +typedef struct { + /* last source position */ + const uint8_t *ptr; int line_num; int col_num; -} SourceLocSlot; + const uint8_t *buf_start; +} GetLineColCache; typedef enum JSParseFunctionEnum { JS_PARSE_FUNC_STATEMENT, @@ -19941,36 +21009,34 @@ typedef struct JSFunctionDef { struct list_head child_list; /* list of JSFunctionDef.link */ struct list_head link; - bool is_eval; /* true if eval code */ - int eval_type; /* only valid if is_eval = true */ - bool is_global_var; /* true if variables are not defined locally: + BOOL is_eval; /* TRUE if eval code */ + int eval_type; /* only valid if is_eval = TRUE */ + BOOL is_global_var; /* TRUE if variables are not defined locally: eval global, eval module or non strict eval */ - bool is_func_expr; /* true if function expression */ - bool has_home_object; /* true if the home object is available */ - bool has_prototype; /* true if a prototype field is necessary */ - bool has_simple_parameter_list; - bool has_parameter_expressions; /* if true, an argument scope is created */ - bool has_use_strict; /* to reject directive in special cases */ - bool has_eval_call; /* true if the function contains a call to eval() */ - bool has_arguments_binding; /* true if the 'arguments' binding is + BOOL is_func_expr; /* TRUE if function expression */ + BOOL has_home_object; /* TRUE if the home object is available */ + BOOL has_prototype; /* true if a prototype field is necessary */ + BOOL has_simple_parameter_list; + BOOL has_parameter_expressions; /* if true, an argument scope is created */ + BOOL has_use_strict; /* to reject directive in special cases */ + BOOL has_eval_call; /* true if the function contains a call to eval() */ + BOOL has_arguments_binding; /* true if the 'arguments' binding is available in the function */ - bool has_this_binding; /* true if the 'this' and new.target binding are + BOOL has_this_binding; /* true if the 'this' and new.target binding are available in the function */ - bool new_target_allowed; /* true if the 'new.target' does not + BOOL new_target_allowed; /* true if the 'new.target' does not throw a syntax error */ - bool super_call_allowed; /* true if super() is allowed */ - bool super_allowed; /* true if super. or super[] is allowed */ - bool arguments_allowed; /* true if the 'arguments' identifier is allowed */ - bool is_derived_class_constructor; - bool in_function_body; - bool backtrace_barrier; + BOOL super_call_allowed; /* true if super() is allowed */ + BOOL super_allowed; /* true if super. or super[] is allowed */ + BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */ + BOOL is_derived_class_constructor; + BOOL in_function_body; JSFunctionKindEnum func_kind : 8; - JSParseFunctionEnum func_type : 7; - uint8_t is_strict_mode : 1; + JSParseFunctionEnum func_type : 8; + uint8_t js_mode; /* bitmap of JS_MODE_x */ JSAtom func_name; /* JS_ATOM_NULL if no name */ JSVarDef *vars; - uint32_t *vars_htab; // indexes into vars[] int var_size; /* allocated size for vars[] */ int var_count; JSVarDef *args; @@ -19989,7 +21055,7 @@ typedef struct JSFunctionDef { int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */ int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */ int home_object_var_idx; - bool need_home_object; + BOOL need_home_object; int scope_level; /* index into fd->scopes if the current lexical scope */ int scope_first; /* index into vd->vars of first lexically scoped variable */ @@ -20005,7 +21071,8 @@ typedef struct JSFunctionDef { DynBuf byte_code; int last_opcode_pos; /* -1 if no last opcode */ - bool use_short_opcodes; /* true if short opcodes are used in byte_code */ + const uint8_t *last_opcode_source_ptr; + BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */ LabelSlot *label_slots; int label_size; /* allocated size for label_slots[] */ @@ -20026,31 +21093,30 @@ typedef struct JSFunctionDef { int jump_size; int jump_count; - SourceLocSlot *source_loc_slots; - int source_loc_size; - int source_loc_count; + LineNumberSlot *line_number_slots; + int line_number_size; + int line_number_count; int line_number_last; int line_number_last_pc; - int col_number_last; /* pc2line table */ + BOOL strip_debug : 1; /* strip all debug info (implies strip_source = TRUE) */ + BOOL strip_source : 1; /* strip only source code */ JSAtom filename; - int line_num; - int col_num; + uint32_t source_pos; /* pointer in the eval() source */ + GetLineColCache *get_line_col_cache; /* XXX: could remove to save memory */ DynBuf pc2line; char *source; /* raw source, utf-8 encoded */ int source_len; JSModuleDef *module; /* != NULL when parsing a module */ - bool has_await; /* true if await is used (used in module eval) */ + BOOL has_await; /* TRUE if await is used (used in module eval) */ } JSFunctionDef; typedef struct JSToken { int val; - int line_num; /* line number of token start */ - int col_num; /* column number of token start */ - const uint8_t *ptr; + const uint8_t *ptr; /* position in the source */ union { struct { JSValue str; @@ -20061,8 +21127,8 @@ typedef struct JSToken { } num; struct { JSAtom atom; - bool has_escape; - bool is_reserved; + BOOL has_escape; + BOOL is_reserved; } ident; struct { JSValue body; @@ -20073,28 +21139,24 @@ typedef struct JSToken { typedef struct JSParseState { JSContext *ctx; - int last_line_num; /* line number of last token */ - int last_col_num; /* column number of last token */ - int line_num; /* line number of current offset */ - int col_num; /* column number of current offset */ const char *filename; JSToken token; - bool got_lf; /* true if got line feed before the current token */ + BOOL got_lf; /* true if got line feed before the current token */ const uint8_t *last_ptr; const uint8_t *buf_start; const uint8_t *buf_ptr; const uint8_t *buf_end; - const uint8_t *eol; // most recently seen end-of-line character - const uint8_t *mark; // first token character, invariant: eol < mark /* current function code */ JSFunctionDef *cur_func; - bool is_module; /* parsing a module */ - bool allow_html_comments; + BOOL is_module; /* parsing a module */ + BOOL allow_html_comments; + BOOL ext_json; /* true if accepting JSON superset */ + GetLineColCache get_line_col_cache; } JSParseState; typedef struct JSOpCode { -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* +#ifdef DUMP_BYTECODE const char *name; #endif uint8_t size; /* in bytes */ @@ -20107,7 +21169,7 @@ typedef struct JSOpCode { static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { #define FMT(f) -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* +#ifdef DUMP_BYTECODE #define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f }, #else #define DEF(id, size, n_pop, n_push, f) { size, n_pop, n_push, OP_FMT_ ## f }, @@ -20117,6 +21179,7 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { #undef FMT }; +#if SHORT_OPCODES /* After the final compilation pass, short opcodes are used. Their opcodes overlap with the temporary opcodes which cannot appear in the final bytecode. Their description is after the temporary @@ -20124,6 +21187,11 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { #define short_opcode_info(op) \ opcode_info[(op) >= OP_TEMP_START ? \ (op) + (OP_TEMP_END - OP_TEMP_START) : (op)] +#else +#define short_opcode_info(op) opcode_info[op] +#endif + +static __exception int next_token(JSParseState *s); static void free_token(JSParseState *s, JSToken *token) { @@ -20155,7 +21223,6 @@ static void free_token(JSParseState *s, JSToken *token) static void __attribute((unused)) dump_token(JSParseState *s, const JSToken *token) { - printf("%d:%d ", token->line_num, token->col_num); switch(token->val) { case TOK_NUMBER: { @@ -20214,56 +21281,104 @@ static void __attribute((unused)) dump_token(JSParseState *s, } } -int JS_PRINTF_FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, JS_PRINTF_FORMAT const char *fmt, ...) +/* return the zero based line and column number in the source. */ +/* Note: we no longer support '\r' as line terminator */ +static int get_line_col(int *pcol_num, const uint8_t *buf, size_t len) +{ + int line_num, col_num, c; + size_t i; + + line_num = 0; + col_num = 0; + for(i = 0; i < len; i++) { + c = buf[i]; + if (c == '\n') { + line_num++; + col_num = 0; + } else if (c < 0x80 || c >= 0xc0) { + col_num++; + } + } + *pcol_num = col_num; + return line_num; +} + +static int get_line_col_cached(GetLineColCache *s, int *pcol_num, const uint8_t *ptr) +{ + int line_num, col_num; + if (ptr >= s->ptr) { + line_num = get_line_col(&col_num, s->ptr, ptr - s->ptr); + if (line_num == 0) { + s->col_num += col_num; + } else { + s->line_num += line_num; + s->col_num = col_num; + } + } else { + line_num = get_line_col(&col_num, ptr, s->ptr - ptr); + if (line_num == 0) { + s->col_num -= col_num; + } else { + const uint8_t *p; + s->line_num -= line_num; + /* find the absolute column position */ + col_num = 0; + for(p = ptr - 1; p >= s->buf_start; p--) { + if (*p == '\n') { + break; + } else if (*p < 0x80 || *p >= 0xc0) { + col_num++; + } + } + s->col_num = col_num; + } + } + s->ptr = ptr; + *pcol_num = s->col_num; + return s->line_num; +} + +/* 'ptr' is the position of the error in the source */ +static int js_parse_error_v(JSParseState *s, const uint8_t *ptr, const char *fmt, va_list ap) { JSContext *ctx = s->ctx; - va_list ap; - int backtrace_flags; + int line_num, col_num; + line_num = get_line_col(&col_num, s->buf_start, ptr - s->buf_start); + JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE); + build_backtrace(ctx, ctx->rt->current_exception, s->filename, + line_num + 1, col_num + 1, 0); + return -1; +} +static __attribute__((format(printf, 3, 4))) int js_parse_error_pos(JSParseState *s, const uint8_t *ptr, const char *fmt, ...) +{ + va_list ap; + int ret; + va_start(ap, fmt); - JS_ThrowError2(ctx, JS_SYNTAX_ERROR, false, fmt, ap); + ret = js_parse_error_v(s, ptr, fmt, ap); va_end(ap); - backtrace_flags = 0; - if (s->cur_func && s->cur_func->backtrace_barrier) - backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL; - build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename, - s->line_num, s->col_num, backtrace_flags); - return -1; + return ret; } -#ifndef QJS_DISABLE_PARSER - -static __exception int next_token(JSParseState *s); +static __attribute__((format(printf, 2, 3))) int js_parse_error(JSParseState *s, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = js_parse_error_v(s, s->token.ptr, fmt, ap); + va_end(ap); + return ret; +} static int js_parse_expect(JSParseState *s, int tok) { - char buf[ATOM_GET_STR_BUF_SIZE]; - - if (s->token.val == tok) - return next_token(s); - - switch(s->token.val) { - case TOK_EOF: - return js_parse_error(s, "Unexpected end of input"); - case TOK_NUMBER: - return js_parse_error(s, "Unexpected number"); - case TOK_STRING: - return js_parse_error(s, "Unexpected string"); - case TOK_TEMPLATE: - return js_parse_error(s, "Unexpected string template"); - case TOK_REGEXP: - return js_parse_error(s, "Unexpected regexp"); - case TOK_IDENT: - return js_parse_error(s, "Unexpected identifier '%s'", - JS_AtomGetStr(s->ctx, buf, sizeof(buf), - s->token.u.ident.atom)); - case TOK_ERROR: - return js_parse_error(s, "Invalid or unexpected token"); - default: - return js_parse_error(s, "Unexpected token '%.*s'", - (int)(s->buf_ptr - s->token.ptr), - (const char *)s->token.ptr); + if (s->token.val != tok) { + /* XXX: dump token correctly in all cases */ + return js_parse_error(s, "expecting '%c'", tok); } + return next_token(s); } static int js_parse_expect_semi(JSParseState *s) @@ -20286,10 +21401,8 @@ static int js_parse_error_reserved_identifier(JSParseState *s) s->token.u.ident.atom)); } -static __exception int js_parse_template_part(JSParseState *s, - const uint8_t *p) +static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p) { - const uint8_t *p_next; uint32_t c; StringBuffer b_s, *b = &b_s; JSValue str; @@ -20323,14 +21436,11 @@ static __exception int js_parse_template_part(JSParseState *s, p++; c = '\n'; } - if (c == '\n') { - s->line_num++; - s->eol = &p[-1]; - s->mark = p; - } else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) { - js_parse_error(s, "invalid UTF-8 sequence"); + if (c >= 0x80) { + const uint8_t *p_next; + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { + js_parse_error_pos(s, p - 1, "invalid UTF-8 sequence"); goto fail; } p = p_next; @@ -20355,13 +21465,13 @@ static __exception int js_parse_template_part(JSParseState *s, } static __exception int js_parse_string(JSParseState *s, int sep, - bool do_throw, const uint8_t *p, + BOOL do_throw, const uint8_t *p, JSToken *token, const uint8_t **pp) { - const uint8_t *p_next; int ret; uint32_t c; StringBuffer b_s, *b = &b_s; + const uint8_t *p_escape; JSValue str; /* string */ @@ -20391,16 +21501,14 @@ static __exception int js_parse_string(JSParseState *s, int sep, break; } if (c == '\\') { + p_escape = p - 1; c = *p; + /* XXX: need a specific JSON case to avoid + accepting invalid escapes */ switch(c) { case '\0': - if (p >= s->buf_end) { - if (sep != '`') - goto invalid_char; - if (do_throw) - js_parse_error(s, "Unexpected end of input"); - goto fail; - } + if (p >= s->buf_end) + goto invalid_char; p++; break; case '\'': @@ -20416,29 +21524,29 @@ static __exception int js_parse_string(JSParseState *s, int sep, case '\n': /* ignore escaped newline sequence */ p++; - if (sep != '`') { - s->line_num++; - s->eol = &p[-1]; - s->mark = p; - } continue; default: - if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) { - /* accept isolated \0 */ - p++; - c = '\0'; - } else - if ((c >= '0' && c <= '9') - && (s->cur_func->is_strict_mode || sep == '`')) { - if (do_throw) { - js_parse_error(s, "%s are not allowed in %s", - (c >= '8') ? "\\8 and \\9" : "Octal escape sequences", - (sep == '`') ? "template strings" : "strict mode"); + if (c >= '0' && c <= '9') { + if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`') + goto parse_escape; + if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) { + p++; + c = '\0'; + } else { + if (c >= '8' || sep == '`') { + /* Note: according to ES2021, \8 and \9 are not + accepted in strict mode or in templates. */ + goto invalid_escape; + } else { + if (do_throw) + js_parse_error_pos(s, p_escape, "octal escape sequences are not allowed in strict mode"); + } + goto fail; } - goto fail; } else if (c >= 0x80) { - c = utf8_decode(p, &p_next); - if (p_next == p + 1) { + const uint8_t *p_next; + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { goto invalid_utf8; } p = p_next; @@ -20446,12 +21554,12 @@ static __exception int js_parse_string(JSParseState *s, int sep, if (c == CP_LS || c == CP_PS) continue; } else { - ret = lre_parse_escape(&p, true); + parse_escape: + ret = lre_parse_escape(&p, TRUE); if (ret == -1) { - if (do_throw) { - js_parse_error(s, "Invalid %s escape sequence", - c == 'u' ? "Unicode" : "hexadecimal"); - } + invalid_escape: + if (do_throw) + js_parse_error_pos(s, p_escape, "malformed escape sequence in string literal"); goto fail; } else if (ret < 0) { /* ignore the '\' (could output a warning) */ @@ -20463,8 +21571,9 @@ static __exception int js_parse_string(JSParseState *s, int sep, break; } } else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) + const uint8_t *p_next; + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) goto invalid_utf8; p = p_next; } @@ -20492,15 +21601,15 @@ static __exception int js_parse_string(JSParseState *s, int sep, return -1; } -static inline bool token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { +static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { return s->token.val == TOK_IDENT && s->token.u.ident.atom == atom && !s->token.u.ident.has_escape; } static __exception int js_parse_regexp(JSParseState *s) { - const uint8_t *p, *p_next; - bool in_class; + const uint8_t *p; + BOOL in_class; StringBuffer b_s, *b = &b_s; StringBuffer b2_s, *b2 = &b2_s; uint32_t c; @@ -20508,7 +21617,7 @@ static __exception int js_parse_regexp(JSParseState *s) p = s->buf_ptr; p++; - in_class = false; + in_class = FALSE; if (string_buffer_init(s->ctx, b, 32)) return -1; if (string_buffer_init(s->ctx, b2, 1)) @@ -20526,10 +21635,10 @@ static __exception int js_parse_regexp(JSParseState *s) if (!in_class) break; } else if (c == '[') { - in_class = true; + in_class = TRUE; } else if (c == ']') { /* XXX: incorrect as the first character in a class */ - in_class = false; + in_class = FALSE; } else if (c == '\\') { if (string_buffer_putc8(b, c)) goto fail; @@ -20539,8 +21648,9 @@ static __exception int js_parse_regexp(JSParseState *s) else if (c == '\0' && p >= s->buf_end) goto eof_error; else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) { + const uint8_t *p_next; + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { goto invalid_utf8; } p = p_next; @@ -20548,19 +21658,20 @@ static __exception int js_parse_regexp(JSParseState *s) goto eol_error; } } else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) { + const uint8_t *p_next; + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { invalid_utf8: - js_parse_error(s, "invalid UTF-8 sequence"); + js_parse_error_pos(s, p - 1, "invalid UTF-8 sequence"); goto fail; } - p = p_next; /* LS or PS are considered as line terminator */ if (c == CP_LS || c == CP_PS) { eol_error: - js_parse_error(s, "unexpected line terminator in regexp"); + js_parse_error_pos(s, p - 1, "unexpected line terminator in regexp"); goto fail; } + p = p_next; } if (string_buffer_putc(b, c)) goto fail; @@ -20568,8 +21679,15 @@ static __exception int js_parse_regexp(JSParseState *s) /* flags */ for(;;) { - c = utf8_decode(p, &p_next); - /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ + const uint8_t *p_next = p; + c = *p_next++; + if (c >= 0x80) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { + p++; + goto invalid_utf8; + } + } if (!lre_js_is_ident_next(c)) break; if (string_buffer_putc(b2, c)) @@ -20596,8 +21714,6 @@ static __exception int js_parse_regexp(JSParseState *s) return -1; } -#endif // QJS_DISABLE_PARSER - static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, char *static_buf) { @@ -20625,14 +21741,12 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, return 0; } -#ifndef QJS_DISABLE_PARSER - /* convert a TOK_IDENT to a keyword when needed */ static void update_token_ident(JSParseState *s) { if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && - s->cur_func->is_strict_mode) || + (s->cur_func->js_mode & JS_MODE_STRICT)) || (s->token.u.ident.atom == JS_ATOM_yield && ((s->cur_func->func_kind & JS_FUNC_GENERATOR) || (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && @@ -20647,7 +21761,7 @@ static void update_token_ident(JSParseState *s) ((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) || s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) { if (s->token.u.ident.has_escape) { - s->token.u.ident.is_reserved = true; + s->token.u.ident.is_reserved = TRUE; s->token.val = TOK_IDENT; } else { /* The keywords atoms are pre allocated */ @@ -20664,19 +21778,19 @@ static void reparse_ident_token(JSParseState *s) (s->token.val >= TOK_FIRST_KEYWORD && s->token.val <= TOK_LAST_KEYWORD)) { s->token.val = TOK_IDENT; - s->token.u.ident.is_reserved = false; + s->token.u.ident.is_reserved = FALSE; update_token_ident(s); } } /* 'c' is the first character. Return JS_ATOM_NULL in case of error */ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, - bool *pident_has_escape, int c, bool is_private) + BOOL *pident_has_escape, int c, BOOL is_private) { - const uint8_t *p, *p_next; + const uint8_t *p, *p1; char ident_buf[128], *buf; size_t ident_size, ident_pos; - JSAtom atom = JS_ATOM_NULL; + JSAtom atom; p = *pp; buf = ident_buf; @@ -20685,29 +21799,30 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, if (is_private) buf[ident_pos++] = '#'; for(;;) { - if (c < 0x80) { + p1 = p; + + if (c < 128) { buf[ident_pos++] = c; } else { - ident_pos += utf8_encode((uint8_t*)buf + ident_pos, c); + ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c); } - c = *p; - p_next = p + 1; - if (c == '\\' && *p_next == 'u') { - c = lre_parse_escape(&p_next, true); - *pident_has_escape = true; - } else if (c >= 0x80) { - c = utf8_decode(p, &p_next); - /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ + c = *p1++; + if (c == '\\' && *p1 == 'u') { + c = lre_parse_escape(&p1, TRUE); + *pident_has_escape = TRUE; + } else if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); } if (!lre_js_is_ident_next(c)) break; - p = p_next; + p = p1; if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { - if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) + if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) { + atom = JS_ATOM_NULL; goto done; + } } } - /* buf is pure ASCII or UTF-8 encoded */ atom = JS_NewAtomLen(s->ctx, buf, ident_pos); done: if (unlikely(buf != ident_buf)) @@ -20719,25 +21834,20 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, static __exception int next_token(JSParseState *s) { - const uint8_t *p, *p_next; + const uint8_t *p; int c; - bool ident_has_escape; + BOOL ident_has_escape; JSAtom atom; - if (js_check_stack_overflow(s->ctx->rt, 1000)) { - JS_ThrowStackOverflow(s->ctx); - return -1; + if (js_check_stack_overflow(s->ctx->rt, 0)) { + return js_parse_error(s, "stack overflow"); } free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; - s->got_lf = false; - s->last_line_num = s->token.line_num; - s->last_col_num = s->token.col_num; + s->got_lf = FALSE; redo: - s->token.line_num = s->line_num; - s->token.col_num = s->col_num; s->token.ptr = p; c = *p; switch(c) { @@ -20755,7 +21865,7 @@ static __exception int next_token(JSParseState *s) break; case '\'': case '\"': - if (js_parse_string(s, c, true, p + 1, &s->token, &p)) + if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p)) goto fail; break; case '\r': /* accept DOS and MAC newline sequences */ @@ -20766,16 +21876,13 @@ static __exception int next_token(JSParseState *s) case '\n': p++; line_terminator: - s->eol = &p[-1]; - s->mark = p; - s->got_lf = true; - s->line_num++; + s->got_lf = TRUE; goto redo; case '\f': case '\v': case ' ': case '\t': - s->mark = ++p; + p++; goto redo; case '/': if (p[1] == '*') { @@ -20790,25 +21897,20 @@ static __exception int next_token(JSParseState *s) p += 2; break; } - if (*p == '\n') { - s->line_num++; - s->got_lf = true; /* considered as LF for ASI */ - s->eol = p++; - s->mark = p; - } else if (*p == '\r') { - s->got_lf = true; /* considered as LF for ASI */ + if (*p == '\n' || *p == '\r') { + s->got_lf = TRUE; /* considered as LF for ASI */ p++; } else if (*p >= 0x80) { - c = utf8_decode(p, &p); - /* ignore invalid UTF-8 in comments */ + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); if (c == CP_LS || c == CP_PS) { - s->got_lf = true; /* considered as LF for ASI */ + s->got_lf = TRUE; /* considered as LF for ASI */ + } else if (c == -1) { + p++; /* skip invalid UTF-8 */ } } else { p++; } } - s->mark = p; goto redo; } else if (p[1] == '/') { /* line comment */ @@ -20820,17 +21922,17 @@ static __exception int next_token(JSParseState *s) if (*p == '\r' || *p == '\n') break; if (*p >= 0x80) { - c = utf8_decode(p, &p); - /* ignore invalid UTF-8 in comments */ + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); /* LS or PS are considered as line terminator */ if (c == CP_LS || c == CP_PS) { break; + } else if (c == -1) { + p++; /* skip invalid UTF-8 */ } } else { p++; } } - s->mark = p; goto redo; } else if (p[1] == '=') { p += 2; @@ -20843,11 +21945,11 @@ static __exception int next_token(JSParseState *s) case '\\': if (p[1] == 'u') { const uint8_t *p1 = p + 1; - int c1 = lre_parse_escape(&p1, true); + int c1 = lre_parse_escape(&p1, TRUE); if (c1 >= 0 && lre_js_is_ident_first(c1)) { c = c1; p = p1; - ident_has_escape = true; + ident_has_escape = TRUE; goto has_ident; } else { /* XXX: syntax error? */ @@ -20871,39 +21973,37 @@ static __exception int next_token(JSParseState *s) case '_': case '$': /* identifier */ - s->mark = p; p++; - ident_has_escape = false; + ident_has_escape = FALSE; has_ident: - atom = parse_ident(s, &p, &ident_has_escape, c, false); + atom = parse_ident(s, &p, &ident_has_escape, c, FALSE); if (atom == JS_ATOM_NULL) goto fail; s->token.u.ident.atom = atom; s->token.u.ident.has_escape = ident_has_escape; - s->token.u.ident.is_reserved = false; + s->token.u.ident.is_reserved = FALSE; s->token.val = TOK_IDENT; update_token_ident(s); break; case '#': /* private name */ { + const uint8_t *p1; p++; - c = *p; - p_next = p + 1; - if (c == '\\' && *p_next == 'u') { - c = lre_parse_escape(&p_next, true); - } else if (c >= 0x80) { - c = utf8_decode(p, &p_next); - if (p_next == p + 1) - goto invalid_utf8; + p1 = p; + c = *p1++; + if (c == '\\' && *p1 == 'u') { + c = lre_parse_escape(&p1, TRUE); + } else if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); } if (!lre_js_is_ident_first(c)) { js_parse_error(s, "invalid first character of private name"); goto fail; } - p = p_next; - ident_has_escape = false; /* not used */ - atom = parse_ident(s, &p, &ident_has_escape, c, true); + p = p1; + ident_has_escape = FALSE; /* not used */ + atom = parse_ident(s, &p, &ident_has_escape, c, TRUE); if (atom == JS_ATOM_NULL) goto fail; s->token.u.ident.atom = atom; @@ -20924,8 +22024,8 @@ static __exception int next_token(JSParseState *s) break; case '0': /* in strict mode, octal literals are not accepted */ - if (is_digit(p[1]) && (s->cur_func->is_strict_mode)) { - js_parse_error(s, "Octal literals are not allowed in strict mode"); + if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) { + js_parse_error(s, "octal literals are deprecated in strict mode"); goto fail; } goto parse_number; @@ -20946,7 +22046,7 @@ static __exception int next_token(JSParseState *s) goto fail; /* reject `10instanceof Number` */ if (JS_VALUE_IS_NAN(ret) || - lre_js_is_ident_next(utf8_decode(p, &p1))) { + lre_js_is_ident_next(unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1))) { JS_FreeValue(s->ctx, ret); js_parse_error(s, "invalid number literal"); goto fail; @@ -21138,11 +22238,9 @@ static __exception int next_token(JSParseState *s) } break; default: - if (c >= 0x80) { /* non-ASCII code-point */ - c = utf8_decode(p, &p_next); - if (p_next == p + 1) - goto invalid_utf8; - p = p_next; + if (c >= 128) { + /* unicode value */ + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); switch(c) { case CP_PS: case CP_LS: @@ -21151,10 +22249,9 @@ static __exception int next_token(JSParseState *s) goto line_terminator; default: if (lre_is_space(c)) { - s->mark = p; goto redo; } else if (lre_js_is_ident_first(c)) { - ident_has_escape = false; + ident_has_escape = FALSE; goto has_ident; } else { js_parse_error(s, "unexpected character"); @@ -21167,153 +22264,18 @@ static __exception int next_token(JSParseState *s) p++; break; } - s->token.col_num = max_int(1, s->mark - s->eol); s->buf_ptr = p; // dump_token(s, &s->token); return 0; - invalid_utf8: - js_parse_error(s, "invalid UTF-8 sequence"); fail: s->token.val = TOK_ERROR; return -1; } -#endif // QJS_DISABLE_PARSER - -static int json_parse_error(JSParseState *s, const uint8_t *curp, const char *msg) -{ - const uint8_t *p, *line_start; - int position = curp - s->buf_start; - int line = 1; - for (line_start = p = s->buf_start; p < curp; p++) { - /* column count does not account for TABs nor wide characters */ - if (*p == '\r' || *p == '\n') { - p += 1 + (p[0] == '\r' && p[1] == '\n'); - line++; - line_start = p; - } - } - return js_parse_error(s, "%s in JSON at position %d (line %d column %d)", - msg, position, line, (int)(p - line_start) + 1); -} - -static int json_parse_string(JSParseState *s, const uint8_t **pp) -{ - const uint8_t *p, *p_next; - int i; - uint32_t c; - StringBuffer b_s, *b = &b_s; - - if (string_buffer_init(s->ctx, b, 32)) - goto fail; - - p = *pp; - for(;;) { - if (p >= s->buf_end) { - goto end_of_input; - } - c = *p++; - if (c == '"') - break; - if (c < 0x20) { - json_parse_error(s, p - 1, "Bad control character in string literal"); - goto fail; - } - if (c == '\\') { - c = *p++; - switch(c) { - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case '\"': break; - case '\\': break; - case '/': break; /* for v8 compatibility */ - case 'u': - c = 0; - for(i = 0; i < 4; i++) { - int h = from_hex(*p++); - if (h < 0) { - json_parse_error(s, p - 1, "Bad Unicode escape"); - goto fail; - } - c = (c << 4) | h; - } - break; - default: - if (p > s->buf_end) - goto end_of_input; - json_parse_error(s, p - 1, "Bad escaped character"); - goto fail; - } - } else - if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) { - json_parse_error(s, p - 1, "Bad UTF-8 sequence"); - goto fail; - } - p = p_next; - } - if (string_buffer_putc(b, c)) - goto fail; - } - s->token.val = TOK_STRING; - s->token.u.str.sep = '"'; - s->token.u.str.str = string_buffer_end(b); - *pp = p; - return 0; - - end_of_input: - js_parse_error(s, "Unexpected end of JSON input"); - fail: - string_buffer_free(b); - return -1; -} - -static int json_parse_number(JSParseState *s, const uint8_t **pp) -{ - const uint8_t *p = *pp; - const uint8_t *p_start = p; - - if (*p == '+' || *p == '-') - p++; - - if (!is_digit(*p)) - return js_parse_error(s, "Unexpected token '%c'", *p_start); - - if (p[0] == '0' && is_digit(p[1])) - return json_parse_error(s, p, "Unexpected number"); - - while (is_digit(*p)) - p++; - - if (*p == '.') { - p++; - if (!is_digit(*p)) - return json_parse_error(s, p, "Unterminated fractional number"); - while (is_digit(*p)) - p++; - } - if (*p == 'e' || *p == 'E') { - p++; - if (*p == '+' || *p == '-') - p++; - if (!is_digit(*p)) - return json_parse_error(s, p, "Exponent part is missing a number"); - while (is_digit(*p)) - p++; - } - s->token.val = TOK_NUMBER; - s->token.u.num.val = js_float64(strtod((const char *)p_start, NULL)); - *pp = p; - return 0; -} - /* 'c' is the first character. Return JS_ATOM_NULL in case of error */ +/* XXX: accept unicode identifiers as JSON5 ? */ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) { const uint8_t *p; @@ -21328,8 +22290,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) for(;;) { buf[ident_pos++] = c; c = *p; - if (c >= 128 || - !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1)) + if (c >= 128 || !lre_is_id_continue_byte(c)) break; p++; if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { @@ -21339,7 +22300,6 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) } } } - /* buf contains pure ASCII */ atom = JS_NewAtomLen(s->ctx, buf, ident_pos); done: if (unlikely(buf != ident_buf)) @@ -21348,25 +22308,192 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) return atom; } -static __exception int json_next_token(JSParseState *s) +static int json_parse_string(JSParseState *s, const uint8_t **pp, int sep) { const uint8_t *p, *p_next; + int i; + uint32_t c; + StringBuffer b_s, *b = &b_s; + + if (string_buffer_init(s->ctx, b, 32)) + goto fail; + + p = *pp; + for(;;) { + if (p >= s->buf_end) { + goto end_of_input; + } + c = *p++; + if (c == sep) + break; + if (c < 0x20) { + js_parse_error_pos(s, p - 1, "Bad control character in string literal"); + goto fail; + } + if (c == '\\') { + c = *p++; + switch(c) { + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case '\\': break; + case '/': break; + case 'u': + c = 0; + for(i = 0; i < 4; i++) { + int h = from_hex(*p++); + if (h < 0) { + js_parse_error_pos(s, p - 1, "Bad Unicode escape"); + goto fail; + } + c = (c << 4) | h; + } + break; + case '\n': + if (s->ext_json) + continue; + goto bad_escape; + case 'v': + if (s->ext_json) { + c = '\v'; + break; + } + goto bad_escape; + default: + if (c == sep) + break; + if (p > s->buf_end) + goto end_of_input; + bad_escape: + js_parse_error_pos(s, p - 1, "Bad escaped character"); + goto fail; + } + } else + if (c >= 0x80) { + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); + if (c > 0x10FFFF) { + js_parse_error_pos(s, p - 1, "Bad UTF-8 sequence"); + goto fail; + } + p = p_next; + } + if (string_buffer_putc(b, c)) + goto fail; + } + s->token.val = TOK_STRING; + s->token.u.str.sep = sep; + s->token.u.str.str = string_buffer_end(b); + *pp = p; + return 0; + + end_of_input: + js_parse_error(s, "Unexpected end of JSON input"); + fail: + string_buffer_free(b); + return -1; +} + +static int json_parse_number(JSParseState *s, const uint8_t **pp) +{ + const uint8_t *p = *pp; + const uint8_t *p_start = p; + int radix; + double d; + JSATODTempMem atod_mem; + + if (*p == '+' || *p == '-') + p++; + + if (!is_digit(*p)) { + if (s->ext_json) { + if (strstart((const char *)p, "Infinity", (const char **)&p)) { + d = INF; + if (*p_start == '-') + d = -d; + goto done; + } else if (strstart((const char *)p, "NaN", (const char **)&p)) { + d = NAN; + goto done; + } else if (*p != '.') { + goto unexpected_token; + } + } else { + goto unexpected_token; + } + } + + if (p[0] == '0') { + if (s->ext_json) { + /* also accepts base 16, 8 and 2 prefix for integers */ + radix = 10; + if (p[1] == 'x' || p[1] == 'X') { + p += 2; + radix = 16; + } else if ((p[1] == 'o' || p[1] == 'O')) { + p += 2; + radix = 8; + } else if ((p[1] == 'b' || p[1] == 'B')) { + p += 2; + radix = 2; + } + if (radix != 10) { + /* prefix is present */ + if (to_digit(*p) >= radix) { + unexpected_token: + return js_parse_error_pos(s, p, "Unexpected token '%c'", *p); + } + d = js_atod((const char *)p_start, (const char **)&p, 0, + JS_ATOD_INT_ONLY | JS_ATOD_ACCEPT_BIN_OCT, &atod_mem); + goto done; + } + } + if (is_digit(p[1])) + return js_parse_error_pos(s, p, "Unexpected number"); + } + + while (is_digit(*p)) + p++; + + if (*p == '.') { + p++; + if (!is_digit(*p)) + return js_parse_error_pos(s, p, "Unterminated fractional number"); + while (is_digit(*p)) + p++; + } + if (*p == 'e' || *p == 'E') { + p++; + if (*p == '+' || *p == '-') + p++; + if (!is_digit(*p)) + return js_parse_error_pos(s, p, "Exponent part is missing a number"); + while (is_digit(*p)) + p++; + } + d = js_atod((const char *)p_start, NULL, 10, 0, &atod_mem); + done: + s->token.val = TOK_NUMBER; + s->token.u.num.val = JS_NewFloat64(s->ctx, d); + *pp = p; + return 0; +} + +static __exception int json_next_token(JSParseState *s) +{ + const uint8_t *p; int c; JSAtom atom; - if (js_check_stack_overflow(s->ctx->rt, 1000)) { - JS_ThrowStackOverflow(s->ctx); - return -1; + if (js_check_stack_overflow(s->ctx->rt, 0)) { + return js_parse_error(s, "stack overflow"); } free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; - s->last_line_num = s->token.line_num; - s->last_col_num = s->token.col_num; redo: - s->token.line_num = s->line_num; - s->token.col_num = s->col_num; s->token.ptr = p; c = *p; switch(c) { @@ -21378,11 +22505,14 @@ static __exception int json_next_token(JSParseState *s) } break; case '\'': - /* JSON does not accept single quoted strings */ - goto def_token; + if (!s->ext_json) { + /* JSON does not accept single quoted strings */ + goto def_token; + } + /* fall through */ case '\"': p++; - if (json_parse_string(s, &p)) + if (json_parse_string(s, &p, c)) goto fail; break; case '\r': /* accept DOS and MAC newline sequences */ @@ -21391,22 +22521,71 @@ static __exception int json_next_token(JSParseState *s) } /* fall thru */ case '\n': - s->line_num++; - s->eol = p++; - s->mark = p; + p++; goto redo; case '\f': case '\v': - /* JSONWhitespace does not match , nor */ - goto def_token; + if (!s->ext_json) { + /* JSONWhitespace does not match , nor */ + goto def_token; + } + /* fall through */ case ' ': case '\t': p++; - s->mark = p; goto redo; case '/': - /* JSON does not accept comments */ - goto def_token; + if (!s->ext_json) { + /* JSON does not accept comments */ + goto def_token; + } + if (p[1] == '*') { + /* comment */ + p += 2; + for(;;) { + if (*p == '\0' && p >= s->buf_end) { + js_parse_error(s, "unexpected end of comment"); + goto fail; + } + if (p[0] == '*' && p[1] == '/') { + p += 2; + break; + } + if (*p >= 0x80) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if (c == -1) { + p++; /* skip invalid UTF-8 */ + } + } else { + p++; + } + } + goto redo; + } else if (p[1] == '/') { + /* line comment */ + p += 2; + for(;;) { + if (*p == '\0' && p >= s->buf_end) + break; + if (*p == '\r' || *p == '\n') + break; + if (*p >= 0x80) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + /* LS or PS are considered as line terminator */ + if (c == CP_LS || c == CP_PS) { + break; + } else if (c == -1) { + p++; /* skip invalid UTF-8 */ + } + } else { + p++; + } + } + goto redo; + } else { + goto def_token; + } + break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': @@ -21423,28 +22602,26 @@ static __exception int json_next_token(JSParseState *s) case 'Y': case 'Z': case '_': case '$': - /* identifier : only pure ascii characters are accepted */ p++; atom = json_parse_ident(s, &p, c); if (atom == JS_ATOM_NULL) goto fail; s->token.u.ident.atom = atom; - s->token.u.ident.has_escape = false; - s->token.u.ident.is_reserved = false; + s->token.u.ident.has_escape = FALSE; + s->token.u.ident.is_reserved = FALSE; s->token.val = TOK_IDENT; break; - case '-': - if (!is_digit(p[1])) { - json_parse_error(s, p, "No number after minus sign"); - goto fail; - } + case '+': + if (!s->ext_json) + goto def_token; goto parse_number; + case '.': + if (s->ext_json && is_digit(p[1])) + goto parse_number; + else + goto def_token; + case '-': case '0': - if (is_digit(p[1])) { - json_parse_error(s, p, "Unexpected number"); - goto fail; - } - goto parse_number; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -21454,16 +22631,8 @@ static __exception int json_next_token(JSParseState *s) goto fail; break; default: - if (c >= 0x80) { - c = utf8_decode(p, &p_next); - if (p_next == p + 1) { - js_parse_error(s, "Unexpected token '\\x%02x' in JSON", *p); - } else { - if (c > 0xFFFF) { - c = get_hi_surrogate(c); - } - js_parse_error(s, "Unexpected token '\\u%04x' in JSON", c); - } + if (c >= 128) { + js_parse_error(s, "unexpected character"); goto fail; } def_token: @@ -21471,7 +22640,6 @@ static __exception int json_next_token(JSParseState *s) p++; break; } - s->token.col_num = s->mark - s->eol; s->buf_ptr = p; // dump_token(s, &s->token); @@ -21482,12 +22650,30 @@ static __exception int json_next_token(JSParseState *s) return -1; } -#ifndef QJS_DISABLE_PARSER - -/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is - only set if TOK_IMPORT is returned */ -/* XXX: handle all unicode cases */ -static int simple_next_token(const uint8_t **pp, bool no_line_terminator) +static int match_identifier(const uint8_t *p, const char *s) { + uint32_t c; + while (*s) { + if ((uint8_t)*s++ != *p++) + return 0; + } + c = *p; + if (c >= 128) + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + return !lre_js_is_ident_next(c); +} + +/* simple_next_token() is used to check for the next token in simple cases. + It is only used for ':' and '=>', 'let' or 'function' look-ahead. + (*pp) is only set if TOK_IMPORT is returned for JS_DetectModule() + Whitespace and comments are skipped correctly. + Then the next token is analyzed, only for specific words. + Return values: + - '\n' if !no_line_terminator + - TOK_ARROW, TOK_IN, TOK_IMPORT, TOK_OF, TOK_EXPORT, TOK_FUNCTION + - TOK_IDENT is returned for other identifiers and keywords + - otherwise the next character or unicode codepoint is returned. + */ +static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) { const uint8_t *p; uint32_t c; @@ -21530,43 +22716,49 @@ static int simple_next_token(const uint8_t **pp, bool no_line_terminator) if (*p == '>') return TOK_ARROW; break; + case 'i': + if (match_identifier(p, "n")) + return TOK_IN; + if (match_identifier(p, "mport")) { + *pp = p + 5; + return TOK_IMPORT; + } + return TOK_IDENT; + case 'o': + if (match_identifier(p, "f")) + return TOK_OF; + return TOK_IDENT; + case 'e': + if (match_identifier(p, "xport")) + return TOK_EXPORT; + return TOK_IDENT; + case 'f': + if (match_identifier(p, "unction")) + return TOK_FUNCTION; + return TOK_IDENT; + case '\\': + if (*p == 'u') { + if (lre_js_is_ident_first(lre_parse_escape(&p, TRUE))) + return TOK_IDENT; + } + break; default: - if (lre_js_is_ident_first(c)) { - if (c == 'i') { - if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) { - return TOK_IN; - } - if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' && - p[3] == 'r' && p[4] == 't' && - !lre_js_is_ident_next(p[5])) { - *pp = p + 5; - return TOK_IMPORT; - } - } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) { - return TOK_OF; - } else if (c == 'e' && - p[0] == 'x' && p[1] == 'p' && p[2] == 'o' && - p[3] == 'r' && p[4] == 't' && - !lre_js_is_ident_next(p[5])) { - *pp = p + 5; - return TOK_EXPORT; - } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && - p[2] == 'c' && p[3] == 't' && p[4] == 'i' && - p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) { - return TOK_FUNCTION; - } else if (c == 'a' && p[0] == 'w' && p[1] == 'a' && - p[2] == 'i' && p[3] == 't' && !lre_js_is_ident_next(p[4])) { - return TOK_AWAIT; - } - return TOK_IDENT; + if (c >= 128) { + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p); + if (no_line_terminator && (c == CP_PS || c == CP_LS)) + return '\n'; } + if (lre_is_space(c)) + continue; + if (lre_js_is_ident_first(c)) + return TOK_IDENT; break; } return c; } } -static int peek_token(JSParseState *s, bool no_line_terminator) +static int peek_token(JSParseState *s, BOOL no_line_terminator) { const uint8_t *p = s->buf_ptr; return simple_next_token(&p, no_line_terminator); @@ -21583,10 +22775,12 @@ static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end) if (*p == '\n' || *p == '\r') { break; } else if (*p >= 0x80) { - c = utf8_decode(p, &p); - /* purposely ignore UTF-8 encoding errors in this comment line */ - if (c == CP_LS || c == CP_PS) + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if (c == CP_LS || c == CP_PS) { break; + } else if (c == -1) { + p++; /* skip invalid UTF-8 */ + } } else { p++; } @@ -21595,6 +22789,29 @@ static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end) } } +/* return true if 'input' contains the source of a module + (heuristic). 'input' must be a zero terminated. + + Heuristic: skip comments and expect 'import' keyword not followed + by '(' or '.' or export keyword. +*/ +BOOL JS_DetectModule(const char *input, size_t input_len) +{ + const uint8_t *p = (const uint8_t *)input; + int tok; + + skip_shebang(&p, p + input_len); + switch(simple_next_token(&p, FALSE)) { + case TOK_IMPORT: + tok = simple_next_token(&p, FALSE); + return (tok != '.' && tok != '('); + case TOK_EXPORT: + return TRUE; + default: + return FALSE; + } +} + static inline int get_prev_opcode(JSFunctionDef *fd) { if (fd->last_opcode_pos < 0 || dbuf_error(&fd->byte_code)) return OP_invalid; @@ -21602,7 +22819,7 @@ static inline int get_prev_opcode(JSFunctionDef *fd) { return fd->byte_code.buf[fd->last_opcode_pos]; } -static bool js_is_live_code(JSParseState *s) { +static BOOL js_is_live_code(JSParseState *s) { switch (get_prev_opcode(s->cur_func)) { case OP_tail_call: case OP_tail_call_method: @@ -21612,12 +22829,14 @@ static bool js_is_live_code(JSParseState *s) { case OP_throw: case OP_throw_error: case OP_goto: +#if SHORT_OPCODES case OP_goto8: case OP_goto16: +#endif case OP_ret: - return false; + return FALSE; default: - return true; + return TRUE; } } @@ -21636,14 +22855,16 @@ static void emit_u32(JSParseState *s, uint32_t val) dbuf_put_u32(&s->cur_func->byte_code, val); } -static void emit_source_loc(JSParseState *s) +static void emit_source_pos(JSParseState *s, const uint8_t *source_ptr) { JSFunctionDef *fd = s->cur_func; DynBuf *bc = &fd->byte_code; - dbuf_putc(bc, OP_source_loc); - dbuf_put_u32(bc, s->token.line_num); - dbuf_put_u32(bc, s->token.col_num); + if (unlikely(fd->last_opcode_source_ptr != source_ptr)) { + dbuf_putc(bc, OP_line_num); + dbuf_put_u32(bc, source_ptr - s->buf_start); + fd->last_opcode_source_ptr = source_ptr; + } } static void emit_op(JSParseState *s, uint8_t val) @@ -21658,7 +22879,7 @@ static void emit_op(JSParseState *s, uint8_t val) static void emit_atom(JSParseState *s, JSAtom name) { DynBuf *bc = &s->cur_func->byte_code; - if (dbuf_realloc(bc, bc->size + 4)) + if (dbuf_claim(bc, 4)) return; /* not enough memory : don't duplicate the atom */ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name)); bc->size += 4; @@ -21681,8 +22902,8 @@ static int new_label_fd(JSFunctionDef *fd) LabelSlot *ls; if (js_resize_array(fd->ctx, (void *)&fd->label_slots, - sizeof(fd->label_slots[0]), - &fd->label_size, fd->label_count + 1)) + sizeof(fd->label_slots[0]), + &fd->label_size, fd->label_count + 1)) return -1; label = fd->label_count++; ls = &fd->label_slots[label]; @@ -21754,15 +22975,15 @@ static int cpool_add(JSParseState *s, JSValue val) return fd->cpool_count - 1; } -static __exception int emit_push_const(JSParseState *s, JSValue val, - bool as_atom) +static __exception int emit_push_const(JSParseState *s, JSValueConst val, + BOOL as_atom) { int idx; if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING && as_atom) { JSAtom atom; /* warning: JS_NewAtomStr frees the string value */ - js_dup(val); + JS_DupValue(s->ctx, val); atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val)); if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) { emit_op(s, OP_push_atom_value); @@ -21771,7 +22992,7 @@ static __exception int emit_push_const(JSParseState *s, JSValue val, } } - idx = cpool_add(s, js_dup(val)); + idx = cpool_add(s, JS_DupValue(s->ctx, val)); if (idx < 0) return -1; emit_op(s, OP_push_const); @@ -21779,86 +23000,6 @@ static __exception int emit_push_const(JSParseState *s, JSValue val, return 0; } -// perl hash; variation of k&r hash with a different magic multiplier -// and a final shuffle to improve distribution of the low-order bits -static uint32_t hash_bytes(uint32_t h, const void *b, size_t n) -{ - const char *p; - - for (p = b; p < (char *)b + n; p++) - h = 33*h + *p; - h += h >> 5; - return h; -} - -static uint32_t hash_atom(JSAtom atom) -{ - return hash_bytes(0, &atom, sizeof(atom)); -} - -// caveat emptor: the table size must be a power of two in order for -// masking to work, and the load factor constant must be an odd number (5) -// -// f(n)=n+n/t is used to estimate the load factor but changing t to an -// even number introduces gaps in the output of f, sometimes "jumping" -// over the next power of two; it's at powers of two when the hash table -// must be resized -static int update_var_htab(JSContext *ctx, JSFunctionDef *fd) -{ - uint32_t i, j, k, m, *p; - - if (fd->var_count < 27) // 27 + 27/5 == 32 - return 0; - k = fd->var_count - 1; - m = fd->var_count + fd->var_count/5; - if (m & (m - 1)) // unless power of two - goto insert; - m *= 2; - p = js_realloc(ctx, fd->vars_htab, m * sizeof(*fd->vars_htab)); - if (!p) - return -1; - for (i = 0; i < m; i++) - p[i] = UINT32_MAX; - fd->vars_htab = p; - k = 0; - m--; -insert: - m = UINT32_MAX >> clz32(m); - do { - i = hash_atom(fd->vars[k].var_name); - j = 1; - for (;;) { - p = &fd->vars_htab[i & m]; - if (*p == UINT32_MAX) - break; - i += j; - j += 1; // quadratic probing - } - *p = k++; - } while (k < (uint32_t)fd->var_count); - return 0; -} - -static int find_var_htab(JSFunctionDef *fd, JSAtom var_name) -{ - uint32_t i, j, m, *p; - - i = hash_atom(var_name); - j = 1; - m = fd->var_count + fd->var_count/5; - m = UINT32_MAX >> clz32(m); - for (;;) { - p = &fd->vars_htab[i & m]; - if (*p == UINT32_MAX) - return -1; - if (fd->vars[*p].var_name == var_name) - return *p; - i += j; - j += 1; // quadratic probing - } - return -1; // pacify compiler -} - /* return the variable index or -1 if not found, add ARGUMENT_VAR_OFFSET for argument variables */ static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) @@ -21873,24 +23014,11 @@ static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) { - JSVarDef *vd; int i; - - if (fd->vars_htab) { - i = find_var_htab(fd, name); - if (i == -1) - goto not_found; - vd = &fd->vars[i]; - if (fd->vars[i].scope_level == 0) - return i; - } for(i = fd->var_count; i-- > 0;) { - vd = &fd->vars[i]; - if (vd->var_name == name) - if (vd->scope_level == 0) - return i; + if (fd->vars[i].var_name == name && fd->vars[i].scope_level == 0) + return i; } -not_found: return find_arg(ctx, fd, name); } @@ -21911,15 +23039,15 @@ static int find_var_in_scope(JSContext *ctx, JSFunctionDef *fd, /* return true if scope == parent_scope or if scope is a child of parent_scope */ -static bool is_child_scope(JSContext *ctx, JSFunctionDef *fd, +static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd, int scope, int parent_scope) { while (scope >= 0) { if (scope == parent_scope) - return true; + return TRUE; scope = fd->scopes[scope].parent; } - return false; + return FALSE; } /* find a 'var' declaration in the same scope or a child scope */ @@ -21961,7 +23089,7 @@ static JSGlobalVar *find_lexical_global_var(JSFunctionDef *fd, JSAtom name) } static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name, - int scope_idx, bool check_catch_var) + int scope_idx, BOOL check_catch_var) { while (scope_idx >= 0) { JSVarDef *vd = &fd->vars[scope_idx]; @@ -22053,9 +23181,7 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) /* the local variable indexes are currently stored on 16 bits */ if (fd->var_count >= JS_MAX_LOCAL_VARS) { - // XXX: add_var() should take JSParseState *s and use js_parse_error - JS_ThrowSyntaxError(ctx, "too many variables declared (only %d allowed)", - JS_MAX_LOCAL_VARS - 1); + JS_ThrowInternalError(ctx, "too many local variables"); return -1; } if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]), @@ -22065,8 +23191,6 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) memset(vd, 0, sizeof(*vd)); vd->var_name = JS_DupAtom(ctx, name); vd->func_pool_idx = -1; - if (update_var_htab(ctx, fd)) - return -1; return fd->var_count - 1; } @@ -22091,8 +23215,8 @@ static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) { fd->func_var_idx = idx; fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME; - if (fd->is_strict_mode) - fd->vars[idx].is_const = true; + if (fd->js_mode & JS_MODE_STRICT) + fd->vars[idx].is_const = TRUE; } return idx; } @@ -22123,7 +23247,7 @@ static int add_arguments_arg(JSContext *ctx, JSFunctionDef *fd) fd->vars[idx].scope_next = fd->scopes[ARG_SCOPE_INDEX].first; fd->scopes[ARG_SCOPE_INDEX].first = idx; fd->vars[idx].scope_level = ARG_SCOPE_INDEX; - fd->vars[idx].is_lexical = true; + fd->vars[idx].is_lexical = TRUE; fd->arguments_arg_idx = idx; } @@ -22137,9 +23261,7 @@ static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) /* the local variable indexes are currently stored on 16 bits */ if (fd->arg_count >= JS_MAX_LOCAL_VARS) { - // XXX: add_arg() should take JSParseState *s and use js_parse_error - JS_ThrowSyntaxError(ctx, "too many parameters in function definition (only %d allowed)", - JS_MAX_LOCAL_VARS - 1); + JS_ThrowInternalError(ctx, "too many arguments"); return -1; } if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]), @@ -22164,9 +23286,9 @@ static JSGlobalVar *add_global_var(JSContext *ctx, JSFunctionDef *s, return NULL; hf = &s->global_vars[s->global_var_count++]; hf->cpool_idx = -1; - hf->force_init = false; - hf->is_lexical = false; - hf->is_const = false; + hf->force_init = FALSE; + hf->is_lexical = FALSE; + hf->is_const = FALSE; hf->scope_level = s->scope_level; hf->var_name = JS_DupAtom(ctx, name); return hf; @@ -22198,13 +23320,13 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, case JS_VAR_DEF_CONST: case JS_VAR_DEF_FUNCTION_DECL: case JS_VAR_DEF_NEW_FUNCTION_DECL: - idx = find_lexical_decl(ctx, fd, name, fd->scope_first, true); + idx = find_lexical_decl(ctx, fd, name, fd->scope_first, TRUE); if (idx >= 0) { if (idx < GLOBAL_VAR_OFFSET) { if (fd->vars[idx].scope_level == fd->scope_level) { /* same scope: in non strict mode, functions can be redefined (annex B.3.3.4). */ - if (!(!fd->is_strict_mode && + if (!(!(fd->js_mode & JS_MODE_STRICT) && var_def_type == JS_VAR_DEF_FUNCTION_DECL && fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) { goto redef_lex_error; @@ -22249,7 +23371,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, hf = add_global_var(s->ctx, fd, name); if (!hf) return -1; - hf->is_lexical = true; + hf->is_lexical = TRUE; hf->is_const = (var_def_type == JS_VAR_DEF_CONST); idx = GLOBAL_VAR_OFFSET; } else { @@ -22275,7 +23397,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, case JS_VAR_DEF_VAR: if (find_lexical_decl(ctx, fd, name, fd->scope_first, - false) >= 0) { + FALSE) >= 0) { invalid_lexical_redefinition: /* error to redefine a var that inside a lexical scope */ return js_parse_error(s, "invalid redefinition of lexical identifier"); @@ -22312,7 +23434,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, /* add a private field variable in the current scope */ static int add_private_class_field(JSParseState *s, JSFunctionDef *fd, - JSAtom name, JSVarKindEnum var_kind, bool is_static) + JSAtom name, JSVarKindEnum var_kind, BOOL is_static) { JSContext *ctx = s->ctx; JSVarDef *vd; @@ -22332,16 +23454,13 @@ static __exception int js_parse_expr(JSParseState *s); static __exception int js_parse_function_decl(JSParseState *s, JSParseFunctionEnum func_type, JSFunctionKindEnum func_kind, - JSAtom func_name, const uint8_t *ptr, - int start_line, int start_col); + JSAtom func_name, const uint8_t *ptr); static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s); static __exception int js_parse_function_decl2(JSParseState *s, JSParseFunctionEnum func_type, JSFunctionKindEnum func_kind, JSAtom func_name, const uint8_t *ptr, - int function_line_num, - int function_col_num, JSParseExportEnum export_flag, JSFunctionDef **pfd); static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags); @@ -22357,7 +23476,7 @@ static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m, JSExportTypeEnum export_type); /* Note: all the fields are already sealed except length */ -static int seal_template_obj(JSContext *ctx, JSValue obj) +static int seal_template_obj(JSContext *ctx, JSValueConst obj) { JSObject *p; JSShapeProperty *prs; @@ -22369,7 +23488,7 @@ static int seal_template_obj(JSContext *ctx, JSValue obj) prs->flags & ~(JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE))) return -1; } - p->extensible = false; + p->extensible = FALSE; return 0; } @@ -22408,14 +23527,14 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) cooked = s->token; if (call) { if (JS_DefinePropertyValueUint32(ctx, raw_array, depth, - js_dup(s->token.u.str.str), + JS_DupValue(ctx, s->token.u.str.str), JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) { return -1; } /* re-parse the string with escape sequences but do not throw a syntax error if it contains invalid sequences */ - if (js_parse_string(s, '`', false, p, &cooked, &p)) { + if (js_parse_string(s, '`', FALSE, p, &cooked, &p)) { cooked.u.str.str = JS_UNDEFINED; } if (JS_DefinePropertyValueUint32(ctx, template_object, depth, @@ -22430,7 +23549,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) */ JS_FreeValue(ctx, s->token.u.str.str); s->token.u.str.str = JS_UNDEFINED; - if (js_parse_string(s, '`', true, p, &cooked, &p)) + if (js_parse_string(s, '`', TRUE, p, &cooked, &p)) return -1; str = JS_VALUE_GET_STRING(cooked.u.str.str); if (str->len != 0 || depth == 0) { @@ -22463,9 +23582,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) free_token(s, &s->token); /* Resume TOK_TEMPLATE parsing (s->token.line_num and * s->token.ptr are OK) */ - s->got_lf = false; - s->last_line_num = s->token.line_num; - s->last_col_num = s->token.col_num; + s->got_lf = FALSE; if (js_parse_template_part(s, s->buf_ptr)) return -1; } @@ -22496,7 +23613,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) #define PROP_TYPE_PRIVATE (1 << 4) -static bool token_is_ident(int tok) +static BOOL token_is_ident(int tok) { /* Accept keywords and reserved words as property names */ return (tok == TOK_IDENT || @@ -22507,26 +23624,31 @@ static bool token_is_ident(int tok) /* if the property is an expression, name = JS_ATOM_NULL */ static int __exception js_parse_property_name(JSParseState *s, JSAtom *pname, - bool allow_method, bool allow_var, - bool allow_private) + BOOL allow_method, BOOL allow_var, + BOOL allow_private) { int is_private = 0; - bool is_non_reserved_ident; + BOOL is_non_reserved_ident; JSAtom name; int prop_type; prop_type = PROP_TYPE_IDENT; if (allow_method) { - if (token_is_pseudo_keyword(s, JS_ATOM_get) - || token_is_pseudo_keyword(s, JS_ATOM_set)) { + /* if allow_private is true (for class field parsing) and + get/set is following by ';' (or LF with ASI), then it + is a field name */ + if ((token_is_pseudo_keyword(s, JS_ATOM_get) || + token_is_pseudo_keyword(s, JS_ATOM_set)) && + (!allow_private || peek_token(s, TRUE) != '\n')) { /* get x(), set x() */ name = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) goto fail1; if (s->token.val == ':' || s->token.val == ',' || s->token.val == '}' || s->token.val == '(' || - s->token.val == '=' || s->token.val == ';') { - is_non_reserved_ident = true; + s->token.val == '=' || + (s->token.val == ';' && allow_private)) { + is_non_reserved_ident = TRUE; goto ident_found; } prop_type = PROP_TYPE_GET + (name == JS_ATOM_set); @@ -22536,14 +23658,14 @@ static int __exception js_parse_property_name(JSParseState *s, goto fail; prop_type = PROP_TYPE_STAR; } else if (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) != '\n') { + peek_token(s, TRUE) != '\n') { name = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) goto fail1; if (s->token.val == ':' || s->token.val == ',' || s->token.val == '}' || s->token.val == '(' || - s->token.val == '=' || s->token.val == ';') { - is_non_reserved_ident = true; + s->token.val == '=') { + is_non_reserved_ident = TRUE; goto ident_found; } JS_FreeAtom(s->ctx, name); @@ -22590,7 +23712,7 @@ static int __exception js_parse_property_name(JSParseState *s, } else if (s->token.val == '[') { if (next_token(s)) goto fail; - if (js_parse_expr(s)) + if (js_parse_assign_expr(s)) goto fail; if (js_parse_expect(s, ']')) goto fail; @@ -22620,44 +23742,26 @@ static int __exception js_parse_property_name(JSParseState *s, } typedef struct JSParsePos { - int last_line_num; - int last_col_num; - int line_num; - int col_num; - bool got_lf; + BOOL got_lf; const uint8_t *ptr; - const uint8_t *eol; - const uint8_t *mark; } JSParsePos; static int js_parse_get_pos(JSParseState *s, JSParsePos *sp) { - sp->last_line_num = s->last_line_num; - sp->last_col_num = s->last_col_num; - sp->line_num = s->token.line_num; - sp->col_num = s->token.col_num; sp->ptr = s->token.ptr; - sp->eol = s->eol; - sp->mark = s->mark; sp->got_lf = s->got_lf; return 0; } static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp) { - s->token.line_num = sp->last_line_num; - s->token.col_num = sp->last_col_num; - s->line_num = sp->line_num; - s->col_num = sp->col_num; s->buf_ptr = sp->ptr; - s->eol = sp->eol; - s->mark = sp->mark; s->got_lf = sp->got_lf; return next_token(s); } -/* return true if a regexp literal is allowed after this token */ -static bool is_regexp_allowed(int tok) +/* return TRUE if a regexp literal is allowed after this token */ +static BOOL is_regexp_allowed(int tok) { switch (tok) { case TOK_NUMBER: @@ -22673,9 +23777,9 @@ static bool is_regexp_allowed(int tok) case ']': case '}': /* XXX: regexp may occur after */ case TOK_IDENT: - return false; + return FALSE; default: - return true; + return TRUE; } } @@ -22683,17 +23787,29 @@ static bool is_regexp_allowed(int tok) #define SKIP_HAS_ELLIPSIS (1 << 1) #define SKIP_HAS_ASSIGNMENT (1 << 2) +static BOOL has_lf_in_range(const uint8_t *p1, const uint8_t *p2) +{ + const uint8_t *tmp; + if (p1 > p2) { + tmp = p1; + p1 = p2; + p2 = tmp; + } + return (memchr(p1, '\n', p2 - p1) != NULL); +} + /* XXX: improve speed with early bailout */ /* XXX: no longer works if regexps are present. Could use previous regexp parsing heuristics to handle most cases */ -static int js_parse_skip_parens_token(JSParseState *s, int *pbits, bool no_line_terminator) +static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_terminator) { char state[256]; size_t level = 0; JSParsePos pos; int last_tok, tok = TOK_EOF; int c, tok_len, bits = 0; - + const uint8_t *last_token_ptr; + /* protect from underflow */ state[level++] = 0; @@ -22723,9 +23839,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, bool no_line_ free_token(s, &s->token); /* Resume TOK_TEMPLATE parsing (s->token.line_num and * s->token.ptr are OK) */ - s->got_lf = false; - s->last_line_num = s->token.line_num; - s->last_col_num = s->token.col_num; + s->got_lf = FALSE; if (js_parse_template_part(s, s->buf_ptr)) goto done; goto handle_template; @@ -22782,6 +23896,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, bool no_line_ } else { last_tok = s->token.val; } + last_token_ptr = s->token.ptr; if (next_token(s)) { /* XXX: should clear the exception generated by next_token() */ break; @@ -22790,7 +23905,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, bool no_line_ tok = s->token.val; if (token_is_pseudo_keyword(s, JS_ATOM_of)) tok = TOK_OF; - if (no_line_terminator && s->last_line_num != s->token.line_num) + if (no_line_terminator && has_lf_in_range(last_token_ptr, s->token.ptr)) tok = '\n'; break; } @@ -22857,19 +23972,17 @@ static __exception int js_parse_object_literal(JSParseState *s) { JSAtom name = JS_ATOM_NULL; const uint8_t *start_ptr; - int start_line, start_col, prop_type; - bool has_proto; + int prop_type; + BOOL has_proto; if (next_token(s)) goto fail; /* XXX: add an initial length that will be patched back */ emit_op(s, OP_object); - has_proto = false; + has_proto = FALSE; while (s->token.val != '}') { /* specific case for getter/setter */ start_ptr = s->token.ptr; - start_line = s->token.line_num; - start_col = s->token.col_num; if (s->token.val == TOK_ELLIPSIS) { if (next_token(s)) @@ -22884,7 +23997,7 @@ static __exception int js_parse_object_literal(JSParseState *s) goto next; } - prop_type = js_parse_property_name(s, &name, true, true, false); + prop_type = js_parse_property_name(s, &name, TRUE, TRUE, FALSE); if (prop_type < 0) goto fail; @@ -22896,7 +24009,7 @@ static __exception int js_parse_object_literal(JSParseState *s) emit_op(s, OP_define_field); emit_atom(s, name); } else if (s->token.val == '(') { - bool is_getset = (prop_type == PROP_TYPE_GET || + BOOL is_getset = (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET); JSParseFunctionEnum func_type; JSFunctionKindEnum func_kind; @@ -22915,7 +24028,7 @@ static __exception int js_parse_object_literal(JSParseState *s) func_kind = JS_FUNC_ASYNC_GENERATOR; } if (js_parse_function_decl(s, func_type, func_kind, JS_ATOM_NULL, - start_ptr, start_line, start_col)) + start_ptr)) goto fail; if (name == JS_ATOM_NULL) { emit_op(s, OP_define_method_computed); @@ -22931,6 +24044,10 @@ static __exception int js_parse_object_literal(JSParseState *s) } emit_u8(s, op_flags | OP_DEFINE_METHOD_ENUMERABLE); } else { + if (name == JS_ATOM_NULL) { + /* must be done before evaluating expr */ + emit_op(s, OP_to_propkey); + } if (js_parse_expect(s, ':')) goto fail; if (js_parse_assign_expr(s)) @@ -22945,7 +24062,7 @@ static __exception int js_parse_object_literal(JSParseState *s) goto fail; } emit_op(s, OP_set_proto); - has_proto = true; + has_proto = TRUE; } else { set_object_name(s, name); emit_op(s, OP_define_field); @@ -22978,12 +24095,77 @@ static __exception int js_parse_object_literal(JSParseState *s) #define PF_POW_FORBIDDEN (1 << 3) static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags); +static void emit_class_field_init(JSParseState *s); +static JSFunctionDef *js_new_function_def(JSContext *ctx, + JSFunctionDef *parent, + BOOL is_eval, + BOOL is_func_expr, + const char *filename, + const uint8_t *source_ptr, + GetLineColCache *get_line_col_cache); +static void emit_return(JSParseState *s, BOOL hasval); static __exception int js_parse_left_hand_side_expr(JSParseState *s) { return js_parse_postfix_expr(s, PF_POSTFIX_CALL); } +static __exception int js_parse_class_default_ctor(JSParseState *s, + BOOL has_super, + JSFunctionDef **pfd) +{ + JSParseFunctionEnum func_type; + JSFunctionDef *fd = s->cur_func; + int idx; + + fd = js_new_function_def(s->ctx, fd, FALSE, FALSE, s->filename, + s->token.ptr, &s->get_line_col_cache); + if (!fd) + return -1; + + s->cur_func = fd; + fd->has_home_object = TRUE; + fd->super_allowed = TRUE; + fd->has_prototype = FALSE; + fd->has_this_binding = TRUE; + fd->new_target_allowed = TRUE; + + push_scope(s); /* enter body scope */ + fd->body_scope = fd->scope_level; + if (has_super) { + fd->is_derived_class_constructor = TRUE; + fd->super_call_allowed = TRUE; + fd->arguments_allowed = TRUE; + fd->has_arguments_binding = TRUE; + func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR; + emit_op(s, OP_init_ctor); + // TODO(bnoordhuis) roll into OP_init_ctor + emit_op(s, OP_scope_put_var_init); + emit_atom(s, JS_ATOM_this); + emit_u16(s, 0); + emit_class_field_init(s); + } else { + func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; + /* error if not invoked as a constructor */ + emit_op(s, OP_check_ctor); + emit_class_field_init(s); + } + + fd->func_kind = JS_FUNC_NORMAL; + fd->func_type = func_type; + emit_return(s, FALSE); + + s->cur_func = fd->parent; + if (pfd) + *pfd = fd; + + /* the real object will be set at the end of the compilation */ + idx = cpool_add(s, JS_NULL); + fd->parent_cpool_idx = idx; + + return 0; +} + /* find field in the current scope */ static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, JSAtom name, int scope_level) @@ -23037,9 +24219,9 @@ static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name) typedef struct { JSFunctionDef *fields_init_fd; int computed_fields_count; - bool need_brand; + BOOL need_brand; int brand_push_pos; - bool is_static; + BOOL is_static; } ClassFieldsDef; static __exception int emit_class_init_start(JSParseState *s, @@ -23092,74 +24274,8 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf) emit_op(s, OP_set_home_object); } -static void emit_return(JSParseState *s, bool hasval); - -static JSFunctionDef *js_new_function_def(JSContext *ctx, - JSFunctionDef *parent, - bool is_eval, - bool is_func_expr, - const char *filename, - int line_num, - int col_num); - -static __exception int js_parse_class_default_ctor(JSParseState *s, - bool has_super, - JSFunctionDef **pfd) -{ - JSParseFunctionEnum func_type; - JSFunctionDef *fd = s->cur_func; - - fd = js_new_function_def(s->ctx, fd, false, false, s->filename, - s->token.line_num, s->token.col_num); - if (!fd) - return -1; - - s->cur_func = fd; - fd->has_home_object = true; - fd->super_allowed = true; - fd->has_prototype = false; - fd->has_this_binding = true; - fd->new_target_allowed = true; - - push_scope(s); /* enter body scope */ - fd->body_scope = fd->scope_level; - if (has_super) { - fd->is_derived_class_constructor = true; - fd->super_call_allowed = true; - fd->arguments_allowed = true; - fd->has_arguments_binding = true; - func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR; - emit_op(s, OP_init_ctor); - // TODO(bnoordhuis) roll into OP_init_ctor - emit_op(s, OP_scope_put_var_init); - emit_atom(s, JS_ATOM_this); - emit_u16(s, 0); - emit_class_field_init(s); - } else { - func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; - /* error if not invoked as a constructor */ - emit_op(s, OP_check_ctor); - emit_class_field_init(s); - } - - fd->func_kind = JS_FUNC_NORMAL; - fd->func_type = func_type; - emit_return(s, false); - - s->cur_func = fd->parent; - if (pfd) - *pfd = fd; - - int idx; - /* the real object will be set at the end of the compilation */ - idx = cpool_add(s, JS_NULL); - fd->parent_cpool_idx = idx; - - return 0; -} - -static __exception int js_parse_class(JSParseState *s, bool is_class_expr, +static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, JSParseExportEnum export_flag) { JSContext *ctx = s->ctx; @@ -23167,16 +24283,16 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1; JSAtom class_var_name = JS_ATOM_NULL; JSFunctionDef *method_fd, *ctor_fd; - int class_name_var_idx, prop_type, ctor_cpool_offset; + int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset; int class_flags = 0, i, define_class_offset; - bool is_static, is_private, is_strict_mode; + BOOL is_static, is_private; const uint8_t *class_start_ptr = s->token.ptr; const uint8_t *start_ptr; ClassFieldsDef class_fields[2]; /* classes are parsed and executed in strict mode */ - is_strict_mode = fd->is_strict_mode; - fd->is_strict_mode = true; + saved_js_mode = fd->js_mode; + fd->js_mode |= JS_MODE_STRICT; if (next_token(s)) goto fail; if (s->token.val == TOK_IDENT) { @@ -23246,7 +24362,7 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, ClassFieldsDef *cf = &class_fields[i]; cf->fields_init_fd = NULL; cf->computed_fields_count = 0; - cf->need_brand = false; + cf->need_brand = FALSE; cf->is_static = i; } @@ -23257,11 +24373,11 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, goto fail; continue; } - is_static = false; + is_static = FALSE; if (s->token.val == TOK_STATIC) { - int next = peek_token(s, true); + int next = peek_token(s, TRUE); if (!(next == ';' || next == '}' || next == '(' || next == '=')) - is_static = true; + is_static = TRUE; } prop_type = -1; if (is_static) { @@ -23269,17 +24385,19 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, goto fail; if (s->token.val == '{') { ClassFieldsDef *cf = &class_fields[is_static]; - if (!cf->fields_init_fd) + JSFunctionDef *init; + if (!cf->fields_init_fd) { if (emit_class_init_start(s, cf)) goto fail; + } s->cur_func = cf->fields_init_fd; + /* XXX: could try to avoid creating a new function and + reuse 'fields_init_fd' with a specific 'var' + scope */ // stack is now: - JSFunctionDef *init; if (js_parse_function_decl2(s, JS_PARSE_FUNC_CLASS_STATIC_INIT, JS_FUNC_NORMAL, JS_ATOM_NULL, s->token.ptr, - s->token.line_num, - s->token.col_num, JS_PARSE_EXPORT_NONE, &init) < 0) { goto fail; } @@ -23289,13 +24407,6 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, emit_atom(s, JS_ATOM_this); emit_u16(s, 0); // stack is now: fclosure this - if (class_name != JS_ATOM_NULL) { - // TODO(bnoordhuis) pass as argument to init method? - emit_op(s, OP_dup); - emit_op(s, OP_scope_put_var_init); - emit_atom(s, class_name); - emit_u16(s, s->cur_func->scope_level); - } emit_op(s, OP_swap); // stack is now: this fclosure emit_op(s, OP_call_method); @@ -23309,7 +24420,7 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, } /* allow "static" field name */ if (s->token.val == ';' || s->token.val == '=') { - is_static = false; + is_static = FALSE; name = JS_DupAtom(ctx, JS_ATOM_static); prop_type = PROP_TYPE_IDENT; } @@ -23318,7 +24429,7 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, emit_op(s, OP_swap); start_ptr = s->token.ptr; if (prop_type < 0) { - prop_type = js_parse_property_name(s, &name, true, false, true); + prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE); if (prop_type < 0) goto fail; } @@ -23333,7 +24444,7 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, goto fail; } if (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET) { - bool is_set = prop_type - PROP_TYPE_GET; + BOOL is_set = prop_type - PROP_TYPE_GET; JSFunctionDef *method_fd; if (is_private) { @@ -23356,18 +24467,16 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0) goto fail; } - class_fields[is_static].need_brand = true; + class_fields[is_static].need_brand = TRUE; } if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set, JS_FUNC_NORMAL, JS_ATOM_NULL, start_ptr, - s->token.line_num, - s->token.col_num, JS_PARSE_EXPORT_NONE, &method_fd)) goto fail; if (is_private) { - method_fd->need_home_object = true; /* needed for brand check */ + method_fd->need_home_object = TRUE; /* needed for brand check */ emit_op(s, OP_set_home_object); /* XXX: missing function name */ emit_op(s, OP_scope_put_var_init); @@ -23447,14 +24556,6 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, emit_atom(s, JS_ATOM_this); emit_u16(s, 0); - // expose class name to static initializers - if (is_static && class_name != JS_ATOM_NULL) { - emit_op(s, OP_dup); - emit_op(s, OP_scope_put_var_init); - emit_atom(s, class_name); - emit_u16(s, s->cur_func->scope_level); - } - if (name == JS_ATOM_NULL) { emit_op(s, OP_scope_get_var); emit_atom(s, field_var_name); @@ -23513,19 +24614,15 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; } if (is_private) { - class_fields[is_static].need_brand = true; + class_fields[is_static].need_brand = TRUE; } - if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, - start_ptr, - s->token.line_num, - s->token.col_num, - JS_PARSE_EXPORT_NONE, &method_fd)) + if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, JS_PARSE_EXPORT_NONE, &method_fd)) goto fail; if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR || func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { ctor_fd = method_fd; } else if (is_private) { - method_fd->need_home_object = true; /* needed for brand check */ + method_fd->need_home_object = TRUE; /* needed for brand check */ if (find_private_class_field(ctx, fd, name, fd->scope_level) >= 0) { private_field_already_defined: @@ -23570,11 +24667,14 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, put_u32(fd->byte_code.buf + ctor_cpool_offset, ctor_fd->parent_cpool_idx); /* store the class source code in the constructor. */ - js_free(ctx, ctor_fd->source); - ctor_fd->source_len = s->buf_ptr - class_start_ptr; - ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr, ctor_fd->source_len); - if (!ctor_fd->source) - goto fail; + if (!fd->strip_source) { + js_free(ctx, ctor_fd->source); + ctor_fd->source_len = s->buf_ptr - class_start_ptr; + ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr, + ctor_fd->source_len); + if (!ctor_fd->source) + goto fail; + } /* consume the '}' */ if (next_token(s)) @@ -23627,6 +24727,16 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, emit_op(s, OP_add_brand); } + if (class_name != JS_ATOM_NULL) { + /* store the class name in the scoped class name variable (it + is independent from the class statement variable + definition) */ + emit_op(s, OP_dup); + emit_op(s, OP_scope_put_var_init); + emit_atom(s, class_name); + emit_u16(s, fd->scope_level); + } + /* initialize the static fields */ if (class_fields[1].fields_init_fd != NULL) { ClassFieldsDef *cf = &class_fields[1]; @@ -23637,15 +24747,6 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, emit_op(s, OP_drop); } - if (class_name != JS_ATOM_NULL) { - /* store the class name in the scoped class name variable (it - is independent from the class statement variable - definition) */ - emit_op(s, OP_dup); - emit_op(s, OP_scope_put_var_init); - emit_atom(s, class_name); - emit_u16(s, fd->scope_level); - } pop_scope(s); pop_scope(s); @@ -23676,20 +24777,20 @@ static __exception int js_parse_class(JSParseState *s, bool is_class_expr, JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_var_name); - fd->is_strict_mode = is_strict_mode; + fd->js_mode = saved_js_mode; return 0; fail: JS_FreeAtom(ctx, name); JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_var_name); - fd->is_strict_mode = is_strict_mode; + fd->js_mode = saved_js_mode; return -1; } static __exception int js_parse_array_literal(JSParseState *s) { uint32_t idx; - bool need_length; + BOOL need_length; if (next_token(s)) return -1; @@ -23713,17 +24814,17 @@ static __exception int js_parse_array_literal(JSParseState *s) emit_u16(s, idx); /* larger arrays and holes are handled with explicit indices */ - need_length = false; + need_length = FALSE; while (s->token.val != ']' && idx < 0x7fffffff) { if (s->token.val == TOK_ELLIPSIS) break; - need_length = true; + need_length = TRUE; if (s->token.val != ',') { if (js_parse_assign_expr(s)) return -1; emit_op(s, OP_define_field); emit_u32(s, __JS_AtomFromUInt32(idx)); - need_length = false; + need_length = FALSE; } idx++; /* accept trailing comma */ @@ -23756,15 +24857,41 @@ static __exception int js_parse_array_literal(JSParseState *s) return -1; if (js_parse_assign_expr(s)) return -1; +#if 1 emit_op(s, OP_append); +#else + int label_next, label_done; + label_next = new_label(s); + label_done = new_label(s); + /* enumerate object */ + emit_op(s, OP_for_of_start); + emit_op(s, OP_rot5l); + emit_op(s, OP_rot5l); + emit_label(s, label_next); + /* on stack: enum_rec array idx */ + emit_op(s, OP_for_of_next); + emit_u8(s, 2); + emit_goto(s, OP_if_true, label_done); + /* append element */ + /* enum_rec array idx val -> enum_rec array new_idx */ + emit_op(s, OP_define_array_el); + emit_op(s, OP_inc); + emit_goto(s, OP_goto, label_next); + emit_label(s, label_done); + /* close enumeration */ + emit_op(s, OP_drop); /* drop undef val */ + emit_op(s, OP_nip1); /* drop enum_rec */ + emit_op(s, OP_nip1); + emit_op(s, OP_nip1); +#endif } else { - need_length = true; + need_length = TRUE; if (s->token.val != ',') { if (js_parse_assign_expr(s)) return -1; /* a idx val */ emit_op(s, OP_define_array_el); - need_length = false; + need_length = FALSE; } emit_op(s, OP_inc); } @@ -23787,7 +24914,7 @@ static __exception int js_parse_array_literal(JSParseState *s) } /* XXX: remove */ -static bool has_with_scope(JSFunctionDef *s, int scope_level) +static BOOL has_with_scope(JSFunctionDef *s, int scope_level) { /* check if scope chain contains a with statement */ while (s) { @@ -23796,18 +24923,18 @@ static bool has_with_scope(JSFunctionDef *s, int scope_level) JSVarDef *vd = &s->vars[scope_idx]; if (vd->var_name == JS_ATOM__with_) - return true; + return TRUE; scope_idx = vd->scope_next; } /* check parent scopes */ scope_level = s->parent_scope_level; s = s->parent; } - return false; + return FALSE; } static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, - JSAtom *pname, int *plabel, int *pdepth, bool keep, + JSAtom *pname, int *plabel, int *pdepth, BOOL keep, int tok) { JSFunctionDef *fd; @@ -23825,7 +24952,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) && - fd->is_strict_mode) { + (fd->js_mode & JS_MODE_STRICT)) { return js_parse_error(s, "invalid lvalue in strict mode"); } if (name == JS_ATOM_this || name == JS_ATOM_new_target) @@ -23888,10 +25015,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, emit_u16(s, scope); break; case OP_get_array_el: - /* XXX: replace by a single opcode ? */ - emit_op(s, OP_to_propkey2); - emit_op(s, OP_dup2); - emit_op(s, OP_get_array_el); + emit_op(s, OP_get_array_el3); break; case OP_get_super_value: emit_op(s, OP_to_propkey); @@ -23914,11 +25038,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, update_label(fd, label, 1); opcode = OP_get_ref_value; break; - case OP_get_array_el: - emit_op(s, OP_to_propkey2); - break; - case OP_get_super_value: - emit_op(s, OP_to_propkey); + default: break; } } @@ -23947,7 +25067,7 @@ typedef enum { OP_scope_get_var which is never generated by get_lvalue(). */ static void put_lvalue(JSParseState *s, int opcode, int scope, JSAtom name, int label, PutLValueEnum special, - bool is_let) + BOOL is_let) { switch(opcode) { case OP_get_field: @@ -24077,20 +25197,12 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) return js_parse_error(s, "yield is a reserved identifier"); } if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) - && fd->is_strict_mode) { + && (fd->js_mode & JS_MODE_STRICT)) { return js_parse_error(s, "invalid variable name in strict mode"); } - if (tok == TOK_LET || tok == TOK_CONST) { - if (name == JS_ATOM_let) - return js_parse_error(s, "invalid lexical variable name 'let'"); - // |undefined| is allowed as an identifier except at the global - // scope of a classic script; sloppy or strict doesn't matter - if (name == JS_ATOM_undefined - && fd->scope_level == 1 - && fd->is_global_var - && !fd->module) { - return js_parse_error(s, "'undefined' already declared"); - } + if (name == JS_ATOM_let + && (tok == TOK_LET || tok == TOK_CONST)) { + return js_parse_error(s, "invalid lexical variable name"); } switch(tok) { case TOK_LET: @@ -24155,15 +25267,34 @@ static int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name) return 0; duplicate: - return js_parse_error(s, "Duplicate parameter name not allowed in this context"); + return js_parse_error(s, "duplicate parameter names not allowed in this context"); } -static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, bool is_arg) +/* tok = TOK_VAR, TOK_LET or TOK_CONST. Return whether a reference + must be taken to the variable for proper 'with' or global variable + evaluation */ +/* Note: this function is needed only because variable references are + not yet optimized in destructuring */ +static BOOL need_var_reference(JSParseState *s, int tok) +{ + JSFunctionDef *fd = s->cur_func; + if (tok != TOK_VAR) + return FALSE; /* no reference for let/const */ + if (fd->js_mode & JS_MODE_STRICT) { + if (!fd->is_global_var) + return FALSE; /* local definitions in strict mode in function or direct eval */ + if (s->is_module) + return FALSE; /* in a module global variables are like closure variables */ + } + return TRUE; +} + +static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg) { JSAtom name; if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) - || (s->cur_func->is_strict_mode && + || ((s->cur_func->js_mode & JS_MODE_STRICT) && (s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) { js_parse_error(s, "invalid destructuring target"); return JS_ATOM_NULL; @@ -24182,23 +25313,19 @@ static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, bool is_arg) /* Return -1 if error, 0 if no initializer, 1 if an initializer is present at the top level. */ -static int js_parse_destructuring_element(JSParseState *s, int tok, - bool is_arg, bool hasval, - int has_ellipsis, // tri-state - bool allow_initializer, - bool export_flag) +static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, + int hasval, int has_ellipsis, + BOOL allow_initializer, BOOL export_flag) { int label_parse, label_assign, label_done, label_lvalue, depth_lvalue; int start_addr, assign_addr; JSAtom prop_name, var_name; int opcode, scope, tok1, skip_bits; - bool has_initializer; - - label_lvalue = -1; + BOOL has_initializer; if (has_ellipsis < 0) { /* pre-parse destructuration target for spread detection */ - js_parse_skip_parens_token(s, &skip_bits, false); + js_parse_skip_parens_token(s, &skip_bits, FALSE); has_ellipsis = skip_bits & SKIP_HAS_ELLIPSIS; } @@ -24243,16 +25370,25 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, var_name = js_parse_destructuring_var(s, tok, is_arg); if (var_name == JS_ATOM_NULL) return -1; - opcode = OP_scope_get_var; - scope = s->cur_func->scope_level; - label_lvalue = -1; - depth_lvalue = 0; + if (need_var_reference(s, tok)) { + /* Must make a reference for proper `with` semantics */ + emit_op(s, OP_scope_get_var); + emit_atom(s, var_name); + emit_u16(s, s->cur_func->scope_level); + JS_FreeAtom(s->ctx, var_name); + goto lvalue0; + } else { + opcode = OP_scope_get_var; + scope = s->cur_func->scope_level; + label_lvalue = -1; + depth_lvalue = 0; + } } else { if (js_parse_left_hand_side_expr(s)) return -1; - + lvalue0: if (get_lvalue(s, &opcode, &scope, &var_name, - &label_lvalue, &depth_lvalue, false, '{')) + &label_lvalue, &depth_lvalue, FALSE, '{')) return -1; } if (s->token.val != '}') { @@ -24264,19 +25400,15 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5)); goto set_val; } - prop_type = js_parse_property_name(s, &prop_name, false, true, false); + prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE, FALSE); if (prop_type < 0) return -1; var_name = JS_ATOM_NULL; - opcode = OP_scope_get_var; - scope = s->cur_func->scope_level; - label_lvalue = -1; - depth_lvalue = 0; if (prop_type == PROP_TYPE_IDENT) { if (next_token(s)) goto prop_error; if ((s->token.val == '[' || s->token.val == '{') - && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == ',' || + && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' || tok1 == '=' || tok1 == '}')) { if (prop_name == JS_ATOM_NULL) { /* computed property name on stack */ @@ -24304,7 +25436,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_op(s, OP_get_field2); emit_u32(s, prop_name); } - if (js_parse_destructuring_element(s, tok, is_arg, true, -1, true, export_flag) < 0) + if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE, export_flag) < 0) return -1; if (s->token.val == '}') break; @@ -24314,7 +25446,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, continue; } if (prop_name == JS_ATOM_NULL) { - emit_op(s, OP_to_propkey2); + emit_op(s, OP_to_propkey); if (has_ellipsis) { /* define the property in excludeList */ emit_op(s, OP_perm3); @@ -24340,12 +25472,26 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, var_name = js_parse_destructuring_var(s, tok, is_arg); if (var_name == JS_ATOM_NULL) goto prop_error; + if (need_var_reference(s, tok)) { + /* Must make a reference for proper `with` semantics */ + emit_op(s, OP_scope_get_var); + emit_atom(s, var_name); + emit_u16(s, s->cur_func->scope_level); + JS_FreeAtom(s->ctx, var_name); + goto lvalue1; + } else { + /* no need to make a reference for let/const */ + opcode = OP_scope_get_var; + scope = s->cur_func->scope_level; + label_lvalue = -1; + depth_lvalue = 0; + } } else { if (js_parse_left_hand_side_expr(s)) goto prop_error; - lvalue: + lvalue1: if (get_lvalue(s, &opcode, &scope, &var_name, - &label_lvalue, &depth_lvalue, false, '{')) + &label_lvalue, &depth_lvalue, FALSE, '{')) goto prop_error; /* swap ref and lvalue object if any */ if (prop_name == JS_ATOM_NULL) { @@ -24397,7 +25543,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, /* prop_type = PROP_TYPE_VAR, cannot be a computed property */ if (is_arg && js_parse_check_duplicate_parameter(s, prop_name)) goto prop_error; - if (s->cur_func->is_strict_mode && + if ((s->cur_func->js_mode & JS_MODE_STRICT) && (prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) { js_parse_error(s, "invalid destructuring target"); goto prop_error; @@ -24410,19 +25556,26 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_atom(s, prop_name); emit_op(s, OP_swap); } - if (!tok || tok == TOK_VAR) { + if (!tok || need_var_reference(s, tok)) { /* generate reference */ /* source -- source source */ emit_op(s, OP_dup); emit_op(s, OP_scope_get_var); emit_atom(s, prop_name); emit_u16(s, s->cur_func->scope_level); - goto lvalue; + goto lvalue1; + } else { + /* no need to make a reference for let/const */ + var_name = JS_DupAtom(s->ctx, prop_name); + opcode = OP_scope_get_var; + scope = s->cur_func->scope_level; + label_lvalue = -1; + depth_lvalue = 0; + + /* source -- source val */ + emit_op(s, OP_get_field2); + emit_u32(s, prop_name); } - var_name = JS_DupAtom(s->ctx, prop_name); - /* source -- source val */ - emit_op(s, OP_get_field2); - emit_u32(s, prop_name); } set_val: if (tok) { @@ -24433,7 +25586,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, JS_EXPORT_TYPE_LOCAL)) goto var_error; } - scope = s->cur_func->scope_level; + scope = s->cur_func->scope_level; /* XXX: check */ } if (s->token.val == '=') { /* handle optional default value */ int label_hasval; @@ -24468,7 +25621,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, if (next_token(s)) return -1; } else if (s->token.val == '[') { - bool has_spread; + BOOL has_spread; int enum_depth; BlockEnv block_env; @@ -24478,9 +25631,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, 'yield' triggers a 'return' */ push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL, -1, -1, 2); - block_env.has_iterator = true; + block_env.has_iterator = TRUE; emit_op(s, OP_for_of_start); - has_spread = false; + has_spread = FALSE; while (s->token.val != ']') { /* get the next value */ if (s->token.val == TOK_ELLIPSIS) { @@ -24488,7 +25641,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, return -1; if (s->token.val == ',' || s->token.val == ']') return js_parse_error(s, "missing binding pattern..."); - has_spread = true; + has_spread = TRUE; } if (s->token.val == ',') { /* do nothing, skip the value, has_spread is false */ @@ -24497,7 +25650,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_op(s, OP_drop); emit_op(s, OP_drop); } else if ((s->token.val == '[' || s->token.val == '{') - && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == ',' || + && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' || tok1 == '=' || tok1 == ']')) { if (has_spread) { if (tok1 == '=') @@ -24508,24 +25661,36 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_u8(s, 0); emit_op(s, OP_drop); } - if (js_parse_destructuring_element(s, tok, is_arg, true, skip_bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0) + if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, export_flag) < 0) return -1; } else { var_name = JS_ATOM_NULL; - enum_depth = 0; if (tok) { var_name = js_parse_destructuring_var(s, tok, is_arg); if (var_name == JS_ATOM_NULL) goto var_error; if (js_define_var(s, var_name, tok)) goto var_error; - opcode = OP_scope_get_var; - scope = s->cur_func->scope_level; + if (need_var_reference(s, tok)) { + /* Must make a reference for proper `with` semantics */ + emit_op(s, OP_scope_get_var); + emit_atom(s, var_name); + emit_u16(s, s->cur_func->scope_level); + JS_FreeAtom(s->ctx, var_name); + goto lvalue2; + } else { + /* no need to make a reference for let/const */ + opcode = OP_scope_get_var; + scope = s->cur_func->scope_level; + label_lvalue = -1; + enum_depth = 0; + } } else { if (js_parse_left_hand_side_expr(s)) return -1; + lvalue2: if (get_lvalue(s, &opcode, &scope, &var_name, - &label_lvalue, &enum_depth, false, '[')) { + &label_lvalue, &enum_depth, FALSE, '[')) { return -1; } } @@ -24585,7 +25750,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, return -1; emit_goto(s, OP_goto, label_assign); emit_label(s, label_done); - has_initializer = true; + has_initializer = TRUE; } else { /* normally hasval is true except if js_parse_skip_parens_token() was wrong in the parsing */ @@ -24598,7 +25763,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, memset(s->cur_func->byte_code.buf + start_addr, OP_nop, assign_addr - start_addr); s->cur_func->label_slots[label_parse].ref_count--; - has_initializer = false; + has_initializer = FALSE; } return has_initializer; @@ -24638,8 +25803,9 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) { FuncCallType call_type; int optional_chaining_label; - bool accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0; - + BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0; + const uint8_t *op_token_ptr; + call_type = FUNC_CALL_NORMAL; switch(s->token.val) { case TOK_NUMBER: @@ -24687,7 +25853,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) parse_regexp: { JSValue str; - int ret, backtrace_flags; + int ret; if (!s->ctx->compile_regexp) return js_parse_error(s, "RegExp are not supported"); /* the previous token is '/' or '/=', so no need to free */ @@ -24698,14 +25864,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) s->token.u.regexp.flags); if (JS_IsException(str)) { /* add the line number info */ - backtrace_flags = 0; - if (s->cur_func && s->cur_func->backtrace_barrier) - backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL; - build_backtrace(s->ctx, s->ctx->rt->current_exception, JS_UNDEFINED, - s->filename, - s->token.line_num, - s->token.col_num, - backtrace_flags); + int line_num, col_num; + line_num = get_line_col(&col_num, s->buf_start, s->token.ptr - s->buf_start); + build_backtrace(s->ctx, s->ctx->rt->current_exception, + s->filename, line_num + 1, col_num + 1, 0); return -1; } ret = emit_push_const(s, str, 0); @@ -24727,13 +25889,11 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) case TOK_FUNCTION: if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR, JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, - s->token.line_num, - s->token.col_num)) + s->token.ptr)) return -1; break; case TOK_CLASS: - if (js_parse_class(s, true, JS_PARSE_EXPORT_NONE)) + if (js_parse_class(s, TRUE, JS_PARSE_EXPORT_NONE)) return -1; break; case TOK_NULL: @@ -24761,26 +25921,19 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) case TOK_IDENT: { JSAtom name; + const uint8_t *source_ptr; if (s->token.u.ident.is_reserved) { return js_parse_error_reserved_identifier(s); } + source_ptr = s->token.ptr; if (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) != '\n') { - const uint8_t *source_ptr; - int source_line_num; - int source_col_num; - - source_ptr = s->token.ptr; - source_line_num = s->token.line_num; - source_col_num = s->token.col_num; + peek_token(s, TRUE) != '\n') { if (next_token(s)) return -1; if (s->token.val == TOK_FUNCTION) { if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR, JS_FUNC_ASYNC, JS_ATOM_NULL, - source_ptr, - source_line_num, - source_col_num)) + source_ptr)) return -1; } else { name = JS_DupAtom(s->ctx, JS_ATOM_async); @@ -24793,11 +25946,12 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; } name = JS_DupAtom(s->ctx, s->token.u.ident.atom); - if (next_token(s)) { /* update line number before emitting code */ + if (next_token(s)) { JS_FreeAtom(s->ctx, name); return -1; } do_get_var: + emit_source_pos(s, source_ptr); emit_op(s, OP_scope_get_var); emit_u32(s, name); emit_u16(s, s->cur_func->scope_level); @@ -24806,20 +25960,12 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) break; case '{': case '[': - { - int skip_bits; - if (js_parse_skip_parens_token(s, &skip_bits, false) == '=') { - if (js_parse_destructuring_element(s, 0, false, false, skip_bits & SKIP_HAS_ELLIPSIS, true, false) < 0) - return -1; - } else { - if (s->token.val == '{') { - if (js_parse_object_literal(s)) - return -1; - } else { - if (js_parse_array_literal(s)) - return -1; - } - } + if (s->token.val == '{') { + if (js_parse_object_literal(s)) + return -1; + } else { + if (js_parse_array_literal(s)) + return -1; } break; case TOK_NEW: @@ -24838,12 +25984,12 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) emit_atom(s, JS_ATOM_new_target); emit_u16(s, 0); } else { - emit_source_loc(s); if (js_parse_postfix_expr(s, 0)) return -1; - accept_lparen = true; + accept_lparen = TRUE; if (s->token.val != '(') { /* new operator on an object */ + emit_source_pos(s, s->token.ptr); emit_op(s, OP_dup); emit_op(s, OP_call_constructor); emit_u16(s, 0); @@ -24894,6 +26040,23 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return js_parse_error(s, "invalid use of 'import()'"); if (js_parse_assign_expr(s)) return -1; + if (s->token.val == ',') { + if (next_token(s)) + return -1; + if (s->token.val != ')') { + if (js_parse_assign_expr(s)) + return -1; + /* accept a trailing comma */ + if (s->token.val == ',') { + if (next_token(s)) + return -1; + } + } else { + emit_op(s, OP_undefined); + } + } else { + emit_op(s, OP_undefined); + } if (js_parse_expect(s, ')')) return -1; emit_op(s, OP_import); @@ -24907,13 +26070,16 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) optional_chaining_label = -1; for(;;) { JSFunctionDef *fd = s->cur_func; - bool has_optional_chain = false; + BOOL has_optional_chain = FALSE; if (s->token.val == TOK_QUESTION_MARK_DOT) { + if ((parse_flags & PF_POSTFIX_CALL) == 0) + return js_parse_error(s, "new keyword cannot be used with an optional chain"); + op_token_ptr = s->token.ptr; /* optional chaining */ if (next_token(s)) return -1; - has_optional_chain = true; + has_optional_chain = TRUE; if (s->token.val == '(' && accept_lparen) { goto parse_func_call; } else if (s->token.val == '[') { @@ -24927,18 +26093,19 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return js_parse_error(s, "template literal cannot appear in an optional chain"); } call_type = FUNC_CALL_TEMPLATE; + op_token_ptr = s->token.ptr; /* XXX: check if right position */ goto parse_func_call2; } else if (s->token.val == '(' && accept_lparen) { int opcode, arg_count, drop_count; /* function call */ parse_func_call: + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (call_type == FUNC_CALL_NORMAL) { parse_func_call2: - emit_source_loc(s); switch(opcode = get_prev_opcode(fd)) { case OP_get_field: /* keep the object on the stack */ @@ -25060,8 +26227,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) arg_count = 0; while (s->token.val != ')') { if (arg_count >= 65535) { - return js_parse_error(s, "Too many arguments in function call (only %d allowed)", - 65535 - 1); + return js_parse_error(s, "Too many call arguments"); } if (s->token.val == TOK_ELLIPSIS) break; @@ -25087,8 +26253,34 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; if (js_parse_assign_expr(s)) return -1; +#if 1 /* XXX: could pass is_last indicator? */ emit_op(s, OP_append); +#else + int label_next, label_done; + label_next = new_label(s); + label_done = new_label(s); + /* push enumerate object below array/idx pair */ + emit_op(s, OP_for_of_start); + emit_op(s, OP_rot5l); + emit_op(s, OP_rot5l); + emit_label(s, label_next); + /* on stack: enum_rec array idx */ + emit_op(s, OP_for_of_next); + emit_u8(s, 2); + emit_goto(s, OP_if_true, label_done); + /* append element */ + /* enum_rec array idx val -> enum_rec array new_idx */ + emit_op(s, OP_define_array_el); + emit_op(s, OP_inc); + emit_goto(s, OP_goto, label_next); + emit_label(s, label_done); + /* close enumeration, drop enum_rec and idx */ + emit_op(s, OP_drop); /* drop undef */ + emit_op(s, OP_nip1); /* drop enum_rec */ + emit_op(s, OP_nip1); + emit_op(s, OP_nip1); +#endif } else { if (js_parse_assign_expr(s)) return -1; @@ -25107,6 +26299,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) /* drop the index */ emit_op(s, OP_drop); + emit_source_pos(s, op_token_ptr); /* apply function call */ switch(opcode) { case OP_get_field: @@ -25121,7 +26314,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) case OP_eval: emit_op(s, OP_apply_eval); emit_u16(s, fd->scope_level); - fd->has_eval_call = true; + fd->has_eval_call = TRUE; break; default: if (call_type == FUNC_CALL_SUPER_CTOR) { @@ -25152,6 +26345,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (next_token(s)) return -1; emit_func_call: + emit_source_pos(s, op_token_ptr); switch(opcode) { case OP_get_field: case OP_scope_get_private_field: @@ -25164,7 +26358,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) emit_op(s, OP_eval); emit_u16(s, arg_count); emit_u16(s, fd->scope_level); - fd->has_eval_call = true; + fd->has_eval_call = TRUE; break; default: if (call_type == FUNC_CALL_SUPER_CTOR) { @@ -25190,9 +26384,11 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) } call_type = FUNC_CALL_NORMAL; } else if (s->token.val == '.') { + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; parse_property: + emit_source_pos(s, op_token_ptr); if (s->token.val == TOK_PRIVATE_NAME) { /* private class field */ if (get_prev_opcode(fd) == OP_get_super) { @@ -25229,7 +26425,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; } else if (s->token.val == '[') { int prev_op; - + op_token_ptr = s->token.ptr; parse_array_access: prev_op = get_prev_opcode(fd); if (has_optional_chain) { @@ -25241,6 +26437,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; if (js_parse_expect(s, ']')) return -1; + emit_source_pos(s, op_token_ptr); if (prev_op == OP_get_super) { emit_op(s, OP_get_super_value); } else { @@ -25338,7 +26535,7 @@ static __exception int js_parse_delete(JSParseState *s) name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); if (name == JS_ATOM_this || name == JS_ATOM_new_target) goto ret_true; - if (fd->is_strict_mode) { + if (fd->js_mode & JS_MODE_STRICT) { return js_parse_error(s, "cannot delete a direct reference in strict mode"); } else { fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var; @@ -25366,6 +26563,7 @@ static __exception int js_parse_delete(JSParseState *s) static __exception int js_parse_unary(JSParseState *s, int parse_flags) { int op; + const uint8_t *op_token_ptr; switch(s->token.val) { case '+': @@ -25373,6 +26571,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) case '!': case '~': case TOK_VOID: + op_token_ptr = s->token.ptr; op = s->token.val; if (next_token(s)) return -1; @@ -25380,15 +26579,18 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) return -1; switch(op) { case '-': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_neg); break; case '+': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_plus); break; case '!': emit_op(s, OP_lnot); break; case '~': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_not); break; case TOK_VOID: @@ -25406,15 +26608,17 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) int opcode, op, scope, label; JSAtom name; op = s->token.val; + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (js_parse_unary(s, 0)) return -1; - if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, true, op)) + if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_dec + op - TOK_DEC); put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, - false); + FALSE); } break; case TOK_TYPEOF: @@ -25448,7 +26652,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) return -1; if (js_parse_unary(s, PF_POW_FORBIDDEN)) return -1; - s->cur_func->has_await = true; + s->cur_func->has_await = TRUE; emit_op(s, OP_await); parse_flags = 0; break; @@ -25460,11 +26664,13 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) int opcode, op, scope, label; JSAtom name; op = s->token.val; - if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, true, op)) + op_token_ptr = s->token.ptr; + if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_post_dec + op - TOK_DEC); put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND, - false); + FALSE); if (next_token(s)) return -1; } @@ -25477,12 +26683,16 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) regarding the precedence of prefix operators and the postifx exponential, ES7 specifies that -2**2 is a syntax error. */ - if (parse_flags & PF_POW_FORBIDDEN) - return js_parse_error(s, "unparenthesized unary expression can't appear on the left-hand side of '**'"); + if (parse_flags & PF_POW_FORBIDDEN) { + JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'"); + return -1; + } + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (js_parse_unary(s, PF_POW_ALLOWED)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_pow); } } @@ -25494,13 +26704,15 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, int parse_flags) { int op, opcode; - + const uint8_t *op_token_ptr; + if (level == 0) { return js_parse_unary(s, PF_POW_ALLOWED); } else if (s->token.val == TOK_PRIVATE_NAME && (parse_flags & PF_IN_ACCEPTED) && level == 4 && - peek_token(s, false) == TOK_IN) { + peek_token(s, FALSE) == TOK_IN) { JSAtom atom; + atom = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) goto fail_private_in; @@ -25524,6 +26736,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, } for(;;) { op = s->token.val; + op_token_ptr = s->token.ptr; switch(level) { case 1: switch(op) { @@ -25645,9 +26858,9 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, } if (next_token(s)) return -1; - emit_source_loc(s); if (js_parse_expr_binary(s, level - 1, parse_flags)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, opcode); } return 0; @@ -25680,7 +26893,8 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op, if (js_parse_expr_binary(s, 8, parse_flags)) return -1; } else { - if (js_parse_logical_and_or(s, TOK_LAND, parse_flags)) + if (js_parse_logical_and_or(s, TOK_LAND, + parse_flags)) return -1; } if (s->token.val != op) { @@ -25754,12 +26968,12 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags) /* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) { - int opcode, op, scope; + int opcode, op, scope, skip_bits; JSAtom name0 = JS_ATOM_NULL; JSAtom name; if (s->token.val == TOK_YIELD) { - bool is_star = false, is_async; + BOOL is_star = FALSE, is_async; if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR)) return js_parse_error(s, "unexpected 'yield' keyword"); @@ -25773,7 +26987,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) s->token.val != ']' && s->token.val != '}' && s->token.val != ',' && s->token.val != ':' && !s->got_lf) { if (s->token.val == '*') { - is_star = true; + is_star = TRUE; if (next_token(s)) return -1; } @@ -25850,7 +27064,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_nip); emit_op(s, OP_nip); emit_op(s, OP_nip); - emit_return(s, true); + emit_return(s, TRUE); /* throw handling */ emit_label(s, label_throw); @@ -25891,51 +27105,51 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_await); emit_op(s, OP_yield); label_next = emit_goto(s, OP_if_false, -1); - emit_return(s, true); + emit_return(s, TRUE); emit_label(s, label_next); } return 0; } else if (s->token.val == '(' && - js_parse_skip_parens_token(s, NULL, true) == TOK_ARROW) { + js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) { return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, s->token.line_num, - s->token.col_num); + s->token.ptr); } else if (token_is_pseudo_keyword(s, JS_ATOM_async)) { const uint8_t *source_ptr; - int tok, source_line_num, source_col_num; + int tok; JSParsePos pos; /* fast test */ - tok = peek_token(s, true); + tok = peek_token(s, TRUE); if (tok == TOK_FUNCTION || tok == '\n') goto next; source_ptr = s->token.ptr; - source_line_num = s->token.line_num; - source_col_num = s->token.col_num; js_parse_get_pos(s, &pos); if (next_token(s)) return -1; if ((s->token.val == '(' && - js_parse_skip_parens_token(s, NULL, true) == TOK_ARROW) || + js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) || (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved && - peek_token(s, true) == TOK_ARROW)) { + peek_token(s, TRUE) == TOK_ARROW)) { return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, JS_FUNC_ASYNC, JS_ATOM_NULL, - source_ptr, source_line_num, - source_col_num); + source_ptr); } else { /* undo the token parsing */ if (js_parse_seek_token(s, &pos)) return -1; } } else if (s->token.val == TOK_IDENT && - peek_token(s, true) == TOK_ARROW) { + peek_token(s, TRUE) == TOK_ARROW) { return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, s->token.line_num, - s->token.col_num); + s->token.ptr); + } else if ((s->token.val == '{' || s->token.val == '[') && + js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { + if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0) + return -1; + return 0; } next: if (s->token.val == TOK_IDENT) { @@ -25948,60 +27162,40 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) op = s->token.val; if (op == '=' || (op >= TOK_MUL_ASSIGN && op <= TOK_POW_ASSIGN)) { int label; + const uint8_t *op_token_ptr; + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0) return -1; - // comply with rather obtuse evaluation order of computed properties: - // obj[key]=val evaluates val->obj->key when obj is null/undefined - // but key->obj->val when an object - // FIXME(bnoordhuis) less stack shuffling; don't to_propkey twice in - // happy path; replace `dup is_undefined_or_null if_true` with new - // opcode if_undefined_or_null? replace `swap dup` with over? - if (op == '=' && opcode == OP_get_array_el) { - int label_next = -1; - JSFunctionDef *fd = s->cur_func; - assert(OP_to_propkey2 == fd->byte_code.buf[fd->last_opcode_pos]); - fd->byte_code.size = fd->last_opcode_pos; - fd->last_opcode_pos = -1; - emit_op(s, OP_swap); // obj key -> key obj - emit_op(s, OP_dup); - emit_op(s, OP_is_undefined_or_null); - label_next = emit_goto(s, OP_if_true, -1); - emit_op(s, OP_swap); - emit_op(s, OP_to_propkey); - emit_op(s, OP_swap); - emit_label(s, label_next); - emit_op(s, OP_swap); - } - if (js_parse_assign_expr2(s, parse_flags)) { JS_FreeAtom(s->ctx, name); return -1; } - if (op == '=' && opcode == OP_get_array_el) { - emit_op(s, OP_swap); // obj key val -> obj val key - emit_op(s, OP_to_propkey); - emit_op(s, OP_swap); - } - if (op == '=') { if (opcode == OP_get_ref_value && name == name0) { set_object_name(s, name); } } else { - emit_op(s, op - TOK_MUL_ASSIGN + OP_mul); + static const uint8_t assign_opcodes[] = { + OP_mul, OP_div, OP_mod, OP_add, OP_sub, + OP_shl, OP_sar, OP_shr, OP_and, OP_xor, OP_or, + OP_pow, + }; + op = assign_opcodes[op - TOK_MUL_ASSIGN]; + emit_source_pos(s, op_token_ptr); + emit_op(s, op); } - put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, false); + put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE); } else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) { int label, label1, depth_lvalue, label2; if (next_token(s)) return -1; if (get_lvalue(s, &opcode, &scope, &name, &label, - &depth_lvalue, true, op) < 0) + &depth_lvalue, TRUE, op) < 0) return -1; emit_op(s, OP_dup); @@ -26037,7 +27231,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) /* XXX: we disable the OP_put_ref_value optimization by not using put_lvalue() otherwise depth_lvalue is not correct */ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH, - false); + FALSE); label2 = emit_goto(s, OP_goto, -1); emit_label(s, label1); @@ -26061,7 +27255,7 @@ static __exception int js_parse_assign_expr(JSParseState *s) /* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_expr2(JSParseState *s, int parse_flags) { - bool comma = false; + BOOL comma = FALSE; for(;;) { if (js_parse_assign_expr2(s, parse_flags)) return -1; @@ -26075,7 +27269,7 @@ static __exception int js_parse_expr2(JSParseState *s, int parse_flags) } if (s->token.val != ',') break; - comma = true; + comma = TRUE; if (next_token(s)) return -1; emit_op(s, OP_drop); @@ -26101,8 +27295,8 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be, be->drop_count = drop_count; be->label_finally = -1; be->scope_level = fd->scope_level; - be->has_iterator = false; - be->is_regular_stmt = false; + be->has_iterator = FALSE; + be->is_regular_stmt = FALSE; } static void pop_break_entry(JSFunctionDef *fd) @@ -26129,12 +27323,12 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont) emit_goto(s, OP_goto, top->label_cont); return 0; } - if (!is_cont && top->label_break != -1) { - if (top->label_name == name || - (name == JS_ATOM_NULL && !top->is_regular_stmt)) { - emit_goto(s, OP_goto, top->label_break); - return 0; - } + if (!is_cont && + top->label_break != -1 && + ((name == JS_ATOM_NULL && !top->is_regular_stmt) || + top->label_name == name)) { + emit_goto(s, OP_goto, top->label_break); + return 0; } i = 0; if (top->has_iterator) { @@ -26162,7 +27356,7 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont) } /* execute the finally blocks before return */ -static void emit_return(JSParseState *s, bool hasval) +static void emit_return(JSParseState *s, BOOL hasval) { BlockEnv *top; @@ -26170,7 +27364,7 @@ static void emit_return(JSParseState *s, bool hasval) if (!hasval) { /* no value: direct return in case of async generator */ emit_op(s, OP_undefined); - hasval = true; + hasval = TRUE; } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) { /* the await must be done before handling the "finally" in case it raises an exception */ @@ -26183,7 +27377,7 @@ static void emit_return(JSParseState *s, bool hasval) if (top->has_iterator || top->label_finally != -1) { if (!hasval) { emit_op(s, OP_undefined); - hasval = true; + hasval = TRUE; } /* Remove the stack elements up to and including the catch offset. When 'yield' is used in an expression we have @@ -26236,9 +27430,9 @@ static void emit_return(JSParseState *s, bool hasval) label_return = -1; } - /* XXX: if this is not initialized, should throw the - ReferenceError in the caller realm */ - emit_op(s, OP_scope_get_var); + /* The error should be raised in the caller context, so we use + a specific opcode */ + emit_op(s, OP_scope_get_var_checkthis); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); @@ -26286,7 +27480,7 @@ static __exception int js_parse_block(JSParseState *s) /* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, - bool export_flag) + BOOL export_flag) { JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; @@ -26315,7 +27509,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, if (s->token.val == '=') { if (next_token(s)) goto var_error; - if (tok == TOK_VAR) { + if (need_var_reference(s, tok)) { /* Must make a reference for proper `with` semantics */ int opcode, scope, label; JSAtom name1; @@ -26323,7 +27517,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, emit_op(s, OP_scope_get_var); emit_atom(s, name); emit_u16(s, fd->scope_level); - if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, false, '=') < 0) + if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0) goto var_error; if (js_parse_assign_expr2(s, parse_flags)) { JS_FreeAtom(ctx, name1); @@ -26331,7 +27525,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, } set_object_name(s, name); put_lvalue(s, opcode, scope, name1, label, - PUT_LVALUE_NOKEEP, false); + PUT_LVALUE_NOKEEP, FALSE); } else { if (js_parse_assign_expr2(s, parse_flags)) goto var_error; @@ -26358,9 +27552,9 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, } else { int skip_bits; if ((s->token.val == '[' || s->token.val == '{') - && js_parse_skip_parens_token(s, &skip_bits, false) == '=') { + && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { emit_op(s, OP_undefined); - if (js_parse_destructuring_element(s, tok, false, true, skip_bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0) + if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, export_flag) < 0) return -1; } else { return js_parse_error(s, "variable name expected"); @@ -26379,21 +27573,23 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, } /* test if the current token is a label. Use simplistic look-ahead scanner */ -static bool is_label(JSParseState *s) +static BOOL is_label(JSParseState *s) { return (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved && - peek_token(s, false) == ':'); + peek_token(s, FALSE) == ':'); } /* test if the current token is a let keyword. Use simplistic look-ahead scanner */ static int is_let(JSParseState *s, int decl_mask) { - int res = false; - + int res = FALSE; + const uint8_t *last_token_ptr; + if (token_is_pseudo_keyword(s, JS_ATOM_let)) { JSParsePos pos; js_parse_get_pos(s, &pos); for (;;) { + last_token_ptr = s->token.ptr; if (next_token(s)) { res = -1; break; @@ -26401,7 +27597,7 @@ static int is_let(JSParseState *s, int decl_mask) if (s->token.val == '[') { /* let [ is a syntax restriction: it never introduces an ExpressionStatement */ - res = true; + res = TRUE; break; } if (s->token.val == '{' || @@ -26412,8 +27608,9 @@ static int is_let(JSParseState *s, int decl_mask) /* Check for possible ASI if not scanning for Declaration */ /* XXX: should also check that `{` introduces a BindingPattern, but Firefox does not and rejects eval("let=1;let\n{if(1)2;}") */ - if (s->last_line_num == s->token.line_num || (decl_mask & DECL_MASK_OTHER)) { - res = true; + if (!has_lf_in_range(last_token_ptr, s->token.ptr) || + (decl_mask & DECL_MASK_OTHER)) { + res = TRUE; break; } break; @@ -26430,20 +27627,20 @@ static int is_let(JSParseState *s, int decl_mask) /* XXX: handle IteratorClose when exiting the loop before the enumeration is done */ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, - bool is_async) + BOOL is_async) { JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; JSAtom var_name; - bool has_initializer, is_for_of, has_destructuring; + BOOL has_initializer, is_for_of, has_destructuring; int tok, tok1, opcode, scope, block_scope_level; int label_next, label_expr, label_cont, label_body, label_break; int pos_next, pos_expr; BlockEnv break_entry; - has_initializer = false; - has_destructuring = false; - is_for_of = false; + has_initializer = FALSE; + has_destructuring = FALSE; + is_for_of = FALSE; block_scope_level = fd->scope_level; label_cont = new_label(s); label_body = new_label(s); @@ -26468,10 +27665,10 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, tok = s->token.val; switch (is_let(s, DECL_MASK_OTHER)) { - case true: + case TRUE: tok = TOK_LET; break; - case false: + case FALSE: break; default: return -1; @@ -26482,9 +27679,9 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { - if (js_parse_destructuring_element(s, tok, false, true, -1, false, false) < 0) + if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE, FALSE) < 0) return -1; - has_destructuring = true; + has_destructuring = TRUE; } else { return js_parse_error(s, "variable name expected"); } @@ -26504,23 +27701,24 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, emit_atom(s, var_name); emit_u16(s, fd->scope_level); } - } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, false) == TOK_OF) { + } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) && + peek_token(s, FALSE) == TOK_OF) { return js_parse_error(s, "'for of' expression cannot start with 'async'"); } else { int skip_bits; if ((s->token.val == '[' || s->token.val == '{') - && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, false)) == TOK_IN || tok1 == TOK_OF)) { - if (js_parse_destructuring_element(s, 0, false, true, skip_bits & SKIP_HAS_ELLIPSIS, true, false) < 0) + && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) { + if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0) return -1; } else { int lvalue_label; if (js_parse_left_hand_side_expr(s)) return -1; if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label, - NULL, false, TOK_FOR)) + NULL, FALSE, TOK_FOR)) return -1; put_lvalue(s, opcode, scope, var_name, lvalue_label, - PUT_LVALUE_NOKEEP_BOTTOM, false); + PUT_LVALUE_NOKEEP_BOTTOM, FALSE); } var_name = JS_ATOM_NULL; } @@ -26530,7 +27728,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, emit_label(s, label_expr); if (s->token.val == '=') { /* XXX: potential scoping issue if inside `with` statement */ - has_initializer = true; + has_initializer = TRUE; /* parse and evaluate initializer prior to evaluating the object (only used with "for in" with a non lexical variable in non strict mode */ @@ -26547,8 +27745,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, JS_FreeAtom(ctx, var_name); if (token_is_pseudo_keyword(s, JS_ATOM_of)) { - is_for_of = true; - break_entry.has_iterator = true; + break_entry.has_iterator = is_for_of = TRUE; break_entry.drop_count += 2; if (has_initializer) goto initializer_error; @@ -26556,7 +27753,8 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (is_async) return js_parse_error(s, "'for await' loop should be used with 'of'"); if (has_initializer && - (tok != TOK_VAR || fd->is_strict_mode || has_destructuring)) { + (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) || + has_destructuring)) { initializer_error: return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer", is_for_of ? "of" : "in"); @@ -26591,13 +27789,13 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (js_parse_expect(s, ')')) return -1; - { + if (OPTIMIZE) { /* move the `next` code here */ DynBuf *bc = &s->cur_func->byte_code; int chunk_size = pos_expr - pos_next; int offset = bc->size - pos_next; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_next, chunk_size); memset(bc->buf + pos_next, OP_nop, chunk_size); /* `next` part ends with a goto */ @@ -26619,12 +27817,9 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, emit_label(s, label_cont); if (is_for_of) { if (is_async) { - /* call the next method */ /* stack: iter_obj next catch_offset */ - emit_op(s, OP_dup3); - emit_op(s, OP_drop); - emit_op(s, OP_call_method); - emit_u16(s, 0); + /* call the next method */ + emit_op(s, OP_for_await_of_next); /* get the result of the promise */ emit_op(s, OP_await); /* unwrap the value and done values */ @@ -26692,14 +27887,14 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, && s->token.val != TOK_DO && s->token.val != TOK_WHILE) { /* labelled regular statement */ - JSFunctionDef *fd = s->cur_func; int label_break, mask; BlockEnv break_entry; label_break = new_label(s); - push_break_entry(fd, &break_entry, label_name, label_break, -1, 0); - fd->top_break->is_regular_stmt = 1; - if (!fd->is_strict_mode && + push_break_entry(s->cur_func, &break_entry, + label_name, label_break, -1, 0); + break_entry.is_regular_stmt = TRUE; + if (!(s->cur_func->js_mode & JS_MODE_STRICT) && (decl_mask & DECL_MASK_FUNC_WITH_LABEL)) { mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL; } else { @@ -26708,7 +27903,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_statement_or_decl(s, mask)) goto fail; emit_label(s, label_break); - pop_break_entry(fd); + pop_break_entry(s->cur_func); goto done; } } @@ -26719,39 +27914,49 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, goto fail; break; case TOK_RETURN: - if (s->cur_func->is_eval) { - js_parse_error(s, "return not in a function"); - goto fail; - } - if (s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) { - js_parse_error(s, "return in a static initializer block"); - goto fail; - } - if (next_token(s)) - goto fail; - if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) { - if (js_parse_expr(s)) + { + const uint8_t *op_token_ptr; + if (s->cur_func->is_eval) { + js_parse_error(s, "return not in a function"); + goto fail; + } + if (s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) { + js_parse_error(s, "return in a static initializer block"); + goto fail; + } + op_token_ptr = s->token.ptr; + if (next_token(s)) + goto fail; + if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) { + if (js_parse_expr(s)) + goto fail; + emit_source_pos(s, op_token_ptr); + emit_return(s, TRUE); + } else { + emit_source_pos(s, op_token_ptr); + emit_return(s, FALSE); + } + if (js_parse_expect_semi(s)) goto fail; - emit_return(s, true); - } else { - emit_return(s, false); } - if (js_parse_expect_semi(s)) - goto fail; break; case TOK_THROW: - if (next_token(s)) - goto fail; - if (s->got_lf) { - js_parse_error(s, "line terminator not allowed after throw"); - goto fail; + { + const uint8_t *op_token_ptr; + op_token_ptr = s->token.ptr; + if (next_token(s)) + goto fail; + if (s->got_lf) { + js_parse_error(s, "line terminator not allowed after throw"); + goto fail; + } + if (js_parse_expr(s)) + goto fail; + emit_source_pos(s, op_token_ptr); + emit_op(s, OP_throw); + if (js_parse_expect_semi(s)) + goto fail; } - emit_source_loc(s); - if (js_parse_expr(s)) - goto fail; - emit_op(s, OP_throw); - if (js_parse_expect_semi(s)) - goto fail; break; case TOK_LET: case TOK_CONST: @@ -26764,7 +27969,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, case TOK_VAR: if (next_token(s)) goto fail; - if (js_parse_var(s, PF_IN_ACCEPTED, tok, /*export_flag*/false)) + if (js_parse_var(s, TRUE, tok, FALSE)) goto fail; if (js_parse_expect_semi(s)) goto fail; @@ -26780,7 +27985,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_expr_paren(s)) goto fail; label1 = emit_goto(s, OP_if_false, -1); - if (s->cur_func->is_strict_mode) + if (s->cur_func->js_mode & JS_MODE_STRICT) mask = 0; else mask = DECL_MASK_FUNC; /* Annex B.3.4 */ @@ -26878,25 +28083,25 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, int pos_cont, pos_body, block_scope_level; BlockEnv break_entry; int tok, bits; - bool is_async; + BOOL is_async; if (next_token(s)) goto fail; set_eval_ret_undefined(s); bits = 0; - is_async = false; + is_async = FALSE; if (s->token.val == '(') { - js_parse_skip_parens_token(s, &bits, false); + js_parse_skip_parens_token(s, &bits, FALSE); } else if (s->token.val == TOK_AWAIT) { if (!(s->cur_func->func_kind & JS_FUNC_ASYNC)) { js_parse_error(s, "for await is only valid in asynchronous functions"); goto fail; } - is_async = true; + is_async = TRUE; if (next_token(s)) goto fail; - s->cur_func->has_await = true; + s->cur_func->has_await = TRUE; } if (js_parse_expect(s, '(')) goto fail; @@ -26916,10 +28121,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, tok = s->token.val; if (tok != ';') { switch (is_let(s, DECL_MASK_OTHER)) { - case true: + case TRUE: tok = TOK_LET; break; - case false: + case FALSE: break; default: goto fail; @@ -26927,10 +28132,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) { if (next_token(s)) goto fail; - if (js_parse_var(s, 0, tok, /*export_flag*/false)) + if (js_parse_var(s, FALSE, tok, FALSE)) goto fail; } else { - if (js_parse_expr2(s, false)) + if (js_parse_expr2(s, FALSE)) goto fail; emit_op(s, OP_drop); } @@ -26990,13 +28195,13 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, /* XXX: check continue case */ close_scopes(s, s->cur_func->scope_level, block_scope_level); - if (label_test != label_body && label_cont != label_test) { + if (OPTIMIZE && label_test != label_body && label_cont != label_test) { /* move the increment code here */ DynBuf *bc = &s->cur_func->byte_code; int chunk_size = pos_body - pos_cont; int offset = bc->size - pos_cont; int i; - dbuf_realloc(bc, bc->size + chunk_size); + dbuf_claim(bc, chunk_size); dbuf_put(bc, bc->buf + pos_cont, chunk_size); memset(bc->buf + pos_cont, OP_nop, chunk_size); /* increment part ends with a goto */ @@ -27189,7 +28394,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { /* XXX: TOK_LET is not completely correct */ - if (js_parse_destructuring_element(s, TOK_LET, false, true, -1, true, false) < 0) + if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE, FALSE) < 0) goto fail; } else { js_parse_error(s, "identifier expected"); @@ -27298,7 +28503,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, goto fail; break; case TOK_WITH: - if (s->cur_func->is_strict_mode) { + if (s->cur_func->js_mode & JS_MODE_STRICT) { js_parse_error(s, "invalid keyword: with"); goto fail; } else { @@ -27331,7 +28536,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, /* ES6 Annex B.3.2 and B.3.3 semantics */ if (!(decl_mask & DECL_MASK_FUNC)) goto func_decl_error; - if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, false) == '*') + if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, FALSE) == '*') goto func_decl_error; goto parse_func_var; case TOK_IDENT: @@ -27341,16 +28546,16 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, } /* Determine if `let` introduces a Declaration or an ExpressionStatement */ switch (is_let(s, decl_mask)) { - case true: + case TRUE: tok = TOK_LET; goto haslet; - case false: + case FALSE: break; default: goto fail; } if (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) == TOK_FUNCTION) { + peek_token(s, TRUE) == TOK_FUNCTION) { if (!(decl_mask & DECL_MASK_OTHER)) { func_decl_error: js_parse_error(s, "function declarations can't appear in single-statement context"); @@ -27359,9 +28564,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, parse_func_var: if (js_parse_function_decl(s, JS_PARSE_FUNC_VAR, JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, - s->token.line_num, - s->token.col_num)) + s->token.ptr)) goto fail; break; } @@ -27372,7 +28575,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, js_parse_error(s, "class declarations can't appear in single-statement context"); goto fail; } - if (js_parse_class(s, false, JS_PARSE_EXPORT_NONE)) + if (js_parse_class(s, FALSE, JS_PARSE_EXPORT_NONE)) return -1; break; @@ -27392,7 +28595,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, default: hasexpr: - emit_source_loc(s); + emit_source_pos(s, s->token.ptr); if (js_parse_expr(s)) goto fail; if (s->cur_func->eval_ret_idx >= 0) { @@ -27415,9 +28618,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, return -1; } -#endif // QJS_DISABLE_PARSER - -/* 'name' is freed */ +/* 'name' is freed. The module is referenced by 'ctx->loaded_modules' */ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) { JSModuleDef *m; @@ -27427,6 +28628,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) return NULL; } m->header.ref_count = 1; + add_gc_object(ctx->rt, &m->header, JS_GC_OBJ_TYPE_MODULE); m->module_name = name; m->module_ns = JS_UNDEFINED; m->func_obj = JS_UNDEFINED; @@ -27435,6 +28637,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->promise = JS_UNDEFINED; m->resolving_funcs[0] = JS_UNDEFINED; m->resolving_funcs[1] = JS_UNDEFINED; + m->private_value = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -27444,6 +28647,11 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, { int i; + for(i = 0; i < m->req_module_entries_count; i++) { + JSReqModuleEntry *rme = &m->req_module_entries[i]; + JS_MarkValue(rt, rme->attributes, mark_func); + } + for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL && @@ -27459,63 +28667,65 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkValue(rt, m->promise, mark_func); JS_MarkValue(rt, m->resolving_funcs[0], mark_func); JS_MarkValue(rt, m->resolving_funcs[1], mark_func); + JS_MarkValue(rt, m->private_value, mark_func); } -static void js_free_module_def(JSContext *ctx, JSModuleDef *m) +static void js_free_module_def(JSRuntime *rt, JSModuleDef *m) { int i; - JS_FreeAtom(ctx, m->module_name); + JS_FreeAtomRT(rt, m->module_name); for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; - JS_FreeAtom(ctx, rme->module_name); + JS_FreeAtomRT(rt, rme->module_name); + JS_FreeValueRT(rt, rme->attributes); } - js_free(ctx, m->req_module_entries); + js_free_rt(rt, m->req_module_entries); for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL) - free_var_ref(ctx->rt, me->u.local.var_ref); - JS_FreeAtom(ctx, me->export_name); - JS_FreeAtom(ctx, me->local_name); + free_var_ref(rt, me->u.local.var_ref); + JS_FreeAtomRT(rt, me->export_name); + JS_FreeAtomRT(rt, me->local_name); } - js_free(ctx, m->export_entries); + js_free_rt(rt, m->export_entries); - js_free(ctx, m->star_export_entries); + js_free_rt(rt, m->star_export_entries); for(i = 0; i < m->import_entries_count; i++) { JSImportEntry *mi = &m->import_entries[i]; - JS_FreeAtom(ctx, mi->import_name); + JS_FreeAtomRT(rt, mi->import_name); } - js_free(ctx, m->import_entries); - js_free(ctx, m->async_parent_modules); + js_free_rt(rt, m->import_entries); + js_free_rt(rt, m->async_parent_modules); - JS_FreeValue(ctx, m->module_ns); - JS_FreeValue(ctx, m->func_obj); - JS_FreeValue(ctx, m->eval_exception); - JS_FreeValue(ctx, m->meta_obj); - JS_FreeValue(ctx, m->promise); - JS_FreeValue(ctx, m->resolving_funcs[0]); - JS_FreeValue(ctx, m->resolving_funcs[1]); - list_del(&m->link); - js_free(ctx, m); + JS_FreeValueRT(rt, m->module_ns); + JS_FreeValueRT(rt, m->func_obj); + JS_FreeValueRT(rt, m->eval_exception); + JS_FreeValueRT(rt, m->meta_obj); + JS_FreeValueRT(rt, m->promise); + JS_FreeValueRT(rt, m->resolving_funcs[0]); + JS_FreeValueRT(rt, m->resolving_funcs[1]); + JS_FreeValueRT(rt, m->private_value); + /* during the GC the finalizers are called in an arbitrary + order so the module may no longer be referenced by the JSContext list */ + if (m->link.next) { + list_del(&m->link); + } + remove_gc_object(&m->header); + if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && m->header.ref_count != 0) { + list_add_tail(&m->header.link, &rt->gc_zero_ref_count_list); + } else { + js_free_rt(rt, m); + } } -#ifndef QJS_DISABLE_PARSER - static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, JSAtom module_name) { JSReqModuleEntry *rme; - int i; - - /* no need to add the module request if it is already present */ - for(i = 0; i < m->req_module_entries_count; i++) { - rme = &m->req_module_entries[i]; - if (rme->module_name == module_name) - return i; - } if (js_resize_array(ctx, (void **)&m->req_module_entries, sizeof(JSReqModuleEntry), @@ -27525,12 +28735,11 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, rme = &m->req_module_entries[m->req_module_entries_count++]; rme->module_name = JS_DupAtom(ctx, module_name); rme->module = NULL; - return i; + rme->attributes = JS_UNDEFINED; + return m->req_module_entries_count - 1; } -#endif // QJS_DISABLE_PARSER - -static JSExportEntry *find_export_entry(JSContext *ctx, const JSModuleDef *m, +static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m, JSAtom export_name) { JSExportEntry *me; @@ -27574,8 +28783,6 @@ static JSExportEntry *add_export_entry2(JSContext *ctx, return me; } -#ifndef QJS_DISABLE_PARSER - static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m, JSAtom local_name, JSAtom export_name, JSExportTypeEnum export_type) @@ -27599,10 +28806,7 @@ static int add_star_export_entry(JSContext *ctx, JSModuleDef *m, return 0; } -#endif // QJS_DISABLE_PARSER - /* create a C module */ -/* `name_str` may be pure ASCII or UTF-8 encoded */ JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, JSModuleInitFunc *func) { @@ -27618,7 +28822,6 @@ JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, return m; } -/* `export_name` may be pure ASCII or UTF-8 encoded */ int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name) { JSExportEntry *me; @@ -27635,7 +28838,6 @@ int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name) return 0; } -/* `export_name` may be pure ASCII or UTF-8 encoded */ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, JSValue val) { @@ -27655,12 +28857,38 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, return -1; } +int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val) +{ + set_value(ctx, &m->private_value, val); + return 0; +} + +JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m) +{ + return JS_DupValue(ctx, m->private_value); +} + void JS_SetModuleLoaderFunc(JSRuntime *rt, JSModuleNormalizeFunc *module_normalize, JSModuleLoaderFunc *module_loader, void *opaque) { rt->module_normalize_func = module_normalize; - rt->module_loader_func = module_loader; + rt->module_loader_has_attr = FALSE; + rt->u.module_loader_func = module_loader; + rt->module_check_attrs = NULL; + rt->module_loader_opaque = opaque; +} + +void JS_SetModuleLoaderFunc2(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc2 *module_loader, + JSModuleCheckSupportedImportAttributes *module_check_attrs, + void *opaque) +{ + rt->module_normalize_func = module_normalize; + rt->module_loader_has_attr = TRUE; + rt->u.module_loader_func2 = module_loader; + rt->module_check_attrs = module_check_attrs; rt->module_loader_opaque = opaque; } @@ -27718,8 +28946,8 @@ static char *js_default_module_normalize_name(JSContext *ctx, } } if (filename[0] != '\0') - js__pstrcat(filename, cap, "/"); - js__pstrcat(filename, cap, r); + pstrcat(filename, cap, "/"); + pstrcat(filename, cap, r); // printf("normalize: %s %s -> %s\n", base_name, name, filename); return filename; } @@ -27739,10 +28967,10 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) } /* return NULL in case of exception (e.g. module could not be loaded) */ -/* `base_cname` and `cname1` may be pure ASCII or UTF-8 encoded */ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, const char *base_cname, - const char *cname1) + const char *cname1, + JSValueConst attributes) { JSRuntime *rt = ctx->rt; JSModuleDef *m; @@ -27775,23 +29003,26 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, JS_FreeAtom(ctx, module_name); /* load the module */ - if (!rt->module_loader_func) { + if (!rt->u.module_loader_func) { /* XXX: use a syntax error ? */ - // XXX: update JS_DetectModule when you change this JS_ThrowReferenceError(ctx, "could not load module '%s'", cname); js_free(ctx, cname); return NULL; } - - m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque); + if (rt->module_loader_has_attr) { + m = rt->u.module_loader_func2(ctx, cname, rt->module_loader_opaque, attributes); + } else { + m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque); + } js_free(ctx, cname); return m; } static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, - JSAtom base_module_name, - JSAtom module_name1) + JSAtom base_module_name, + JSAtom module_name1, + JSValueConst attributes) { const char *base_cname, *cname; JSModuleDef *m; @@ -27804,7 +29035,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, JS_FreeCString(ctx, base_cname); return NULL; } - m = js_host_resolve_imported_module(ctx, base_cname, cname); + m = js_host_resolve_imported_module(ctx, base_cname, cname, attributes); JS_FreeCString(ctx, base_cname); JS_FreeCString(ctx, cname); return m; @@ -27988,7 +29219,7 @@ static void js_resolve_export_throw_error(JSContext *ctx, typedef enum { EXPORTED_NAME_AMBIGUOUS, EXPORTED_NAME_NORMAL, - EXPORTED_NAME_NS, + EXPORTED_NAME_DELAYED, } ExportedNameEntryEnum; typedef struct ExportedNameEntry { @@ -27997,7 +29228,6 @@ typedef struct ExportedNameEntry { union { JSExportEntry *me; /* using when the list is built */ JSVarRef *var_ref; /* EXPORTED_NAME_NORMAL */ - JSModuleDef *module; /* for EXPORTED_NAME_NS */ } u; } ExportedNameEntry; @@ -28023,7 +29253,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name) static __exception int get_exported_names(JSContext *ctx, GetExportNamesState *s, - JSModuleDef *m, bool from_star) + JSModuleDef *m, BOOL from_star) { ExportedNameEntry *en; int i, j; @@ -28064,7 +29294,7 @@ static __exception int get_exported_names(JSContext *ctx, JSStarExportEntry *se = &m->star_export_entries[i]; JSModuleDef *m1; m1 = m->req_module_entries[se->req_module_idx].module; - if (get_exported_names(ctx, s, m1, true)) + if (get_exported_names(ctx, s, m1, TRUE)) return -1; } return 0; @@ -28095,7 +29325,7 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque) /* XXX: raise an error ? */ ret = 0; } else { - ret = js_string_compare(JS_VALUE_GET_STRING(str1), + ret = js_string_compare(ctx, JS_VALUE_GET_STRING(str1), JS_VALUE_GET_STRING(str2)); } JS_FreeValue(ctx, str1); @@ -28107,7 +29337,29 @@ static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { JSModuleDef *m = opaque; - return JS_GetModuleNamespace(ctx, m); + JSResolveResultEnum res; + JSExportEntry *res_me; + JSModuleDef *res_m; + JSVarRef *var_ref; + + res = js_resolve_export(ctx, &res_m, &res_me, m, atom); + if (res != JS_RESOLVE_RES_FOUND) { + /* fail safe: normally no error should happen here except for memory */ + js_resolve_export_throw_error(ctx, res, m, atom); + return JS_EXCEPTION; + } + if (res_me->local_name == JS_ATOM__star_) { + return JS_GetModuleNamespace(ctx, res_m->req_module_entries[res_me->u.req_module_idx].module); + } else { + if (res_me->u.local.var_ref) { + var_ref = res_me->u.local.var_ref; + } else { + JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj); + var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; + } + /* WARNING: a varref is returned as a string ! */ + return JS_MKPTR(JS_TAG_STRING, var_ref); + } } static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) @@ -28124,7 +29376,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) p = JS_VALUE_GET_OBJ(obj); memset(s, 0, sizeof(*s)); - ret = get_exported_names(ctx, s, m, false); + ret = get_exported_names(ctx, s, m, FALSE); js_free(ctx, s->modules); if (ret) goto fail; @@ -28152,17 +29404,18 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) en->export_type = EXPORTED_NAME_AMBIGUOUS; } else { if (res_me->local_name == JS_ATOM__star_) { - en->export_type = EXPORTED_NAME_NS; - en->u.module = res_m->req_module_entries[res_me->u.req_module_idx].module; + en->export_type = EXPORTED_NAME_DELAYED; } else { - en->export_type = EXPORTED_NAME_NORMAL; if (res_me->u.local.var_ref) { en->u.var_ref = res_me->u.local.var_ref; } else { JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - p1 = JS_VALUE_GET_OBJ(res_m->func_obj); en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; } + if (en->u.var_ref == NULL) + en->export_type = EXPORTED_NAME_DELAYED; + else + en->export_type = EXPORTED_NAME_NORMAL; } } } @@ -28177,11 +29430,6 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) case EXPORTED_NAME_NORMAL: { JSVarRef *var_ref = en->u.var_ref; - if (!var_ref) { - js_resolve_export_throw_error(ctx, JS_RESOLVE_RES_CIRCULAR, - m, en->export_name); - goto fail; - } pr = add_property(ctx, p, en->export_name, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_VARREF); @@ -28191,13 +29439,13 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) pr->u.var_ref = var_ref; } break; - case EXPORTED_NAME_NS: - /* the exported namespace must be created on demand */ + case EXPORTED_NAME_DELAYED: + /* the exported namespace or reference may depend on + circular references, so we resolve it lazily */ if (JS_DefineAutoInitProperty(ctx, obj, en->export_name, JS_AUTOINIT_ID_MODULE_NS, - en->u.module, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) - goto fail; + m, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) break; default: break; @@ -28210,7 +29458,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) JS_AtomToString(ctx, JS_ATOM_Module), 0); - p->extensible = false; + p->extensible = FALSE; return obj; fail: js_free(ctx, s->exported_names); @@ -28227,19 +29475,9 @@ JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; m->module_ns = val; } - return js_dup(m->module_ns); + return JS_DupValue(ctx, m->module_ns); } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE -#define module_trace(ctx, ...) \ - do { \ - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) \ - printf(__VA_ARGS__); \ - } while (0) -#else -#define module_trace(...) -#endif - /* Load all the required modules for module 'm' */ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) { @@ -28248,18 +29486,19 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) if (m->resolved) return 0; -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { +#ifdef DUMP_MODULE_RESOLVE + { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("resolving module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } #endif - m->resolved = true; + m->resolved = TRUE; /* resolve each requested module */ for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; m1 = js_host_resolve_imported_module_atom(ctx, m->module_name, - rme->module_name); + rme->module_name, + rme->attributes); if (!m1) return -1; rme->module = m1; @@ -28271,7 +29510,7 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) return 0; } -static JSVarRef *js_create_module_var(JSContext *ctx, bool is_lexical) +static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical) { JSVarRef *var_ref; var_ref = js_malloc(ctx, sizeof(JSVarRef)); @@ -28283,7 +29522,7 @@ static JSVarRef *js_create_module_var(JSContext *ctx, bool is_lexical) else var_ref->value = JS_UNDEFINED; var_ref->pvalue = &var_ref->value; - var_ref->is_detached = true; + var_ref->is_detached = TRUE; add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); return var_ref; } @@ -28325,9 +29564,9 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m) var_ref = js_create_module_var(ctx, cv->is_lexical); if (!var_ref) goto fail; - - module_trace(ctx, "local %d: %p\n", i, (void *)var_ref); - +#ifdef DUMP_MODULE_RESOLVE + printf("local %d: %p\n", i, var_ref); +#endif var_refs[i] = var_ref; } } @@ -28343,7 +29582,7 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m) /* must be done before js_link_module() because of cyclic references */ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) { - bool is_c_module; + BOOL is_c_module; int i; JSVarRef *var_ref; @@ -28357,7 +29596,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL) { - var_ref = js_create_module_var(ctx, false); + var_ref = js_create_module_var(ctx, FALSE); if (!var_ref) return -1; me->u.local.var_ref = var_ref; @@ -28367,7 +29606,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) if (js_create_module_bytecode_function(ctx, m)) return -1; } - m->func_created = true; + m->func_created = TRUE; /* do it on the dependencies */ @@ -28391,7 +29630,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, JSModuleDef *m1; JSVarRef **var_refs, *var_ref; JSObject *p; - bool is_c_module; + BOOL is_c_module; JSValue ret_val; if (js_check_stack_overflow(ctx->rt, 0)) { @@ -28399,8 +29638,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, return -1; } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { +#ifdef DUMP_MODULE_RESOLVE + { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("js_inner_module_linking '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } @@ -28437,8 +29676,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { +#ifdef DUMP_MODULE_RESOLVE + { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } @@ -28460,8 +29699,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { +#ifdef DUMP_MODULE_RESOLVE + { printf("exported bindings:\n"); for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; @@ -28480,24 +29719,22 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, for(i = 0; i < m->import_entries_count; i++) { mi = &m->import_entries[i]; -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { - printf("import var_idx=%d name=", mi->var_idx); - print_atom(ctx, mi->import_name); - printf(": "); - } +#ifdef DUMP_MODULE_RESOLVE + printf("import var_idx=%d name=", mi->var_idx); + print_atom(ctx, mi->import_name); + printf(": "); #endif m1 = m->req_module_entries[mi->req_module_idx].module; - if (mi->import_name == JS_ATOM__star_) { + if (mi->is_star) { JSValue val; /* name space import */ val = JS_GetModuleNamespace(ctx, m1); if (JS_IsException(val)) goto fail; set_value(ctx, &var_refs[mi->var_idx]->value, val); - - module_trace(ctx, "namespace\n"); - +#ifdef DUMP_MODULE_RESOLVE + printf("namespace\n"); +#endif } else { JSResolveResultEnum ret; JSExportEntry *res_me; @@ -28518,16 +29755,16 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, val = JS_GetModuleNamespace(ctx, m2); if (JS_IsException(val)) goto fail; - var_ref = js_create_module_var(ctx, true); + var_ref = js_create_module_var(ctx, TRUE); if (!var_ref) { JS_FreeValue(ctx, val); goto fail; } set_value(ctx, &var_ref->value, val); var_refs[mi->var_idx] = var_ref; - - module_trace(ctx, "namespace from\n"); - +#ifdef DUMP_MODULE_RESOLVE + printf("namespace from\n"); +#endif } else { var_ref = res_me->u.local.var_ref; if (!var_ref) { @@ -28536,8 +29773,9 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } var_ref->header.ref_count++; var_refs[mi->var_idx] = var_ref; - - module_trace(ctx, "local export (var_ref=%p)\n", (void *)var_ref); +#ifdef DUMP_MODULE_RESOLVE + printf("local export (var_ref=%p)\n", var_ref); +#endif } } } @@ -28573,10 +29811,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { - printf("js_inner_module_linking done\n"); - } +#ifdef DUMP_MODULE_RESOLVE + printf("js_inner_module_linking done\n"); #endif return index; fail: @@ -28589,8 +29825,8 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m) { JSModuleDef *stack_top, *m1; -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { +#ifdef DUMP_MODULE_RESOLVE + { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("js_link_module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } @@ -28624,8 +29860,8 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels) JSFunctionBytecode *b; JSObject *p; /* XXX: currently we just use the filename of the englobing - function. It does not work for eval(). Need to add a - ScriptOrModule info in JSFunctionBytecode */ + function from the debug info. May need to add a ScriptOrModule + info in JSFunctionBytecode. */ sf = ctx->rt->current_stack_frame; if (!sf) return JS_ATOM_NULL; @@ -28634,13 +29870,23 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels) if (!sf) return JS_ATOM_NULL; } - if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT) - return JS_ATOM_NULL; - p = JS_VALUE_GET_OBJ(sf->cur_func); - if (!js_class_has_bytecode(p->class_id)) - return JS_ATOM_NULL; - b = p->u.func.function_bytecode; - return JS_DupAtom(ctx, b->filename); + for(;;) { + if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT) + return JS_ATOM_NULL; + p = JS_VALUE_GET_OBJ(sf->cur_func); + if (!js_class_has_bytecode(p->class_id)) + return JS_ATOM_NULL; + b = p->u.func.function_bytecode; + if (!b->is_direct_or_indirect_eval) { + if (!b->has_debug) + return JS_ATOM_NULL; + return JS_DupAtom(ctx, b->debug.filename); + } else { + sf = sf->prev_frame; + if (!sf) + return JS_ATOM_NULL; + } + } } JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m) @@ -28659,7 +29905,7 @@ JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; m->meta_obj = obj; } - return js_dup(obj); + return JS_DupValue(ctx, obj); } static JSValue js_import_meta(JSContext *ctx) @@ -28685,14 +29931,13 @@ static JSValue js_import_meta(JSContext *ctx) static JSValue JS_NewModuleValue(JSContext *ctx, JSModuleDef *m) { - return js_dup(JS_MKPTR(JS_TAG_MODULE, m)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); } static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + int argc, JSValueConst *argv, int magic, JSValue *func_data) { - JSValueConst *resolving_funcs = func_data; + JSValueConst *resolving_funcs = (JSValueConst *)func_data; JSValueConst error; JSValue ret; @@ -28701,16 +29946,16 @@ static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val, error = argv[0]; else error = JS_UNDEFINED; - ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, &error); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, + 1, &error); JS_FreeValue(ctx, ret); return JS_UNDEFINED; } static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + int argc, JSValueConst *argv, int magic, JSValue *func_data) { - JSValueConst *resolving_funcs = func_data; + JSValueConst *resolving_funcs = (JSValueConst *)func_data; JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]); JSValue ret, ns; @@ -28718,10 +29963,11 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val, ns = JS_GetModuleNamespace(ctx, m); if (JS_IsException(ns)) { JSValue err = JS_GetException(ctx); - js_load_module_rejected(ctx, JS_UNDEFINED, 1, vc(&err), 0, func_data); + js_load_module_rejected(ctx, JS_UNDEFINED, 1, (JSValueConst *)&err, 0, func_data); return JS_UNDEFINED; } - ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, 1, vc(&ns)); + ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, + 1, (JSValueConst *)&ns); JS_FreeValue(ctx, ret); JS_FreeValue(ctx, ns); return JS_UNDEFINED; @@ -28729,14 +29975,15 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val, static void JS_LoadModuleInternal(JSContext *ctx, const char *basename, const char *filename, - JSValueConst *resolving_funcs) + JSValueConst *resolving_funcs, + JSValueConst attributes) { JSValue evaluate_promise; JSModuleDef *m; JSValue ret, err, func_obj, evaluate_resolving_funcs[2]; JSValueConst func_data[3]; - m = js_host_resolve_imported_module(ctx, basename, filename); + m = js_host_resolve_imported_module(ctx, basename, filename, attributes); if (!m) goto fail; @@ -28751,7 +29998,8 @@ static void JS_LoadModuleInternal(JSContext *ctx, const char *basename, if (JS_IsException(evaluate_promise)) { fail: err = JS_GetException(ctx); - ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&err)); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, + 1, (JSValueConst *)&err); JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */ JS_FreeValue(ctx, err); return; @@ -28764,7 +30012,7 @@ static void JS_LoadModuleInternal(JSContext *ctx, const char *basename, evaluate_resolving_funcs[0] = JS_NewCFunctionData(ctx, js_load_module_fulfilled, 0, 0, 3, func_data); evaluate_resolving_funcs[1] = JS_NewCFunctionData(ctx, js_load_module_rejected, 0, 0, 3, func_data); JS_FreeValue(ctx, func_obj); - ret = js_promise_then(ctx, evaluate_promise, 2, vc(evaluate_resolving_funcs)); + ret = js_promise_then(ctx, evaluate_promise, 2, (JSValueConst *)evaluate_resolving_funcs); JS_FreeValue(ctx, ret); JS_FreeValue(ctx, evaluate_resolving_funcs[0]); JS_FreeValue(ctx, evaluate_resolving_funcs[1]); @@ -28781,7 +30029,8 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename, promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; - JS_LoadModuleInternal(ctx, basename, filename, vc(resolving_funcs)); + JS_LoadModuleInternal(ctx, basename, filename, + (JSValueConst *)resolving_funcs, JS_UNDEFINED); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); return promise; @@ -28793,6 +30042,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, JSValueConst *resolving_funcs = argv; JSValueConst basename_val = argv[2]; JSValueConst specifier = argv[3]; + JSValueConst attributes = argv[4]; const char *basename = NULL, *filename; JSValue ret, err; @@ -28809,24 +30059,26 @@ static JSValue js_dynamic_import_job(JSContext *ctx, goto exception; JS_LoadModuleInternal(ctx, basename, filename, - resolving_funcs); + resolving_funcs, attributes); JS_FreeCString(ctx, filename); JS_FreeCString(ctx, basename); return JS_UNDEFINED; exception: err = JS_GetException(ctx); - ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&err)); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, + 1, (JSValueConst *)&err); JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */ JS_FreeValue(ctx, err); JS_FreeCString(ctx, basename); return JS_UNDEFINED; } -static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options) { JSAtom basename; - JSValue promise, resolving_funcs[2], basename_val; - JSValue args[4]; + JSValue promise, resolving_funcs[2], basename_val, err, ret; + JSValue specifier_str = JS_UNDEFINED, attributes = JS_UNDEFINED, attributes_obj = JS_UNDEFINED; + JSValueConst args[5]; basename = JS_GetScriptOrModuleName(ctx, 0); if (basename == JS_ATOM_NULL) @@ -28843,29 +30095,93 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) return promise; } + /* the string conversion must occur here */ + specifier_str = JS_ToString(ctx, specifier); + if (JS_IsException(specifier_str)) + goto exception; + + if (!JS_IsUndefined(options)) { + if (!JS_IsObject(options)) { + JS_ThrowTypeError(ctx, "options must be an object"); + goto exception; + } + attributes_obj = JS_GetProperty(ctx, options, JS_ATOM_with); + if (JS_IsException(attributes_obj)) + goto exception; + if (!JS_IsUndefined(attributes_obj)) { + JSPropertyEnum *atoms; + uint32_t atoms_len, i; + JSValue val; + + if (!JS_IsObject(attributes_obj)) { + JS_ThrowTypeError(ctx, "options.with must be an object"); + goto exception; + } + attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &atoms_len, JS_VALUE_GET_OBJ(attributes_obj), + JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) { + goto exception; + } + for(i = 0; i < atoms_len; i++) { + val = JS_GetProperty(ctx, attributes_obj, atoms[i].atom); + if (JS_IsException(val)) + goto exception1; + if (!JS_IsString(val)) { + JS_FreeValue(ctx, val); + JS_ThrowTypeError(ctx, "module attribute values must be strings"); + goto exception1; + } + if (JS_DefinePropertyValue(ctx, attributes, atoms[i].atom, val, + JS_PROP_C_W_E) < 0) { + exception1: + JS_FreePropertyEnum(ctx, atoms, atoms_len); + goto exception; + } + } + JS_FreePropertyEnum(ctx, atoms, atoms_len); + if (ctx->rt->module_check_attrs && + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, attributes) < 0) { + goto exception; + } + JS_FreeValue(ctx, attributes_obj); + } + } + args[0] = resolving_funcs[0]; args[1] = resolving_funcs[1]; args[2] = basename_val; - args[3] = unsafe_unconst(specifier); - + args[3] = specifier_str; + args[4] = attributes; + /* cannot run JS_LoadModuleInternal synchronously because it would cause an unexpected recursion in js_evaluate_module() */ - JS_EnqueueJob(ctx, js_dynamic_import_job, 4, vc(args)); - + JS_EnqueueJob(ctx, js_dynamic_import_job, 5, args); + done: JS_FreeValue(ctx, basename_val); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); + JS_FreeValue(ctx, specifier_str); + JS_FreeValue(ctx, attributes); return promise; + exception: + JS_FreeValue(ctx, attributes_obj); + err = JS_GetException(ctx); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, + 1, (JSValueConst *)&err); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, err); + goto done; } static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m) { m->status = JS_MODULE_STATUS_EVALUATED; if (!JS_IsUndefined(m->promise)) { - JSValue ret_val; + JSValue value, ret_val; assert(m->cycle_root == m); - JSValueConst value = JS_UNDEFINED; - ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED, 1, &value); + value = JS_UNDEFINED; + ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED, + 1, (JSValueConst *)&value); JS_FreeValue(ctx, ret_val); } } @@ -28877,14 +30193,14 @@ typedef struct { } ExecModuleList; /* XXX: slow. Could use a linked list instead of ExecModuleList */ -static bool find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m) +static BOOL find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m) { int i; for(i = 0; i < exec_list->count; i++) { if (exec_list->tab[i] == m) - return true; + return TRUE; } - return false; + return FALSE; } static int gather_available_ancestors(JSContext *ctx, JSModuleDef *module, @@ -28931,15 +30247,25 @@ static int exec_module_list_cmp(const void *p1, const void *p2, void *opaque) static int js_execute_async_module(JSContext *ctx, JSModuleDef *m); static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m, JSValue *pvalue); +#ifdef DUMP_MODULE_EXEC +static void js_dump_module(JSContext *ctx, const char *str, JSModuleDef *m) +{ + char buf1[ATOM_GET_STR_BUF_SIZE]; + static const char *module_status_str[] = { "unlinked", "linking", "linked", "evaluating", "evaluating_async", "evaluated" }; + printf("%s: %s status=%s\n", str, JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name), module_status_str[m->status]); +} +#endif static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + int argc, JSValueConst *argv, int magic, JSValue *func_data) { JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]); JSValueConst error = argv[0]; int i; +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, module); +#endif if (js_check_stack_overflow(ctx->rt, 0)) return JS_ThrowStackOverflow(ctx); @@ -28952,15 +30278,16 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t assert(!module->eval_has_exception); assert(module->async_evaluation); - module->eval_has_exception = true; - module->eval_exception = js_dup(error); + module->eval_has_exception = TRUE; + module->eval_exception = JS_DupValue(ctx, error); module->status = JS_MODULE_STATUS_EVALUATED; + module->async_evaluation = FALSE; for(i = 0; i < module->async_parent_modules_count; i++) { JSModuleDef *m = module->async_parent_modules[i]; JSValue m_obj = JS_NewModuleValue(ctx, m); js_async_module_execution_rejected(ctx, JS_UNDEFINED, 1, &error, 0, - vc(&m_obj)); + &m_obj); JS_FreeValue(ctx, m_obj); } @@ -28975,13 +30302,15 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t } static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + int argc, JSValueConst *argv, int magic, JSValue *func_data) { JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]); ExecModuleList exec_list_s, *exec_list = &exec_list_s; int i; +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, module); +#endif if (module->status == JS_MODULE_STATUS_EVALUATED) { assert(module->eval_has_exception); return JS_UNDEFINED; @@ -28989,7 +30318,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC); assert(!module->eval_has_exception); assert(module->async_evaluation); - module->async_evaluation = false; + module->async_evaluation = FALSE; js_set_module_evaluated(ctx, module); exec_list->tab = NULL; @@ -29007,6 +30336,9 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst for(i = 0; i < exec_list->count; i++) { JSModuleDef *m = exec_list->tab[i]; +#ifdef DUMP_MODULE_EXEC + printf(" %d/%d", i, exec_list->count); js_dump_module(ctx, "", m); +#endif if (m->status == JS_MODULE_STATUS_EVALUATED) { assert(m->eval_has_exception); } else if (m->has_tla) { @@ -29016,11 +30348,12 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst if (js_execute_sync_module(ctx, m, &error) < 0) { JSValue m_obj = JS_NewModuleValue(ctx, m); js_async_module_execution_rejected(ctx, JS_UNDEFINED, - 1, vc(&error), - 0, vc(&m_obj)); + 1, (JSValueConst *)&error, 0, + &m_obj); JS_FreeValue(ctx, m_obj); JS_FreeValue(ctx, error); } else { + m->async_evaluation = FALSE; js_set_module_evaluated(ctx, m); } } @@ -29033,13 +30366,16 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m) { JSValue promise, m_obj; JSValue resolve_funcs[2], ret_val; +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, m); +#endif promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0); if (JS_IsException(promise)) return -1; m_obj = JS_NewModuleValue(ctx, m); - resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, vc(&m_obj)); - resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, vc(&m_obj)); - ret_val = js_promise_then(ctx, promise, 2, vc(resolve_funcs)); + resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, (JSValueConst *)&m_obj); + resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, (JSValueConst *)&m_obj); + ret_val = js_promise_then(ctx, promise, 2, (JSValueConst *)resolve_funcs); JS_FreeValue(ctx, ret_val); JS_FreeValue(ctx, m_obj); JS_FreeValue(ctx, resolve_funcs[0]); @@ -29052,6 +30388,9 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m) static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m, JSValue *pvalue) { +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, m); +#endif if (m->init_func) { /* C module init : no asynchronous execution */ if (m->init_func(ctx, m) < 0) @@ -29091,23 +30430,20 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m, JSModuleDef *m1; int i; +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, m); +#endif + if (js_check_stack_overflow(ctx->rt, 0)) { JS_ThrowStackOverflow(ctx); *pvalue = JS_GetException(ctx); return -1; } -#ifdef ENABLE_DUMPS // JS_DUMP_MODULE_RESOLVE - if (check_dump_flag(ctx->rt, JS_DUMP_MODULE_RESOLVE)) { - char buf1[ATOM_GET_STR_BUF_SIZE]; - printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); - } -#endif - if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC || m->status == JS_MODULE_STATUS_EVALUATED) { if (m->eval_has_exception) { - *pvalue = js_dup(m->eval_exception); + *pvalue = JS_DupValue(ctx, m->eval_exception); return -1; } else { *pvalue = JS_UNDEFINED; @@ -29146,7 +30482,7 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m, assert(m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC || m1->status == JS_MODULE_STATUS_EVALUATED); if (m1->eval_has_exception) { - *pvalue = js_dup(m1->eval_exception); + *pvalue = JS_DupValue(ctx, m1->eval_exception); return -1; } } @@ -29162,12 +30498,12 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m, if (m->pending_async_dependencies > 0) { assert(!m->async_evaluation); - m->async_evaluation = true; + m->async_evaluation = TRUE; m->async_evaluation_timestamp = ctx->rt->module_async_evaluation_next_timestamp++; } else if (m->has_tla) { assert(!m->async_evaluation); - m->async_evaluation = true; + m->async_evaluation = TRUE; m->async_evaluation_timestamp = ctx->rt->module_async_evaluation_next_timestamp++; js_execute_async_module(ctx, m); @@ -29204,6 +30540,9 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) JSModuleDef *m1, *stack_top; JSValue ret_val, result; +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, __func__, m); +#endif assert(m->status == JS_MODULE_STATUS_LINKED || m->status == JS_MODULE_STATUS_EVALUATING_ASYNC || m->status == JS_MODULE_STATUS_EVALUATED); @@ -29213,7 +30552,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) } /* a promise may be created only on the cycle_root of a cycle */ if (!JS_IsUndefined(m->promise)) - return js_dup(m->promise); + return JS_DupValue(ctx, m->promise); m->promise = JS_NewPromiseCapability(ctx, m->resolving_funcs); if (JS_IsException(m->promise)) return JS_EXCEPTION; @@ -29224,8 +30563,8 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) m1 = stack_top; assert(m1->status == JS_MODULE_STATUS_EVALUATING); m1->status = JS_MODULE_STATUS_EVALUATED; - m1->eval_has_exception = true; - m1->eval_exception = js_dup(result); + m1->eval_has_exception = TRUE; + m1->eval_exception = JS_DupValue(ctx, result); m1->cycle_root = m; /* spec bug: should be present */ stack_top = m1->stack_prev; } @@ -29233,47 +30572,131 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) assert(m->status == JS_MODULE_STATUS_EVALUATED); assert(m->eval_has_exception); ret_val = JS_Call(ctx, m->resolving_funcs[1], JS_UNDEFINED, - 1, vc(&m->eval_exception)); + 1, (JSValueConst *)&m->eval_exception); JS_FreeValue(ctx, ret_val); } else { +#ifdef DUMP_MODULE_EXEC + js_dump_module(ctx, " done", m); +#endif assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC || m->status == JS_MODULE_STATUS_EVALUATED); assert(!m->eval_has_exception); if (!m->async_evaluation) { + JSValue value; assert(m->status == JS_MODULE_STATUS_EVALUATED); - JSValueConst value = JS_UNDEFINED; + value = JS_UNDEFINED; ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED, - 1, &value); + 1, (JSValueConst *)&value); JS_FreeValue(ctx, ret_val); } assert(stack_top == NULL); } - return js_dup(m->promise); + return JS_DupValue(ctx, m->promise); } -#ifndef QJS_DISABLE_PARSER +static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme) +{ + JSContext *ctx = s->ctx; + JSAtom key; + int ret; + const uint8_t *key_token_ptr; + + if (next_token(s)) + return -1; + if (js_parse_expect(s, '{')) + return -1; + while (s->token.val != '}') { + key_token_ptr = s->token.ptr; + if (s->token.val == TOK_STRING) { + key = JS_ValueToAtom(ctx, s->token.u.str.str); + if (key == JS_ATOM_NULL) + return -1; + } else { + if (!token_is_ident(s->token.val)) { + js_parse_error(s, "identifier expected"); + return -1; + } + key = JS_DupAtom(ctx, s->token.u.ident.atom); + } + if (next_token(s)) + return -1; + if (js_parse_expect(s, ':')) { + JS_FreeAtom(ctx, key); + return -1; + } + if (s->token.val != TOK_STRING) { + js_parse_error_pos(s, key_token_ptr, "string expected"); + return -1; + } + if (JS_IsUndefined(rme->attributes)) { + JSValue attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsException(attributes)) { + JS_FreeAtom(ctx, key); + return -1; + } + rme->attributes = attributes; + } + ret = JS_HasProperty(ctx, rme->attributes, key); + if (ret != 0) { + JS_FreeAtom(ctx, key); + if (ret < 0) + return -1; + else + return js_parse_error(s, "duplicate with key"); + } + ret = JS_DefinePropertyValue(ctx, rme->attributes, key, + JS_DupValue(ctx, s->token.u.str.str), JS_PROP_C_W_E); + JS_FreeAtom(ctx, key); + if (ret < 0) + return -1; + if (next_token(s)) + return -1; + if (s->token.val != ',') + break; + if (next_token(s)) + return -1; + } + if (!JS_IsUndefined(rme->attributes) && + ctx->rt->module_check_attrs && + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) { + return -1; + } + return js_parse_expect(s, '}'); +} -static __exception JSAtom js_parse_from_clause(JSParseState *s) +/* return the module index in m->req_module_entries[] or < 0 if error */ +static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) { JSAtom module_name; + int idx; + if (!token_is_pseudo_keyword(s, JS_ATOM_from)) { js_parse_error(s, "from clause expected"); - return JS_ATOM_NULL; + return -1; } if (next_token(s)) - return JS_ATOM_NULL; + return -1; if (s->token.val != TOK_STRING) { js_parse_error(s, "string expected"); - return JS_ATOM_NULL; + return -1; } module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) - return JS_ATOM_NULL; + return -1; if (next_token(s)) { JS_FreeAtom(s->ctx, module_name); - return JS_ATOM_NULL; + return -1; + } + + idx = add_req_module_entry(s->ctx, m, module_name); + JS_FreeAtom(s->ctx, module_name); + if (idx < 0) + return -1; + if (s->token.val == TOK_WITH) { + if (js_parse_with_clause(s, &m->req_module_entries[idx])) + return -1; } - return module_name; + return idx; } static __exception int js_parse_export(JSParseState *s) @@ -29282,7 +30705,6 @@ static __exception int js_parse_export(JSParseState *s) JSModuleDef *m = s->cur_func->module; JSAtom local_name, export_name; int first_export, idx, i, tok; - JSAtom module_name; JSExportEntry *me; if (next_token(s)) @@ -29290,15 +30712,13 @@ static __exception int js_parse_export(JSParseState *s) tok = s->token.val; if (tok == TOK_CLASS) { - return js_parse_class(s, false, JS_PARSE_EXPORT_NAMED); + return js_parse_class(s, FALSE, JS_PARSE_EXPORT_NAMED); } else if (tok == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) == TOK_FUNCTION)) { + peek_token(s, TRUE) == TOK_FUNCTION)) { return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT, JS_FUNC_NORMAL, JS_ATOM_NULL, s->token.ptr, - s->token.line_num, - s->token.col_num, JS_PARSE_EXPORT_NAMED, NULL); } @@ -29320,11 +30740,21 @@ static __exception int js_parse_export(JSParseState *s) if (token_is_pseudo_keyword(s, JS_ATOM_as)) { if (next_token(s)) goto fail; - if (!token_is_ident(s->token.val)) { - js_parse_error(s, "identifier expected"); - goto fail; + if (s->token.val == TOK_STRING) { + if (js_string_find_invalid_codepoint(JS_VALUE_GET_STRING(s->token.u.str.str)) >= 0) { + js_parse_error(s, "contains unpaired surrogate"); + goto fail; + } + export_name = JS_ValueToAtom(s->ctx, s->token.u.str.str); + if (export_name == JS_ATOM_NULL) + goto fail; + } else { + if (!token_is_ident(s->token.val)) { + js_parse_error(s, "identifier expected"); + goto fail; + } + export_name = JS_DupAtom(ctx, s->token.u.ident.atom); } - export_name = JS_DupAtom(ctx, s->token.u.ident.atom); if (next_token(s)) { fail: JS_FreeAtom(ctx, local_name); @@ -29349,11 +30779,7 @@ static __exception int js_parse_export(JSParseState *s) if (js_parse_expect(s, '}')) return -1; if (token_is_pseudo_keyword(s, JS_ATOM_from)) { - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - return -1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) return -1; for(i = first_export; i < m->export_entries_count; i++) { @@ -29375,11 +30801,7 @@ static __exception int js_parse_export(JSParseState *s) export_name = JS_DupAtom(ctx, s->token.u.ident.atom); if (next_token(s)) goto fail1; - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - goto fail1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) goto fail1; me = add_export_entry(s, m, JS_ATOM__star_, export_name, @@ -29389,11 +30811,7 @@ static __exception int js_parse_export(JSParseState *s) return -1; me->u.req_module_idx = idx; } else { - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - return -1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) return -1; if (add_star_export_entry(ctx, m, idx) < 0) @@ -29402,15 +30820,13 @@ static __exception int js_parse_export(JSParseState *s) break; case TOK_DEFAULT: if (s->token.val == TOK_CLASS) { - return js_parse_class(s, false, JS_PARSE_EXPORT_DEFAULT); + return js_parse_class(s, FALSE, JS_PARSE_EXPORT_DEFAULT); } else if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) == TOK_FUNCTION)) { + peek_token(s, TRUE) == TOK_FUNCTION)) { return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT, JS_FUNC_NORMAL, JS_ATOM_NULL, s->token.ptr, - s->token.line_num, - s->token.col_num, JS_PARSE_EXPORT_DEFAULT, NULL); } else { if (js_parse_assign_expr(s)) @@ -29435,7 +30851,7 @@ static __exception int js_parse_export(JSParseState *s) case TOK_VAR: case TOK_LET: case TOK_CONST: - return js_parse_var(s, PF_IN_ACCEPTED, tok, /*export_flag*/true); + return js_parse_var(s, TRUE, tok, TRUE); default: return js_parse_error(s, "invalid export syntax"); } @@ -29443,18 +30859,17 @@ static __exception int js_parse_export(JSParseState *s) } static int add_closure_var(JSContext *ctx, JSFunctionDef *s, - bool is_local, bool is_arg, + BOOL is_local, BOOL is_arg, int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, + BOOL is_const, BOOL is_lexical, JSVarKindEnum var_kind); static int add_import(JSParseState *s, JSModuleDef *m, - JSAtom local_name, JSAtom import_name) + JSAtom local_name, JSAtom import_name, BOOL is_star) { JSContext *ctx = s->ctx; int i, var_idx; JSImportEntry *mi; - bool is_local; if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval) return js_parse_error(s, "invalid import binding"); @@ -29466,10 +30881,9 @@ static int add_import(JSParseState *s, JSModuleDef *m, } } - is_local = (import_name == JS_ATOM__star_); - var_idx = add_closure_var(ctx, s->cur_func, is_local, false, + var_idx = add_closure_var(ctx, s->cur_func, is_star, FALSE, m->import_entries_count, - local_name, true, true, JS_VAR_NORMAL); + local_name, TRUE, TRUE, FALSE); if (var_idx < 0) return -1; if (js_resize_array(ctx, (void **)&m->import_entries, @@ -29480,6 +30894,7 @@ static int add_import(JSParseState *s, JSModuleDef *m, mi = &m->import_entries[m->import_entries_count++]; mi->import_name = JS_DupAtom(ctx, import_name); mi->var_idx = var_idx; + mi->is_star = is_star; return 0; } @@ -29502,6 +30917,14 @@ static __exception int js_parse_import(JSParseState *s) JS_FreeAtom(ctx, module_name); return -1; } + idx = add_req_module_entry(ctx, m, module_name); + JS_FreeAtom(ctx, module_name); + if (idx < 0) + return -1; + if (s->token.val == TOK_WITH) { + if (js_parse_with_clause(s, &m->req_module_entries[idx])) + return -1; + } } else { if (s->token.val == TOK_IDENT) { if (s->token.u.ident.is_reserved) { @@ -29512,7 +30935,7 @@ static __exception int js_parse_import(JSParseState *s) import_name = JS_ATOM_default; if (next_token(s)) goto fail; - if (add_import(s, m, local_name, import_name)) + if (add_import(s, m, local_name, import_name, FALSE)) goto fail; JS_FreeAtom(ctx, local_name); @@ -29538,7 +30961,7 @@ static __exception int js_parse_import(JSParseState *s) import_name = JS_ATOM__star_; if (next_token(s)) goto fail; - if (add_import(s, m, local_name, import_name)) + if (add_import(s, m, local_name, import_name, TRUE)) goto fail; JS_FreeAtom(ctx, local_name); } else if (s->token.val == '{') { @@ -29546,11 +30969,24 @@ static __exception int js_parse_import(JSParseState *s) return -1; while (s->token.val != '}') { - if (!token_is_ident(s->token.val)) { - js_parse_error(s, "identifier expected"); - return -1; + BOOL is_string; + if (s->token.val == TOK_STRING) { + is_string = TRUE; + if (js_string_find_invalid_codepoint(JS_VALUE_GET_STRING(s->token.u.str.str)) >= 0) { + js_parse_error(s, "contains unpaired surrogate"); + return -1; + } + import_name = JS_ValueToAtom(s->ctx, s->token.u.str.str); + if (import_name == JS_ATOM_NULL) + return -1; + } else { + is_string = FALSE; + if (!token_is_ident(s->token.val)) { + js_parse_error(s, "identifier expected"); + return -1; + } + import_name = JS_DupAtom(ctx, s->token.u.ident.atom); } - import_name = JS_DupAtom(ctx, s->token.u.ident.atom); local_name = JS_ATOM_NULL; if (next_token(s)) goto fail; @@ -29562,16 +30998,19 @@ static __exception int js_parse_import(JSParseState *s) goto fail; } local_name = JS_DupAtom(ctx, s->token.u.ident.atom); - if (next_token(s)) { + if (next_token(s)) + goto fail; + } else { + if (is_string) { + js_parse_error(s, "expecting 'as'"); fail: JS_FreeAtom(ctx, local_name); JS_FreeAtom(ctx, import_name); return -1; } - } else { local_name = JS_DupAtom(ctx, import_name); } - if (add_import(s, m, local_name, import_name)) + if (add_import(s, m, local_name, import_name, FALSE)) goto fail; JS_FreeAtom(ctx, local_name); JS_FreeAtom(ctx, import_name); @@ -29584,14 +31023,10 @@ static __exception int js_parse_import(JSParseState *s) return -1; } end_import_clause: - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) + idx = js_parse_from_clause(s, m); + if (idx < 0) return -1; } - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); - if (idx < 0) - return -1; for(i = first_import; i < m->import_entries_count; i++) m->import_entries[i].req_module_idx = idx; @@ -29605,18 +31040,16 @@ static __exception int js_parse_source_element(JSParseState *s) if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) == TOK_FUNCTION)) { + peek_token(s, TRUE) == TOK_FUNCTION)) { if (js_parse_function_decl(s, JS_PARSE_FUNC_STATEMENT, JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, - s->token.line_num, - s->token.col_num)) + s->token.ptr)) return -1; } else if (s->token.val == TOK_EXPORT && fd->module) { if (js_parse_export(s)) return -1; } else if (s->token.val == TOK_IMPORT && fd->module && - ((tok = peek_token(s, false)) != '(' && tok != '.')) { + ((tok = peek_token(s, FALSE)) != '(' && tok != '.')) { /* the peek_token is needed to avoid confusion with ImportCall (dynamic import) or import.meta */ if (js_parse_import(s)) @@ -29628,14 +31061,13 @@ static __exception int js_parse_source_element(JSParseState *s) return 0; } -/* `filename` may be pure ASCII or UTF-8 encoded */ static JSFunctionDef *js_new_function_def(JSContext *ctx, JSFunctionDef *parent, - bool is_eval, - bool is_func_expr, + BOOL is_eval, + BOOL is_func_expr, const char *filename, - int line_num, - int col_num) + const uint8_t *source_ptr, + GetLineColCache *get_line_col_cache) { JSFunctionDef *fd; @@ -29651,13 +31083,15 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, fd->parent_cpool_idx = -1; if (parent) { list_add_tail(&fd->link, &parent->child_list); - fd->is_strict_mode = parent->is_strict_mode; + fd->js_mode = parent->js_mode; fd->parent_scope_level = parent->scope_level; } + fd->strip_debug = ((ctx->rt->strip_flags & JS_STRIP_DEBUG) != 0); + fd->strip_source = ((ctx->rt->strip_flags & (JS_STRIP_DEBUG | JS_STRIP_SOURCE)) != 0); fd->is_eval = is_eval; fd->is_func_expr = is_func_expr; - js_dbuf_init(ctx, &fd->byte_code); + js_dbuf_bytecode_init(ctx, &fd->byte_code); fd->last_opcode_pos = -1; fd->func_name = JS_ATOM_NULL; fd->var_object_idx = -1; @@ -29682,21 +31116,19 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, fd->body_scope = -1; fd->filename = JS_NewAtom(ctx, filename); - fd->line_num = line_num; - fd->col_num = col_num; - + fd->source_pos = source_ptr - get_line_col_cache->buf_start; + fd->get_line_col_cache = get_line_col_cache; + js_dbuf_init(ctx, &fd->pc2line); //fd->pc2line_last_line_num = line_num; //fd->pc2line_last_pc = 0; - + fd->last_opcode_source_ptr = source_ptr; return fd; } -#endif // QJS_DISABLE_PARSER - static void free_bytecode_atoms(JSRuntime *rt, const uint8_t *bc_buf, int bc_len, - bool use_short_opcodes) + BOOL use_short_opcodes) { int pos, len, op; JSAtom atom; @@ -29729,8 +31161,6 @@ static void free_bytecode_atoms(JSRuntime *rt, } } -#ifndef QJS_DISABLE_PARSER - static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) { int i; @@ -29748,7 +31178,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) dbuf_free(&fd->byte_code); js_free(ctx, fd->jump_slots); js_free(ctx, fd->label_slots); - js_free(ctx, fd->source_loc_slots); + js_free(ctx, fd->line_number_slots); for(i = 0; i < fd->cpool_count; i++) { JS_FreeValue(ctx, fd->cpool[i]); @@ -29761,7 +31191,6 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) JS_FreeAtom(ctx, fd->vars[i].var_name); } js_free(ctx, fd->vars); - js_free(ctx, fd->vars_htab); // XXX can probably be freed earlier? for(i = 0; i < fd->arg_count; i++) { JS_FreeAtom(ctx, fd->args[i].var_name); } @@ -29793,11 +31222,9 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) js_free(ctx, fd); } -#endif // QJS_DISABLE_PARSER - -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_* +#ifdef DUMP_BYTECODE static const char *skip_lines(const char *p, int n) { - while (p && n-- > 0 && *p) { + while (n-- > 0 && *p) { while (*p && *p++ != '\n') continue; } @@ -29807,7 +31234,7 @@ static const char *skip_lines(const char *p, int n) { static void print_lines(const char *source, int line, int line1) { const char *s = source; const char *p = skip_lines(s, line); - if (p && *p) { + if (*p) { while (line++ < line1) { p = skip_lines(s = p, 1); printf(";; %.*s", (int)(p - s), s); @@ -29826,18 +31253,19 @@ static void dump_byte_code(JSContext *ctx, int pass, const JSVarDef *vars, int var_count, const JSClosureVar *closure_var, int closure_var_count, const JSValue *cpool, uint32_t cpool_count, - const char *source, int line_num, - const LabelSlot *label_slots, JSFunctionBytecode *b, - int start_pos) + const char *source, + const LabelSlot *label_slots, JSFunctionBytecode *b) { const JSOpCode *oi; - int pos, pos_next, op, size, idx, addr, line, line1, in_source; + int pos, pos_next, op, size, idx, addr, line, line1, in_source, line_num; uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits)); - bool use_short_opcodes = (b != NULL); - - if (start_pos != 0 || bits == NULL) - goto no_labels; + BOOL use_short_opcodes = (b != NULL); + if (b) { + int col_num; + line_num = find_line_num(ctx, b, -1, &col_num); + } + /* scan for jump targets */ for (pos = 0; pos < len; pos = pos_next) { op = tab[pos]; @@ -29848,6 +31276,7 @@ static void dump_byte_code(JSContext *ctx, int pass, pos_next = pos + oi->size; if (op < OP_COUNT) { switch (oi->fmt) { +#if SHORT_OPCODES case OP_FMT_label8: pos++; addr = (int8_t)tab[pos]; @@ -29856,6 +31285,7 @@ static void dump_byte_code(JSContext *ctx, int pass, pos++; addr = (int16_t)get_u16(tab + pos); goto has_addr; +#endif case OP_FMT_atom_label_u8: case OP_FMT_atom_label_u16: pos += 4; @@ -29878,7 +31308,6 @@ static void dump_byte_code(JSContext *ctx, int pass, } } } - no_labels: in_source = 0; if (source) { /* Always print first line: needed if single line */ @@ -29889,11 +31318,12 @@ static void dump_byte_code(JSContext *ctx, int pass, pos = 0; while (pos < len) { op = tab[pos]; - if (source) { + if (source && b) { + int col_num; if (b) { - int col1; - line1 = find_line_num(ctx, b, pos, &col1) - line_num + 1; - } else if (op == OP_source_loc) { + line1 = find_line_num(ctx, b, pos, &col_num) - line_num + 1; + } else if (op == OP_line_num) { + /* XXX: no longer works */ line1 = get_u32(tab + pos + 1) - line_num + 1; } if (line1 > line) { @@ -29922,8 +31352,8 @@ static void dump_byte_code(JSContext *ctx, int pass, printf("truncated opcode (0x%02x)\n", op); break; } -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_HEX - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_HEX)) { +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 16) + { int i, x, x0; x = x0 = printf("%5d ", pos); for (i = 0; i < size; i++) { @@ -29935,12 +31365,12 @@ static void dump_byte_code(JSContext *ctx, int pass, printf("%*s", x0 + 20 - x, ""); } #endif - if (bits && bits[pos]) { + if (bits[pos]) { printf("%5d: ", pos); } else { printf(" "); } - printf("%-15s", oi->name); /* align opcode arguments */ + printf("%s", oi->name); pos++; switch(oi->fmt) { case OP_FMT_none_int: @@ -29971,42 +31401,47 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_u32: printf(" %u", get_u32(tab + pos)); break; - case OP_FMT_u32x2: - printf(" %u:%u", get_u32(tab + pos), get_u32(tab + pos + 4)); - break; +#if SHORT_OPCODES case OP_FMT_label8: addr = get_i8(tab + pos); goto has_addr1; case OP_FMT_label16: addr = get_i16(tab + pos); goto has_addr1; +#endif case OP_FMT_label: - case OP_FMT_label_u16: addr = get_u32(tab + pos); + goto has_addr1; has_addr1: if (pass == 1) - printf(" %d:%u", addr, label_slots[addr].pos); + printf(" %u:%u", addr, label_slots[addr].pos); if (pass == 2) - printf(" %d:%u", addr, label_slots[addr].pos2); - if (pass == 3) { - if (start_pos) - printf(" %04x", addr + pos + start_pos); - else - printf(" %d", addr + pos); - } - if (oi->fmt == OP_FMT_label_u16) - printf(",%u", get_u16(tab + pos + 4)); + printf(" %u:%u", addr, label_slots[addr].pos2); + if (pass == 3) + printf(" %u", addr + pos); + break; + case OP_FMT_label_u16: + addr = get_u32(tab + pos); + if (pass == 1) + printf(" %u:%u", addr, label_slots[addr].pos); + if (pass == 2) + printf(" %u:%u", addr, label_slots[addr].pos2); + if (pass == 3) + printf(" %u", addr + pos); + printf(",%u", get_u16(tab + pos + 4)); break; +#if SHORT_OPCODES case OP_FMT_const8: idx = get_u8(tab + pos); goto has_pool_idx; +#endif case OP_FMT_const: idx = get_u32(tab + pos); goto has_pool_idx; has_pool_idx: - printf(" %-4u ; ", idx); + printf(" %u: ", idx); if (idx < cpool_count) { - JS_DumpValue(ctx->rt, cpool[idx]); + JS_PrintValue(ctx, js_dump_value_write, stdout, cpool[idx], NULL); } break; case OP_FMT_atom: @@ -30040,24 +31475,15 @@ static void dump_byte_code(JSContext *ctx, int pass, printf(",%u", get_u16(tab + pos + 8)); break; case OP_FMT_none_loc: - if (op == OP_get_loc0_loc1) { - printf(" 0, 1 ; "); - if (var_count > 0) - print_atom(ctx, vars[0].var_name); - if (var_count > 1) - print_atom(ctx, vars[1].var_name); - } else { - idx = (op - OP_get_loc0) % 4; - goto has_loc; - } - break; + idx = (op - OP_get_loc0) % 4; + goto has_loc; case OP_FMT_loc8: idx = get_u8(tab + pos); goto has_loc; case OP_FMT_loc: idx = get_u16(tab + pos); has_loc: - printf(" %-4d ; ", idx); + printf(" %d: ", idx); if (idx < var_count) { print_atom(ctx, vars[idx].var_name); } @@ -30068,7 +31494,7 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_arg: idx = get_u16(tab + pos); has_arg: - printf(" %-4d ; ", idx); + printf(" %d: ", idx); if (idx < arg_count) { print_atom(ctx, args[idx].var_name); } @@ -30079,7 +31505,7 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_var_ref: idx = get_u16(tab + pos); has_var_ref: - printf(" %-4d ; ", idx); + printf(" %d: ", idx); if (idx < closure_var_count) { print_atom(ctx, closure_var[idx].var_name); } @@ -30098,86 +31524,64 @@ static void dump_byte_code(JSContext *ctx, int pass, js_free(ctx, bits); } -// caveat emptor: intended to be called during execution of bytecode -// and only works for pass3 bytecode -static __maybe_unused void dump_single_byte_code(JSContext *ctx, - const uint8_t *pc, - JSFunctionBytecode *b, - int start_pos) +static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len) { - JSVarDef *args, *vars; - - args = vars = b->vardefs; - if (vars) - vars = &vars[b->arg_count]; - - dump_byte_code(ctx, /*pass*/3, pc, short_opcode_info(*pc).size, - args, b->arg_count, vars, b->var_count, - b->closure_var, b->closure_var_count, - b->cpool, b->cpool_count, - NULL, b->line_num, - NULL, b, start_pos); -} - -static __maybe_unused void print_func_name(JSFunctionBytecode *b) -{ - print_lines(b->source, 0, 1); -} - -static __maybe_unused void dump_pc2line(JSContext *ctx, - const uint8_t *buf, int len, - int line_num, int col_num) -{ - const uint8_t *p_end, *p_next, *p; - int pc, v; + const uint8_t *p_end, *p; + int pc, v, line_num, col_num, ret; unsigned int op; - + uint32_t val; + if (len <= 0) return; - printf("%5s %5s %5s\n", "PC", "LINE", "COLUMN"); + printf("%5s %5s %5s\n", "PC", "LINE", "COL"); p = buf; p_end = buf + len; + + /* get the function line and column numbers */ + ret = get_leb128(&val, p, p_end); + if (ret < 0) + goto fail; + p += ret; + line_num = val + 1; + + ret = get_leb128(&val, p, p_end); + if (ret < 0) + goto fail; + p += ret; + col_num = val + 1; + + printf("%5s %5d %5d\n", "-", line_num, col_num); + pc = 0; while (p < p_end) { op = *p++; if (op == 0) { - v = utf8_decode_len(p, p_end - p, &p_next); - if (v < 0) + ret = get_leb128(&val, p, p_end); + if (ret < 0) goto fail; - pc += v; - p = p_next; - v = utf8_decode_len(p, p_end - p, &p_next); - if (v < 0) + pc += val; + p += ret; + ret = get_sleb128(&v, p, p_end); + if (ret < 0) goto fail; - if (v & 1) { - v = -(v >> 1) - 1; - } else { - v = v >> 1; - } + p += ret; line_num += v; - p = p_next; } else { op -= PC2LINE_OP_FIRST; pc += (op / PC2LINE_RANGE); line_num += (op % PC2LINE_RANGE) + PC2LINE_BASE; } - v = utf8_decode_len(p, p_end - p, &p_next); - if (v < 0) + ret = get_sleb128(&v, p, p_end); + if (ret < 0) goto fail; - if (v & 1) { - v = -(v >> 1) - 1; - } else { - v = v >> 1; - } + p += ret; col_num += v; - p = p_next; + printf("%5d %5d %5d\n", pc, line_num, col_num); } - return; -fail: - printf("invalid pc2line encode pos=%d\n", (int)(p - buf)); + fail: ; } static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b) @@ -30185,16 +31589,22 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB int i; char atom_buf[ATOM_GET_STR_BUF_SIZE]; const char *str; - const uint8_t *op; - if (b->filename != JS_ATOM_NULL) { - str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->filename); - printf("%s:%d:%d: ", str, b->line_num, b->col_num); + if (b->has_debug && b->debug.filename != JS_ATOM_NULL) { + int line_num, col_num; + str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->debug.filename); + line_num = find_line_num(ctx, b, -1, &col_num); + printf("%s:%d:%d: ", str, line_num, col_num); } str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name); printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str); - printf(" mode: %s\n", b->is_strict_mode ? "strict" : "sloppy"); + if (b->js_mode) { + printf(" mode:"); + if (b->js_mode & JS_MODE_STRICT) + printf(" strict"); + printf("\n"); + } if (b->arg_count && b->vardefs) { printf(" args:"); for(i = 0; i < b->arg_count; i++) { @@ -30232,40 +31642,33 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB } } printf(" stack_size: %d\n", b->stack_size); - printf(" byte_code_len: %d\n", b->byte_code_len); - op = b->byte_code_buf; - for (i = 0; op < &b->byte_code_buf[b->byte_code_len]; i++) - op += short_opcode_info(*op).size; - printf(" opcodes: %d\n", i); + printf(" opcodes:\n"); dump_byte_code(ctx, 3, b->byte_code_buf, b->byte_code_len, b->vardefs, b->arg_count, b->vardefs ? b->vardefs + b->arg_count : NULL, b->var_count, b->closure_var, b->closure_var_count, b->cpool, b->cpool_count, - b->source, b->line_num, NULL, b, 0); -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PC2LINE - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PC2LINE)) - dump_pc2line(ctx, b->pc2line_buf, b->pc2line_len, b->line_num, b->col_num); + b->has_debug ? b->debug.source : NULL, + NULL, b); +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 32) + if (b->has_debug) + dump_pc2line(ctx, b->debug.pc2line_buf, b->debug.pc2line_len); #endif printf("\n"); } #endif -#ifndef QJS_DISABLE_PARSER - static int add_closure_var(JSContext *ctx, JSFunctionDef *s, - bool is_local, bool is_arg, + BOOL is_local, BOOL is_arg, int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, + BOOL is_const, BOOL is_lexical, JSVarKindEnum var_kind) { JSClosureVar *cv; /* the closure variable indexes are currently stored on 16 bits */ if (s->closure_var_count >= JS_MAX_LOCAL_VARS) { - // XXX: add_closure_var() should take JSParseState *s and use js_parse_error - JS_ThrowSyntaxError(ctx, "too many closure variables used (only %d allowed)", - JS_MAX_LOCAL_VARS - 1); + JS_ThrowInternalError(ctx, "too many closure variables"); return -1; } @@ -30297,12 +31700,12 @@ static int find_closure_var(JSContext *ctx, JSFunctionDef *s, } /* 'fd' must be a parent of 's'. Create in 's' a closure referencing a - local variable (is_local = true) or a closure (is_local = false) in + local variable (is_local = TRUE) or a closure (is_local = FALSE) in 'fd' */ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, - JSFunctionDef *fd, bool is_local, - bool is_arg, int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, + JSFunctionDef *fd, BOOL is_local, + BOOL is_arg, int var_idx, JSAtom var_name, + BOOL is_const, BOOL is_lexical, JSVarKindEnum var_kind) { int i; @@ -30313,7 +31716,7 @@ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, is_const, is_lexical, var_kind); if (var_idx < 0) return -1; - is_local = false; + is_local = FALSE; } for(i = 0; i < s->closure_var_count; i++) { JSClosureVar *cv = &s->closure_var[i]; @@ -30326,12 +31729,12 @@ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, } static int get_closure_var(JSContext *ctx, JSFunctionDef *s, - JSFunctionDef *fd, bool is_arg, + JSFunctionDef *fd, BOOL is_arg, int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, + BOOL is_const, BOOL is_lexical, JSVarKindEnum var_kind) { - return get_closure_var2(ctx, s, fd, true, is_arg, + return get_closure_var2(ctx, s, fd, TRUE, is_arg, var_idx, var_name, is_const, is_lexical, var_kind); } @@ -30344,7 +31747,7 @@ static int get_with_scope_opcode(int op) return OP_with_get_var + (op - OP_scope_get_var); } -static bool can_opt_put_ref_value(const uint8_t *bc_buf, int pos) +static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos) { int opcode = bc_buf[pos]; return (bc_buf[pos + 1] == OP_put_ref_value && @@ -30354,7 +31757,7 @@ static bool can_opt_put_ref_value(const uint8_t *bc_buf, int pos) opcode == OP_rot3l)); } -static bool can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos) +static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos) { int opcode = bc_buf[pos]; return (bc_buf[pos + 1] == OP_put_ref_value && @@ -30414,19 +31817,10 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, JSAtom var_name) { int label_pos, end_pos, pos, op; - bool is_strict_mode = s->is_strict_mode; /* replace the reference get/put with normal variable accesses */ - if (is_strict_mode) { - /* need to check if the variable exists before evaluating the right - expression */ - /* XXX: need an extra OP_true if destructuring an array */ - dbuf_putc(bc, OP_check_var); - dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); - } else { - /* XXX: need 2 extra OP_true if destructuring an array */ - } + /* XXX: need 2 extra OP_true if destructuring an array */ if (bc_buf[pos_next] == OP_get_ref_value) { dbuf_putc(bc, OP_get_var); dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); @@ -30440,34 +31834,10 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, assert(bc_buf[pos] == OP_label); end_pos = label_pos + 2; op = bc_buf[label_pos]; - if (is_strict_mode) { - if (op != OP_nop) { - switch(op) { - case OP_insert3: - op = OP_insert2; - break; - case OP_perm4: - op = OP_perm3; - break; - case OP_rot3l: - op = OP_swap; - break; - default: - abort(); - } - bc_buf[pos++] = op; - } - } else { - if (op == OP_insert3) - bc_buf[pos++] = OP_dup; - } - if (is_strict_mode) { - bc_buf[pos] = OP_put_var_strict; - /* XXX: need 1 extra OP_drop if destructuring an array */ - } else { - bc_buf[pos] = OP_put_var; - /* XXX: need 2 extra OP_drop if destructuring an array */ - } + if (op == OP_insert3) + bc_buf[pos++] = OP_dup; + bc_buf[pos] = OP_put_var; + /* XXX: need 2 extra OP_drop if destructuring an array */ put_u32(bc_buf + pos + 1, JS_DupAtom(ctx, var_name)); pos += 5; /* pad with OP_nop */ @@ -30532,7 +31902,7 @@ static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s, the case, handle it and jump to 'label_done' */ static void var_object_test(JSContext *ctx, JSFunctionDef *s, JSAtom var_name, int op, DynBuf *bc, - int *plabel_done, bool is_with) + int *plabel_done, BOOL is_with) { dbuf_putc(bc, get_with_scope_opcode(op)); dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); @@ -30559,7 +31929,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, int label_done; JSFunctionDef *fd; JSVarDef *vd; - bool is_pseudo_var, is_arg_scope; + BOOL is_pseudo_var, is_arg_scope; label_done = -1; @@ -30671,6 +32041,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, case OP_scope_get_ref: dbuf_putc(bc, OP_undefined); /* fall thru */ + case OP_scope_get_var_checkthis: case OP_scope_get_var_undef: case OP_scope_get_var: case OP_scope_put_var: @@ -30696,7 +32067,12 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, } } else { if (s->vars[var_idx].is_lexical) { - dbuf_putc(bc, OP_get_loc_check); + if (op == OP_scope_get_var_checkthis) { + /* only used for 'this' return in derived class constructors */ + dbuf_putc(bc, OP_get_loc_checkthis); + } else { + dbuf_putc(bc, OP_get_loc_check); + } } else { dbuf_putc(bc, OP_get_loc); } @@ -30742,7 +32118,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, break; } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) { vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, idx, vd->var_name, false, false, JS_VAR_NORMAL); + idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, JS_VAR_NORMAL); if (idx >= 0) { dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); @@ -30779,9 +32155,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, if (!is_arg_scope && fd->var_object_idx >= 0 && !is_pseudo_var) { vd = &fd->vars[fd->var_object_idx]; vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, + idx = get_closure_var(ctx, s, fd, FALSE, fd->var_object_idx, vd->var_name, - false, false, JS_VAR_NORMAL); + FALSE, FALSE, JS_VAR_NORMAL); dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); var_object_test(ctx, s, var_name, op, bc, &label_done, 0); @@ -30791,9 +32167,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, if (fd->arg_var_object_idx >= 0 && !is_pseudo_var) { vd = &fd->vars[fd->arg_var_object_idx]; vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, + idx = get_closure_var(ctx, s, fd, FALSE, fd->arg_var_object_idx, vd->var_name, - false, false, JS_VAR_NORMAL); + FALSE, FALSE, JS_VAR_NORMAL); dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); var_object_test(ctx, s, var_name, op, bc, &label_done, 0); @@ -30814,7 +32190,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, if (var_name == cv->var_name) { if (fd != s) { idx = get_closure_var2(ctx, s, fd, - false, + FALSE, cv->is_arg, idx1, cv->var_name, cv->is_const, cv->is_lexical, cv->var_kind); @@ -30828,9 +32204,9 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, int is_with = (cv->var_name == JS_ATOM__with_); if (fd != s) { idx = get_closure_var2(ctx, s, fd, - false, + FALSE, cv->is_arg, idx1, - cv->var_name, false, false, + cv->var_name, FALSE, FALSE, JS_VAR_NORMAL); } else { idx = idx1; @@ -30847,12 +32223,12 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, if (var_idx & ARGUMENT_VAR_OFFSET) { fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1; idx = get_closure_var(ctx, s, fd, - true, var_idx - ARGUMENT_VAR_OFFSET, - var_name, false, false, JS_VAR_NORMAL); + TRUE, var_idx - ARGUMENT_VAR_OFFSET, + var_name, FALSE, FALSE, JS_VAR_NORMAL); } else { fd->vars[var_idx].is_captured = 1; idx = get_closure_var(ctx, s, fd, - false, var_idx, + FALSE, var_idx, var_name, fd->vars[var_idx].is_const, fd->vars[var_idx].is_lexical, @@ -30997,7 +32373,7 @@ static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd, return -1; } -static void get_loc_or_ref(DynBuf *bc, bool is_ref, int idx) +static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx) { /* if the field is not initialized, the error is catched when accessing it */ @@ -31009,23 +32385,23 @@ static void get_loc_or_ref(DynBuf *bc, bool is_ref, int idx) } static int resolve_scope_private_field1(JSContext *ctx, - bool *pis_ref, int *pvar_kind, + BOOL *pis_ref, int *pvar_kind, JSFunctionDef *s, JSAtom var_name, int scope_level) { int idx, var_kind; JSFunctionDef *fd; - bool is_ref; + BOOL is_ref; fd = s; - is_ref = false; + is_ref = FALSE; for(;;) { idx = find_private_class_field_all(ctx, fd, var_name, scope_level); if (idx >= 0) { var_kind = fd->vars[idx].var_kind; if (is_ref) { - idx = get_closure_var(ctx, s, fd, false, idx, var_name, - true, true, JS_VAR_NORMAL); + idx = get_closure_var(ctx, s, fd, FALSE, idx, var_name, + TRUE, TRUE, JS_VAR_NORMAL); if (idx < 0) return -1; } @@ -31039,10 +32415,10 @@ static int resolve_scope_private_field1(JSContext *ctx, JSClosureVar *cv = &fd->closure_var[idx]; if (cv->var_name == var_name) { var_kind = cv->var_kind; - is_ref = true; + is_ref = TRUE; if (fd != s) { idx = get_closure_var2(ctx, s, fd, - false, + FALSE, cv->is_arg, idx, cv->var_name, cv->is_const, cv->is_lexical, @@ -31055,14 +32431,13 @@ static int resolve_scope_private_field1(JSContext *ctx, } } /* XXX: no line number info */ - // XXX: resolve_scope_private_field1() should take JSParseState *s and use js_parse_error_atom JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'", var_name); return -1; } else { fd = fd->parent; } - is_ref = true; + is_ref = TRUE; } done: *pis_ref = is_ref; @@ -31076,7 +32451,7 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s, DynBuf *bc) { int idx, var_kind; - bool is_ref; + BOOL is_ref; idx = resolve_scope_private_field1(ctx, &is_ref, &var_kind, s, var_name, scope_level); @@ -31185,7 +32560,7 @@ static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s, } /* XXX: should handle the argument scope generically */ -static bool is_var_in_arg_scope(const JSVarDef *vd) +static BOOL is_var_in_arg_scope(const JSVarDef *vd) { return (vd->var_name == JS_ATOM_home_object || vd->var_name == JS_ATOM_this_active_func || @@ -31200,11 +32575,11 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) JSFunctionDef *fd; JSVarDef *vd; int i, scope_level, scope_idx; - bool has_arguments_binding, has_this_binding, is_arg_scope; + BOOL has_arguments_binding, has_this_binding, is_arg_scope; /* in non strict mode, variables are created in the caller's environment object */ - if (!s->is_eval && !s->is_strict_mode) { + if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) { s->var_object_idx = add_var(ctx, s, JS_ATOM__var_); if (s->has_parameter_expressions) { /* an additional variable object is needed for the @@ -31231,7 +32606,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) /* also add an arguments binding in the argument scope to raise an error if a direct eval in the argument scope tries to redefine it */ - if (s->has_parameter_expressions && !s->is_strict_mode) + if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT)) add_arguments_arg(ctx, s); } if (s->is_func_expr && s->func_name != JS_ATOM_NULL) @@ -31260,12 +32635,12 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func); if (fd->has_home_object && fd->home_object_var_idx < 0) fd->home_object_var_idx = add_var(ctx, fd, JS_ATOM_home_object); - has_this_binding = true; + has_this_binding = TRUE; } /* add 'arguments' if it was not previously added */ if (!has_arguments_binding && fd->has_arguments_binding) { add_arguments_var(ctx, fd); - has_arguments_binding = true; + has_arguments_binding = TRUE; } /* add function name */ if (fd->is_func_expr && fd->func_name != JS_ATOM_NULL) @@ -31276,7 +32651,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) while (scope_idx >= 0) { vd = &fd->vars[scope_idx]; vd->is_captured = 1; - get_closure_var(ctx, s, fd, false, scope_idx, + get_closure_var(ctx, s, fd, FALSE, scope_idx, vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind); scope_idx = vd->scope_next; } @@ -31288,7 +32663,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd = &fd->args[i]; if (vd->var_name != JS_ATOM_NULL) { get_closure_var(ctx, s, fd, - true, i, vd->var_name, false, + TRUE, i, vd->var_name, FALSE, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31299,7 +32674,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd->var_name != JS_ATOM__ret_ && vd->var_name != JS_ATOM_NULL) { get_closure_var(ctx, s, fd, - false, i, vd->var_name, false, + FALSE, i, vd->var_name, FALSE, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31309,7 +32684,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) /* do not close top level last result */ if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) { get_closure_var(ctx, s, fd, - false, i, vd->var_name, false, + FALSE, i, vd->var_name, FALSE, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31321,7 +32696,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) for (idx = 0; idx < fd->closure_var_count; idx++) { JSClosureVar *cv = &fd->closure_var[idx]; get_closure_var2(ctx, s, fd, - false, cv->is_arg, + FALSE, cv->is_arg, idx, cv->var_name, cv->is_const, cv->is_lexical, cv->var_kind); } @@ -31332,8 +32707,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv, JSVarDef *vd, int var_idx) { - cv->is_local = true; - cv->is_arg = false; + cv->is_local = TRUE; + cv->is_arg = FALSE; cv->is_const = vd->is_const; cv->is_lexical = vd->is_lexical; cv->var_kind = vd->var_kind; @@ -31348,7 +32723,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, { int i, count; JSVarDef *vd; - bool is_arg_scope; + BOOL is_arg_scope; count = b->arg_count + b->var_count + b->closure_var_count; s->closure_var = NULL; @@ -31374,10 +32749,10 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, for(i = 0; i < b->arg_count; i++) { JSClosureVar *cv = &s->closure_var[s->closure_var_count++]; vd = &b->vardefs[i]; - cv->is_local = true; - cv->is_arg = true; - cv->is_const = false; - cv->is_lexical = false; + cv->is_local = TRUE; + cv->is_arg = TRUE; + cv->is_const = FALSE; + cv->is_lexical = FALSE; cv->var_kind = JS_VAR_NORMAL; cv->var_idx = i; cv->var_name = JS_DupAtom(ctx, vd->var_name); @@ -31403,7 +32778,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv0 = &b->closure_var[i]; JSClosureVar *cv = &s->closure_var[s->closure_var_count++]; - cv->is_local = false; + cv->is_local = FALSE; cv->is_arg = cv0->is_arg; cv->is_const = cv0->is_const; cv->is_lexical = cv0->is_lexical; @@ -31418,8 +32793,7 @@ typedef struct CodeContext { const uint8_t *bc_buf; /* code buffer */ int bc_len; /* length of the code buffer */ int pos; /* position past the matched code pattern */ - int line_num; /* last visited OP_source_loc parameter or -1 */ - int col_num; /* last visited OP_source_loc parameter or -1 */ + int line_num; /* last visited OP_line_num parameter or -1 */ int op; int idx; int label; @@ -31427,19 +32801,18 @@ typedef struct CodeContext { JSAtom atom; } CodeContext; -#define M2(op1, op2) ((uint32_t)(op1) | ((uint32_t)(op2) << 8)) -#define M3(op1, op2, op3) ((uint32_t)(op1) | ((uint32_t)(op2) << 8) | ((uint32_t)(op3) << 16)) -#define M4(op1, op2, op3, op4) ((uint32_t)(op1) | ((uint32_t)(op2) << 8) | ((uint32_t)(op3) << 16) | ((uint32_t)(op4) << 24)) +#define M2(op1, op2) ((op1) | ((op2) << 8)) +#define M3(op1, op2, op3) ((op1) | ((op2) << 8) | ((op3) << 16)) +#define M4(op1, op2, op3, op4) ((op1) | ((op2) << 8) | ((op3) << 16) | ((op4) << 24)) -static bool code_match(CodeContext *s, int pos, ...) +static BOOL code_match(CodeContext *s, int pos, ...) { const uint8_t *tab = s->bc_buf; - int op, len, op1, line_num, col_num, pos_next; + int op, len, op1, line_num, pos_next; va_list ap; - bool ret = false; + BOOL ret = FALSE; line_num = -1; - col_num = -1; va_start(ap, pos); for(;;) { @@ -31447,8 +32820,7 @@ static bool code_match(CodeContext *s, int pos, ...) if (op1 == -1) { s->pos = pos; s->line_num = line_num; - s->col_num = col_num; - ret = true; + ret = TRUE; break; } for (;;) { @@ -31459,9 +32831,8 @@ static bool code_match(CodeContext *s, int pos, ...) pos_next = pos + len; if (pos_next > s->bc_len) goto done; - if (op == OP_source_loc) { + if (op == OP_line_num) { line_num = get_u32(tab + pos + 1); - col_num = get_u32(tab + pos + 5); pos = pos_next; } else { break; @@ -31591,7 +32962,6 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy dbuf_set_error(bc); return; } - /* if 'this' is true, initialize the global variables and return */ dbuf_putc(bc, OP_push_this); dbuf_putc(bc, OP_if_false); @@ -31605,7 +32975,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy for(i = 0; i < s->global_var_count; i++) { JSGlobalVar *hf = &s->global_vars[i]; int has_closure = 0; - bool force_init = hf->force_init; + BOOL force_init = hf->force_init; /* we are in an eval, so the closure contains all the enclosing variables */ /* If the outer function has a variable environment, @@ -31614,7 +32984,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy JSClosureVar *cv = &s->closure_var[idx]; if (cv->var_name == hf->var_name) { has_closure = 2; - force_init = false; + force_init = FALSE; break; } if (cv->var_name == JS_ATOM__var_ || @@ -31622,7 +32992,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); has_closure = 1; - force_init = true; + force_init = TRUE; break; } } @@ -31697,20 +33067,26 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy } static int skip_dead_code(JSFunctionDef *s, const uint8_t *bc_buf, int bc_len, - int pos, int *linep, int *colp) + int pos, int *linep) { int op, len, label; for (; pos < bc_len; pos += len) { op = bc_buf[pos]; len = opcode_info[op].size; - if (op == OP_source_loc) { + if (op == OP_line_num) { *linep = get_u32(bc_buf + pos + 1); - *colp = get_u32(bc_buf + pos + 5); - } else if (op == OP_label) { + } else + if (op == OP_label) { label = get_u32(bc_buf + pos + 1); if (update_label(s, label, 0) > 0) break; +#if 0 + if (s->label_slots[label].first_reloc) { + printf("line %d: unreferenced label %d:%d has relocations\n", + *linep, label, s->label_slots[label].pos2); + } +#endif assert(s->label_slots[label].first_reloc == NULL); } else { /* XXX: output a warning for unreachable code? */ @@ -31747,9 +33123,7 @@ static int get_label_pos(JSFunctionDef *s, int label) pos = s->label_slots[label].pos; for (;;) { switch (s->byte_code.buf[pos]) { - case OP_source_loc: - pos += 9; - continue; + case OP_line_num: case OP_label: pos += 5; continue; @@ -31769,7 +33143,7 @@ static int get_label_pos(JSFunctionDef *s, int label) variables when necessary */ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) { - int pos, pos_next, bc_len, op, len, i, idx, line_num, col_num; + int pos, pos_next, bc_len, op, len, i, idx, line_num; uint8_t *bc_buf; JSAtom var_name; DynBuf bc_out; @@ -31778,7 +33152,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) cc.bc_buf = bc_buf = s->byte_code.buf; cc.bc_len = bc_len = s->byte_code.size; - js_dbuf_init(ctx, &bc_out); + js_dbuf_bytecode_init(ctx, &bc_out); /* first pass for runtime checks (must be done before the variables are created) */ @@ -31820,16 +33194,14 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) } line_num = 0; /* avoid warning */ - col_num = 0; for (pos = 0; pos < bc_len; pos = pos_next) { op = bc_buf[pos]; len = opcode_info[op].size; pos_next = pos + len; switch(op) { - case OP_source_loc: + case OP_line_num: line_num = get_u32(bc_buf + pos + 1); - col_num = get_u32(bc_buf + pos + 5); - s->source_loc_size++; + s->line_number_size++; goto no_change; case OP_eval: /* convert scope index to adjusted variable index */ @@ -31839,15 +33211,16 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) mark_eval_captured_variables(ctx, s, scope); dbuf_putc(&bc_out, op); dbuf_put_u16(&bc_out, call_argc); - dbuf_put_u16(&bc_out, s->scopes[scope].first + 1); + dbuf_put_u16(&bc_out, s->scopes[scope].first - ARG_SCOPE_END); } break; case OP_apply_eval: /* convert scope index to adjusted variable index */ scope = get_u16(bc_buf + pos + 1); mark_eval_captured_variables(ctx, s, scope); dbuf_putc(&bc_out, op); - dbuf_put_u16(&bc_out, s->scopes[scope].first + 1); + dbuf_put_u16(&bc_out, s->scopes[scope].first - ARG_SCOPE_END); break; + case OP_scope_get_var_checkthis: case OP_scope_get_var_undef: case OP_scope_get_var: case OP_scope_put_var: @@ -31890,7 +33263,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) break; case OP_gosub: s->jump_size++; - { + if (OPTIMIZE) { /* remove calls to empty finalizers */ int label; LabelSlot *ls; @@ -31904,22 +33277,43 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) } } goto no_change; + case OP_drop: + if (0) { + /* remove drops before return_undef */ + /* do not perform this optimization in pass2 because + it breaks patterns recognised in resolve_labels */ + int pos1 = pos_next; + int line1 = line_num; + while (code_match(&cc, pos1, OP_drop, -1)) { + if (cc.line_num >= 0) line1 = cc.line_num; + pos1 = cc.pos; + } + if (code_match(&cc, pos1, OP_return_undef, -1)) { + pos_next = pos1; + if (line1 != -1 && line1 != line_num) { + line_num = line1; + s->line_number_size++; + dbuf_putc(&bc_out, OP_line_num); + dbuf_put_u32(&bc_out, line_num); + } + break; + } + } + goto no_change; case OP_insert3: - /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */ - if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) { - dbuf_putc(&bc_out, cc.op); - pos_next = cc.pos; - if (cc.line_num == -1) + if (OPTIMIZE) { + /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */ + if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) { + dbuf_putc(&bc_out, cc.op); + pos_next = cc.pos; + if (cc.line_num != -1 && cc.line_num != line_num) { + line_num = cc.line_num; + s->line_number_size++; + dbuf_putc(&bc_out, OP_line_num); + dbuf_put_u32(&bc_out, line_num); + } break; - if (cc.line_num != line_num || cc.col_num != col_num) { - line_num = cc.line_num; - col_num = cc.col_num; - s->source_loc_size++; - dbuf_putc(&bc_out, OP_source_loc); - dbuf_put_u32(&bc_out, line_num); - dbuf_put_u32(&bc_out, col_num); } - break; } goto no_change; @@ -31933,23 +33327,17 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) case OP_throw: case OP_throw_error: case OP_ret: - { + if (OPTIMIZE) { /* remove dead code */ int line = -1; - int col = -1; dbuf_put(&bc_out, bc_buf + pos, len); - pos = skip_dead_code(s, bc_buf, bc_len, pos + len, - &line, &col); + pos = skip_dead_code(s, bc_buf, bc_len, pos + len, &line); pos_next = pos; - if (line < 0 || pos >= bc_len) - break; - if (line_num != line || col_num != col) { + if (pos < bc_len && line >= 0 && line_num != line) { line_num = line; - col_num = col; - s->source_loc_size++; - dbuf_putc(&bc_out, OP_source_loc); + s->line_number_size++; + dbuf_putc(&bc_out, OP_line_num); dbuf_put_u32(&bc_out, line_num); - dbuf_put_u32(&bc_out, col_num); } break; } @@ -32036,37 +33424,34 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) goto no_change; case OP_dup: - /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */ - /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */ - if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) { - int lab0, lab1, op1, pos1, line1, col1, pos2; - lab0 = lab1 = cc.label; - assert(lab1 >= 0 && lab1 < s->label_count); - op1 = cc.op; - pos1 = cc.pos; - line1 = cc.line_num; - col1 = cc.col_num; - while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) { - lab1 = cc.label; - } - if (code_match(&cc, pos2, op1, -1)) { - s->jump_size++; - update_label(s, lab0, -1); - update_label(s, cc.label, +1); - dbuf_putc(&bc_out, op1); - dbuf_put_u32(&bc_out, cc.label); - pos_next = pos1; - if (line1 == -1) + if (OPTIMIZE) { + /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */ + /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */ + if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) { + int lab0, lab1, op1, pos1, line1, pos2; + lab0 = lab1 = cc.label; + assert(lab1 >= 0 && lab1 < s->label_count); + op1 = cc.op; + pos1 = cc.pos; + line1 = cc.line_num; + while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) { + lab1 = cc.label; + } + if (code_match(&cc, pos2, op1, -1)) { + s->jump_size++; + update_label(s, lab0, -1); + update_label(s, cc.label, +1); + dbuf_putc(&bc_out, op1); + dbuf_put_u32(&bc_out, cc.label); + pos_next = pos1; + if (line1 != -1 && line1 != line_num) { + line_num = line1; + s->line_number_size++; + dbuf_putc(&bc_out, OP_line_num); + dbuf_put_u32(&bc_out, line_num); + } break; - if (line1 != line_num || col1 != col_num) { - line_num = line1; - col_num = col1; - s->source_loc_size++; - dbuf_putc(&bc_out, OP_source_loc); - dbuf_put_u32(&bc_out, line_num); - dbuf_put_u32(&bc_out, col_num); } - break; } } goto no_change; @@ -32118,50 +33503,55 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) return -1; } -/* the pc2line table gives a line number for each PC value */ -static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, - int line_num, int col_num) +/* the pc2line table gives a source position for each PC value */ +static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, uint32_t source_pos) { - if (s->source_loc_slots == NULL) - return; - if (s->source_loc_count >= s->source_loc_size) - return; - if (pc < s->line_number_last_pc) - return; - if (line_num == s->line_number_last) - if (col_num == s->col_number_last) - return; - s->source_loc_slots[s->source_loc_count].pc = pc; - s->source_loc_slots[s->source_loc_count].line_num = line_num; - s->source_loc_slots[s->source_loc_count].col_num = col_num; - s->source_loc_count++; - s->line_number_last_pc = pc; - s->line_number_last = line_num; - s->col_number_last = col_num; + if (s->line_number_slots != NULL + && s->line_number_count < s->line_number_size + && pc >= s->line_number_last_pc + && source_pos != s->line_number_last) { + s->line_number_slots[s->line_number_count].pc = pc; + s->line_number_slots[s->line_number_count].source_pos = source_pos; + s->line_number_count++; + s->line_number_last_pc = pc; + s->line_number_last = source_pos; + } } +/* XXX: could use a more compact storage */ +/* XXX: get_line_col_cached() is slow. For more predictable + performance, line/cols could be stored every N source + bytes. Alternatively, get_line_col_cached() could be issued in + emit_source_pos() so that the deltas are more likely to be + small. */ static void compute_pc2line_info(JSFunctionDef *s) { - if (s->source_loc_slots) { - int last_line_num = s->line_num; - int last_col_num = s->col_num; + if (!s->strip_debug) { + int last_line_num, last_col_num; uint32_t last_pc = 0; - int i; - + int i, line_num, col_num; + const uint8_t *buf_start = s->get_line_col_cache->buf_start; js_dbuf_init(s->ctx, &s->pc2line); - for (i = 0; i < s->source_loc_count; i++) { - uint32_t pc = s->source_loc_slots[i].pc; - int line_num = s->source_loc_slots[i].line_num; - int col_num = s->source_loc_slots[i].col_num; + + last_line_num = get_line_col_cached(s->get_line_col_cache, + &last_col_num, + buf_start + s->source_pos); + dbuf_put_leb128(&s->pc2line, last_line_num); /* line number minus 1 */ + dbuf_put_leb128(&s->pc2line, last_col_num); /* column number minus 1 */ + + for (i = 0; i < s->line_number_count; i++) { + uint32_t pc = s->line_number_slots[i].pc; + uint32_t source_pos = s->line_number_slots[i].source_pos; int diff_pc, diff_line, diff_col; - if (line_num < 0) + if (source_pos == -1) continue; - diff_pc = pc - last_pc; if (diff_pc < 0) continue; + line_num = get_line_col_cached(s->get_line_col_cache, &col_num, + buf_start + source_pos); diff_line = line_num - last_line_num; diff_col = col_num - last_col_num; if (diff_line == 0 && diff_col == 0) @@ -32179,7 +33569,7 @@ static void compute_pc2line_info(JSFunctionDef *s) dbuf_put_sleb128(&s->pc2line, diff_line); } dbuf_put_sleb128(&s->pc2line, diff_col); - + last_pc = pc; last_line_num = line_num; last_col_num = col_num; @@ -32200,45 +33590,49 @@ static RelocEntry *add_reloc(JSContext *ctx, LabelSlot *ls, uint32_t addr, int s return re; } -static bool code_has_label(CodeContext *s, int pos, int label) +static BOOL code_has_label(CodeContext *s, int pos, int label) { while (pos < s->bc_len) { int op = s->bc_buf[pos]; - if (op == OP_source_loc) { - pos += 9; + if (op == OP_line_num) { + pos += 5; continue; } if (op == OP_label) { int lab = get_u32(s->bc_buf + pos + 1); if (lab == label) - return true; + return TRUE; pos += 5; continue; } if (op == OP_goto) { int lab = get_u32(s->bc_buf + pos + 1); if (lab == label) - return true; + return TRUE; } break; } - return false; + return FALSE; } /* return the target label, following the OP_goto jumps the first opcode at destination is stored in *pop */ -static int find_jump_target(JSFunctionDef *s, int label, int *pop) +static int find_jump_target(JSFunctionDef *s, int label0, int *pop, int *pline) { - int i, pos, op; + int i, pos, op, label; + label = label0; update_label(s, label, -1); for (i = 0; i < 10; i++) { assert(label >= 0 && label < s->label_count); pos = s->label_slots[label].pos2; for (;;) { switch(op = s->byte_code.buf[pos]) { - case OP_source_loc: + case OP_line_num: + if (pline) + *pline = get_u32(s->byte_code.buf + pos + 1); + /* fall thru */ case OP_label: pos += opcode_info[op].size; continue; @@ -32259,6 +33653,19 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop) } } /* cycle detected, could issue a warning */ + /* XXX: the combination of find_jump_target() and skip_dead_code() + seems incorrect with cyclic labels. See for exemple: + + for (;;) { + l:break l; + l:break l; + l:break l; + l:break l; + } + + Avoiding changing the target is just a workaround and might not + suffice to completely fix the problem. */ + label = label0; done: *pop = op; update_label(s, label, +1); @@ -32267,6 +33674,7 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop) static void push_short_int(DynBuf *bc_out, int val) { +#if SHORT_OPCODES if (val >= -1 && val <= 7) { dbuf_putc(bc_out, OP_push_0 + val); return; @@ -32281,12 +33689,14 @@ static void push_short_int(DynBuf *bc_out, int val) dbuf_put_u16(bc_out, val); return; } +#endif dbuf_putc(bc_out, OP_push_i32); dbuf_put_u32(bc_out, val); } static void put_short_code(DynBuf *bc_out, int op, int idx) { +#if SHORT_OPCODES if (idx < 4) { switch (op) { case OP_get_loc: @@ -32337,6 +33747,7 @@ static void put_short_code(DynBuf *bc_out, int op, int idx) return; } } +#endif dbuf_putc(bc_out, op); dbuf_put_u16(bc_out, idx); } @@ -32344,36 +33755,38 @@ static void put_short_code(DynBuf *bc_out, int op, int idx) /* peephole optimizations and resolve goto/labels */ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) { - int pos, pos_next, bc_len, op, op1, len, i, line_num, col_num, patch_offsets; + int pos, pos_next, bc_len, op, op1, len, i, line_num; const uint8_t *bc_buf; DynBuf bc_out; LabelSlot *label_slots, *ls; RelocEntry *re, *re_next; CodeContext cc; int label; +#if SHORT_OPCODES JumpSlot *jp; +#endif label_slots = s->label_slots; - line_num = s->line_num; - col_num = s->col_num; + line_num = s->source_pos; cc.bc_buf = bc_buf = s->byte_code.buf; cc.bc_len = bc_len = s->byte_code.size; - js_dbuf_init(ctx, &bc_out); + js_dbuf_bytecode_init(ctx, &bc_out); +#if SHORT_OPCODES if (s->jump_size) { s->jump_slots = js_mallocz(s->ctx, sizeof(*s->jump_slots) * s->jump_size); if (s->jump_slots == NULL) return -1; } - - if (s->source_loc_size) { - s->source_loc_slots = js_mallocz(s->ctx, sizeof(*s->source_loc_slots) * s->source_loc_size); - if (s->source_loc_slots == NULL) +#endif + /* XXX: Should skip this phase if not generating SHORT_OPCODES */ + if (s->line_number_size && !s->strip_debug) { + s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size); + if (s->line_number_slots == NULL) return -1; - s->line_number_last = s->line_num; - s->col_number_last = s->col_num; + s->line_number_last = s->source_pos; s->line_number_last_pc = 0; } @@ -32408,7 +33821,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } /* initialize the 'arguments' variable if needed */ if (s->arguments_var_idx >= 0) { - if (s->is_strict_mode || !s->has_simple_parameter_list) { + if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) { dbuf_putc(&bc_out, OP_special_object); dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS); } else { @@ -32443,12 +33856,11 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) len = opcode_info[op].size; pos_next = pos + len; switch(op) { - case OP_source_loc: + case OP_line_num: /* line number info (for debug). We put it in a separate compressed table to reduce memory usage and get better performance */ line_num = get_u32(bc_buf + pos + 1); - col_num = get_u32(bc_buf + pos + 5); break; case OP_label: @@ -32489,14 +33901,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) argc = get_u16(bc_buf + pos + 1); if (code_match(&cc, pos_next, OP_return, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op + 1, argc); - pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, - &line_num, &col_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, &line_num); break; } - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op, argc); break; } @@ -32507,16 +33917,16 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) case OP_return_async: case OP_throw: case OP_throw_error: - pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, - &line_num, &col_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num); goto no_change; case OP_goto: label = get_u32(bc_buf + pos + 1); has_goto: - { + if (OPTIMIZE) { + int line1 = -1; /* Use custom matcher because multiple labels can follow */ - label = find_jump_target(s, label, &op1); + label = find_jump_target(s, label, &op1, &line1); if (code_has_label(&cc, pos_next, label)) { /* jump to next instruction: remove jump */ update_label(s, label, -1); @@ -32525,11 +33935,11 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) if (op1 == OP_return || op1 == OP_return_undef || op1 == OP_throw) { /* jump to return/throw: remove jump, append return/throw */ /* updating the line number obfuscates assembly listing */ + //if (line1 != -1) line_num = line1; update_label(s, label, -1); - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, op1); - pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, - &line_num, &col_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num); break; } /* XXX: should duplicate single instructions followed by goto or return */ @@ -32543,6 +33953,14 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) case OP_gosub: label = get_u32(bc_buf + pos + 1); + if (0 && OPTIMIZE) { + label = find_jump_target(s, label, &op1, NULL); + if (op1 == OP_ret) { + update_label(s, label, -1); + /* empty finally clause: remove gosub */ + break; + } + } goto has_label; case OP_catch: @@ -32552,35 +33970,35 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) case OP_if_true: case OP_if_false: label = get_u32(bc_buf + pos + 1); - label = find_jump_target(s, label, &op1); - /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */ - if (code_has_label(&cc, pos_next, label)) { - update_label(s, label, -1); - dbuf_putc(&bc_out, OP_drop); - break; - } - /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */ - if (code_match(&cc, pos_next, OP_goto, -1)) { - int pos1 = cc.pos; - int line1 = cc.line_num; - int col1 = cc.col_num; - if (code_has_label(&cc, pos1, label)) { - if (line1 >= 0) line_num = line1; - if (col1 >= 0) col_num = col1; - pos_next = pos1; + if (OPTIMIZE) { + label = find_jump_target(s, label, &op1, NULL); + /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */ + if (code_has_label(&cc, pos_next, label)) { update_label(s, label, -1); - label = cc.label; - op ^= OP_if_true ^ OP_if_false; + dbuf_putc(&bc_out, OP_drop); + break; + } + /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */ + if (code_match(&cc, pos_next, OP_goto, -1)) { + int pos1 = cc.pos; + int line1 = cc.line_num; + if (code_has_label(&cc, pos1, label)) { + if (line1 != -1) line_num = line1; + pos_next = pos1; + update_label(s, label, -1); + label = cc.label; + op ^= OP_if_true ^ OP_if_false; + } } } has_label: - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); if (op == OP_goto) { - pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, - &line_num, &col_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num); } assert(label >= 0 && label < s->label_count); ls = &label_slots[label]; +#if SHORT_OPCODES jp = &s->jump_slots[s->jump_count++]; jp->op = op; jp->size = 4; @@ -32624,6 +34042,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) break; } } +#endif dbuf_putc(&bc_out, op); dbuf_put_u32(&bc_out, ls->addr - bc_out.size); if (ls->addr == -1) { @@ -32637,7 +34056,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) case OP_with_delete_var: case OP_with_make_ref: case OP_with_get_ref: - case OP_with_get_ref_undef: { JSAtom atom; int is_with; @@ -32645,15 +34063,19 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) atom = get_u32(bc_buf + pos + 1); label = get_u32(bc_buf + pos + 5); is_with = bc_buf[pos + 9]; - label = find_jump_target(s, label, &op1); + if (OPTIMIZE) { + label = find_jump_target(s, label, &op1, NULL); + } assert(label >= 0 && label < s->label_count); ls = &label_slots[label]; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); +#if SHORT_OPCODES jp = &s->jump_slots[s->jump_count++]; jp->op = op; jp->size = 4; jp->pos = bc_out.size + 5; jp->label = label; +#endif dbuf_putc(&bc_out, op); dbuf_put_u32(&bc_out, atom); dbuf_put_u32(&bc_out, ls->addr - bc_out.size); @@ -32667,108 +34089,110 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) break; case OP_drop: - /* remove useless drops before return */ - if (code_match(&cc, pos_next, OP_return_undef, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - break; + if (OPTIMIZE) { + /* remove useless drops before return */ + if (code_match(&cc, pos_next, OP_return_undef, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + break; + } } goto no_change; case OP_null: - /* transform null strict_eq into is_null */ - if (code_match(&cc, pos_next, OP_strict_eq, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_is_null); - pos_next = cc.pos; - break; - } - /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */ - if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_is_null); - pos_next = cc.pos; - label = cc.label; - op = cc.op ^ OP_if_false ^ OP_if_true; - goto has_label; +#if SHORT_OPCODES + if (OPTIMIZE) { + /* transform null strict_eq into is_null */ + if (code_match(&cc, pos_next, OP_strict_eq, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_is_null); + pos_next = cc.pos; + break; + } + /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */ + if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_is_null); + pos_next = cc.pos; + label = cc.label; + op = cc.op ^ OP_if_false ^ OP_if_true; + goto has_label; + } } +#endif /* fall thru */ case OP_push_false: case OP_push_true: - val = (op == OP_push_true); - if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { - has_constant_test: - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - if (val == cc.op - OP_if_false) { - /* transform null if_false(l1) -> goto l1 */ - /* transform false if_false(l1) -> goto l1 */ - /* transform true if_true(l1) -> goto l1 */ - pos_next = cc.pos; - op = OP_goto; - label = cc.label; - goto has_goto; - } else { - /* transform null if_true(l1) -> nop */ - /* transform false if_true(l1) -> nop */ - /* transform true if_false(l1) -> nop */ - pos_next = cc.pos; - update_label(s, cc.label, -1); - break; + if (OPTIMIZE) { + val = (op == OP_push_true); + if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { + has_constant_test: + if (cc.line_num >= 0) line_num = cc.line_num; + if (val == cc.op - OP_if_false) { + /* transform null if_false(l1) -> goto l1 */ + /* transform false if_false(l1) -> goto l1 */ + /* transform true if_true(l1) -> goto l1 */ + pos_next = cc.pos; + op = OP_goto; + label = cc.label; + goto has_goto; + } else { + /* transform null if_true(l1) -> nop */ + /* transform false if_true(l1) -> nop */ + /* transform true if_false(l1) -> nop */ + pos_next = cc.pos; + update_label(s, cc.label, -1); + break; + } } } goto no_change; case OP_push_i32: - /* transform i32(val) neg -> i32(-val) */ - val = get_i32(bc_buf + pos + 1); - if ((val != INT32_MIN && val != 0) - && code_match(&cc, pos_next, OP_neg, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - if (code_match(&cc, cc.pos, OP_drop, -1)) { + if (OPTIMIZE) { + /* transform i32(val) neg -> i32(-val) */ + val = get_i32(bc_buf + pos + 1); + if ((val != INT32_MIN && val != 0) + && code_match(&cc, pos_next, OP_neg, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - } else { - add_pc2line_info(s, bc_out.size, line_num, col_num); - push_short_int(&bc_out, -val); + if (code_match(&cc, cc.pos, OP_drop, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + } else { + add_pc2line_info(s, bc_out.size, line_num); + push_short_int(&bc_out, -val); + } + pos_next = cc.pos; + break; } - pos_next = cc.pos; - break; - } - /* remove push/drop pairs generated by the parser */ - if (code_match(&cc, pos_next, OP_drop, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - pos_next = cc.pos; + /* remove push/drop pairs generated by the parser */ + if (code_match(&cc, pos_next, OP_drop, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + pos_next = cc.pos; + break; + } + /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */ + if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { + val = (val != 0); + goto has_constant_test; + } + add_pc2line_info(s, bc_out.size, line_num); + push_short_int(&bc_out, val); break; } - /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */ - if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { - val = (val != 0); - goto has_constant_test; - } - add_pc2line_info(s, bc_out.size, line_num, col_num); - push_short_int(&bc_out, val); - break; + goto no_change; case OP_push_bigint_i32: - { + if (OPTIMIZE) { /* transform i32(val) neg -> i32(-val) */ val = get_i32(bc_buf + pos + 1); if (val != INT32_MIN && code_match(&cc, pos_next, OP_neg, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; if (code_match(&cc, cc.pos, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; } else { - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_push_bigint_i32); dbuf_put_u32(&bc_out, -val); } @@ -32778,12 +34202,13 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } goto no_change; +#if SHORT_OPCODES case OP_push_const: case OP_fclosure: - { + if (OPTIMIZE) { int idx = get_u32(bc_buf + pos + 1); if (idx < 256) { - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_push_const8 + op - OP_push_const); dbuf_putc(&bc_out, idx); break; @@ -32792,120 +34217,120 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) goto no_change; case OP_get_field: - { + if (OPTIMIZE) { JSAtom atom = get_u32(bc_buf + pos + 1); if (atom == JS_ATOM_length) { JS_FreeAtom(ctx, atom); - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_get_length); break; } } goto no_change; - +#endif case OP_push_atom_value: - { + if (OPTIMIZE) { JSAtom atom = get_u32(bc_buf + pos + 1); /* remove push/drop pairs generated by the parser */ if (code_match(&cc, pos_next, OP_drop, -1)) { JS_FreeAtom(ctx, atom); if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; pos_next = cc.pos; break; } +#if SHORT_OPCODES if (atom == JS_ATOM_empty_string) { JS_FreeAtom(ctx, atom); - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_push_empty_string); break; } +#endif } goto no_change; case OP_to_propkey: - case OP_to_propkey2: - /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */ - if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1) - || code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1) - || code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) { - break; + if (OPTIMIZE) { + /* remove redundant to_propkey opcodes when storing simple data */ + if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1) + || code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1) + || code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) { + break; + } } goto no_change; case OP_undefined: - /* remove push/drop pairs generated by the parser */ - if (code_match(&cc, pos_next, OP_drop, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - pos_next = cc.pos; - break; - } - /* transform undefined return -> return_undefined */ - if (code_match(&cc, pos_next, OP_return, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_return_undef); - pos_next = cc.pos; - break; - } - /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */ - if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { - val = 0; - goto has_constant_test; - } - /* transform undefined strict_eq -> is_undefined */ - if (code_match(&cc, pos_next, OP_strict_eq, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_is_undefined); - pos_next = cc.pos; - break; - } - /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */ - if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_is_undefined); - pos_next = cc.pos; - label = cc.label; - op = cc.op ^ OP_if_false ^ OP_if_true; - goto has_label; + if (OPTIMIZE) { + /* remove push/drop pairs generated by the parser */ + if (code_match(&cc, pos_next, OP_drop, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + pos_next = cc.pos; + break; + } + /* transform undefined return -> return_undefined */ + if (code_match(&cc, pos_next, OP_return, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_return_undef); + pos_next = cc.pos; + break; + } + /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */ + if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) { + val = 0; + goto has_constant_test; + } +#if SHORT_OPCODES + /* transform undefined strict_eq -> is_undefined */ + if (code_match(&cc, pos_next, OP_strict_eq, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_is_undefined); + pos_next = cc.pos; + break; + } + /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */ + if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_is_undefined); + pos_next = cc.pos; + label = cc.label; + op = cc.op ^ OP_if_false ^ OP_if_true; + goto has_label; + } +#endif } goto no_change; case OP_insert2: - /* Transformation: - insert2 put_field(a) drop -> put_field(a) - insert2 put_var_strict(a) drop -> put_var_strict(a) - */ - if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, cc.op); - dbuf_put_u32(&bc_out, cc.atom); - pos_next = cc.pos; - break; + if (OPTIMIZE) { + /* Transformation: + insert2 put_field(a) drop -> put_field(a) + */ + if (code_match(&cc, pos_next, OP_put_field, OP_drop, -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, OP_put_field); + dbuf_put_u32(&bc_out, cc.atom); + pos_next = cc.pos; + break; + } } goto no_change; case OP_dup: - { + if (OPTIMIZE) { /* Transformation: dup put_x(n) drop -> put_x(n) */ int op1, line2 = -1; /* Transformation: dup put_x(n) -> set_x(n) */ if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; op1 = cc.op + 1; /* put_x -> set_x */ pos_next = cc.pos; if (code_match(&cc, cc.pos, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; op1 -= 1; /* set_x drop -> put_x */ pos_next = cc.pos; if (code_match(&cc, cc.pos, op1 - 1, cc.idx, -1)) { @@ -32914,7 +34339,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) pos_next = cc.pos; } } - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op1, cc.idx); if (line2 >= 0) line_num = line2; break; @@ -32922,18 +34347,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } goto no_change; - case OP_swap: - // transformation: swap swap -> nothing! - if (code_match(&cc, pos_next, OP_swap, -1, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - pos_next = cc.pos; - break; - } - goto no_change; - case OP_get_loc: - { + if (OPTIMIZE) { /* transformation: get_loc(n) post_dec put_loc(n) drop -> dec_loc(n) get_loc(n) post_inc put_loc(n) drop -> inc_loc(n) @@ -32947,8 +34362,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) if (code_match(&cc, pos_next, M2(OP_post_dec, OP_post_inc), OP_put_loc, idx, OP_drop, -1) || code_match(&cc, pos_next, M2(OP_dec, OP_inc), OP_dup, OP_put_loc, idx, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, (cc.op == OP_inc || cc.op == OP_post_inc) ? OP_inc_loc : OP_dec_loc); dbuf_putc(&bc_out, idx); pos_next = cc.pos; @@ -32959,12 +34373,14 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) */ if (code_match(&cc, pos_next, OP_push_atom_value, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); +#if SHORT_OPCODES if (cc.atom == JS_ATOM_empty_string) { JS_FreeAtom(ctx, cc.atom); dbuf_putc(&bc_out, OP_push_empty_string); - } else { + } else +#endif + { dbuf_putc(&bc_out, OP_push_atom_value); dbuf_put_u32(&bc_out, cc.atom); } @@ -32978,8 +34394,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) */ if (code_match(&cc, pos_next, OP_push_i32, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); push_short_int(&bc_out, cc.label); dbuf_putc(&bc_out, OP_add_loc); dbuf_putc(&bc_out, idx); @@ -32993,97 +34408,86 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) */ if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, cc.op, cc.idx); dbuf_putc(&bc_out, OP_add_loc); dbuf_putc(&bc_out, idx); pos_next = cc.pos; break; } - /* transformation: get_loc(0) get_loc(1) -> get_loc0_loc1 */ - if (idx == 0 && code_match(&cc, pos_next, OP_get_loc, 1, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_get_loc0_loc1); - pos_next = cc.pos; - break; - } - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op, idx); + break; } - break; + goto no_change; +#if SHORT_OPCODES case OP_get_arg: case OP_get_var_ref: - { + if (OPTIMIZE) { int idx; idx = get_u16(bc_buf + pos + 1); - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op, idx); + break; } - break; + goto no_change; +#endif case OP_put_loc: case OP_put_arg: case OP_put_var_ref: - { + if (OPTIMIZE) { /* transformation: put_x(n) get_x(n) -> set_x(n) */ int idx; idx = get_u16(bc_buf + pos + 1); if (code_match(&cc, pos_next, op - 1, idx, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op + 1, idx); pos_next = cc.pos; break; } - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); put_short_code(&bc_out, op, idx); + break; } - break; + goto no_change; case OP_post_inc: case OP_post_dec: - { + if (OPTIMIZE) { /* transformation: post_inc put_x drop -> inc put_x post_inc perm3 put_field drop -> inc put_field - post_inc perm3 put_var_strict drop -> inc put_var_strict post_inc perm4 put_array_el drop -> inc put_array_el */ int op1, idx; if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; op1 = cc.op; idx = cc.idx; pos_next = cc.pos; if (code_match(&cc, cc.pos, op1 - 1, idx, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; op1 += 1; /* put_x(n) get_x(n) -> set_x(n) */ pos_next = cc.pos; } - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec)); put_short_code(&bc_out, op1, idx); break; } - if (code_match(&cc, pos_next, OP_perm3, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) { + if (code_match(&cc, pos_next, OP_perm3, OP_put_field, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec)); - dbuf_putc(&bc_out, cc.op); + dbuf_putc(&bc_out, OP_put_field); dbuf_put_u32(&bc_out, cc.atom); pos_next = cc.pos; break; } if (code_match(&cc, pos_next, OP_perm4, OP_put_array_el, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec)); dbuf_putc(&bc_out, OP_put_array_el); pos_next = cc.pos; @@ -33092,61 +34496,51 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } goto no_change; +#if SHORT_OPCODES case OP_typeof: - /* simplify typeof tests */ - if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq; - int op2 = -1; - switch (cc.atom) { - case JS_ATOM_undefined: - op2 = OP_typeof_is_undefined; - break; - case JS_ATOM_function: - op2 = OP_typeof_is_function; - break; - } - if (op2 >= 0) { - /* transform typeof(s) == "" into is_ */ - if (op1 == OP_strict_eq) { - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, op2); - JS_FreeAtom(ctx, cc.atom); - pos_next = cc.pos; + if (OPTIMIZE) { + /* simplify typeof tests */ + if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) { + if (cc.line_num >= 0) line_num = cc.line_num; + int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq; + int op2 = -1; + switch (cc.atom) { + case JS_ATOM_undefined: + op2 = OP_typeof_is_undefined; + break; + case JS_ATOM_function: + op2 = OP_typeof_is_function; break; } - if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) { - /* transform typeof(s) != "" if_false into is_ if_true */ - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, op2); - JS_FreeAtom(ctx, cc.atom); - pos_next = cc.pos; - label = cc.label; - op = OP_if_true; - goto has_label; + if (op2 >= 0) { + /* transform typeof(s) == "" into is_ */ + if (op1 == OP_strict_eq) { + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, op2); + JS_FreeAtom(ctx, cc.atom); + pos_next = cc.pos; + break; + } + if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) { + /* transform typeof(s) != "" if_false into is_ if_true */ + if (cc.line_num >= 0) line_num = cc.line_num; + add_pc2line_info(s, bc_out.size, line_num); + dbuf_putc(&bc_out, op2); + JS_FreeAtom(ctx, cc.atom); + pos_next = cc.pos; + label = cc.label; + op = OP_if_true; + goto has_label; + } } } } goto no_change; - - case OP_object: - if (code_match(&cc, pos_next, OP_null, OP_set_proto, -1)) { - if (cc.line_num >= 0) line_num = cc.line_num; - if (cc.col_num >= 0) col_num = cc.col_num; - add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, OP_special_object); - dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_NULL_PROTO); - pos_next = cc.pos; - break; - } - goto no_change; +#endif default: no_change: - add_pc2line_info(s, bc_out.size, line_num, col_num); + add_pc2line_info(s, bc_out.size, line_num); dbuf_put(&bc_out, bc_buf + pos, len); break; } @@ -33156,94 +34550,95 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) for(i = 0; i < s->label_count; i++) { assert(label_slots[i].first_reloc == NULL); } - - /* more jump optimizations */ - patch_offsets = 0; - for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) { - LabelSlot *ls; - JumpSlot *jp1; - int j, pos, diff, delta; - - delta = 3; - switch (op = jp->op) { - case OP_goto16: - delta = 1; - /* fall thru */ - case OP_if_false: - case OP_if_true: - case OP_goto: - pos = jp->pos; - diff = s->label_slots[jp->label].addr - pos; - if (diff >= -128 && diff <= 127 + delta) { - //put_u8(bc_out.buf + pos, diff); - jp->size = 1; - if (op == OP_goto16) { - bc_out.buf[pos - 1] = jp->op = OP_goto8; - } else { - bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false); - } - goto shrink; - } else - if (diff == (int16_t)diff && op == OP_goto) { - //put_u16(bc_out.buf + pos, diff); - jp->size = 2; - delta = 2; - bc_out.buf[pos - 1] = jp->op = OP_goto16; - shrink: - /* XXX: should reduce complexity, using 2 finger copy scheme */ - memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta, - bc_out.size - pos - jp->size - delta); - bc_out.size -= delta; - patch_offsets++; - for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) { - if (ls->addr > pos) - ls->addr -= delta; - } - for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) { - if (jp1->pos > pos) - jp1->pos -= delta; - } - for (j = 0; j < s->source_loc_count; j++) { - if (s->source_loc_slots[j].pc > pos) - s->source_loc_slots[j].pc -= delta; +#if SHORT_OPCODES + if (OPTIMIZE) { + /* more jump optimizations */ + int patch_offsets = 0; + for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) { + LabelSlot *ls; + JumpSlot *jp1; + int j, pos, diff, delta; + + delta = 3; + switch (op = jp->op) { + case OP_goto16: + delta = 1; + /* fall thru */ + case OP_if_false: + case OP_if_true: + case OP_goto: + pos = jp->pos; + diff = s->label_slots[jp->label].addr - pos; + if (diff >= -128 && diff <= 127 + delta) { + //put_u8(bc_out.buf + pos, diff); + jp->size = 1; + if (op == OP_goto16) { + bc_out.buf[pos - 1] = jp->op = OP_goto8; + } else { + bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false); + } + goto shrink; + } else + if (diff == (int16_t)diff && op == OP_goto) { + //put_u16(bc_out.buf + pos, diff); + jp->size = 2; + delta = 2; + bc_out.buf[pos - 1] = jp->op = OP_goto16; + shrink: + /* XXX: should reduce complexity, using 2 finger copy scheme */ + memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta, + bc_out.size - pos - jp->size - delta); + bc_out.size -= delta; + patch_offsets++; + for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) { + if (ls->addr > pos) + ls->addr -= delta; + } + for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) { + if (jp1->pos > pos) + jp1->pos -= delta; + } + for (j = 0; j < s->line_number_count; j++) { + if (s->line_number_slots[j].pc > pos) + s->line_number_slots[j].pc -= delta; + } + continue; } - continue; + break; } - break; } - } - - if (patch_offsets) { - JumpSlot *jp1; - int j; - for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) { - int diff1 = s->label_slots[jp1->label].addr - jp1->pos; - switch (jp1->size) { - case 1: - put_u8(bc_out.buf + jp1->pos, diff1); - break; - case 2: - put_u16(bc_out.buf + jp1->pos, diff1); - break; - case 4: - put_u32(bc_out.buf + jp1->pos, diff1); - break; + if (patch_offsets) { + JumpSlot *jp1; + int j; + for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) { + int diff1 = s->label_slots[jp1->label].addr - jp1->pos; + switch (jp1->size) { + case 1: + put_u8(bc_out.buf + jp1->pos, diff1); + break; + case 2: + put_u16(bc_out.buf + jp1->pos, diff1); + break; + case 4: + put_u32(bc_out.buf + jp1->pos, diff1); + break; + } } } } - js_free(ctx, s->jump_slots); s->jump_slots = NULL; +#endif js_free(ctx, s->label_slots); s->label_slots = NULL; /* XXX: should delay until copying to runtime bytecode function */ compute_pc2line_info(s); - js_free(ctx, s->source_loc_slots); - s->source_loc_slots = NULL; + js_free(ctx, s->line_number_slots); + s->line_number_slots = NULL; /* set the new byte code */ dbuf_free(&s->byte_code); s->byte_code = bc_out; - s->use_short_opcodes = true; + s->use_short_opcodes = TRUE; if (dbuf_error(&s->byte_code)) { JS_ThrowOutOfMemory(ctx); return -1; @@ -33328,7 +34723,8 @@ static __exception int compute_stack_size(JSContext *ctx, for(i = 0; i < s->bc_len; i++) s->stack_level_tab[i] = 0xffff; s->pc_stack = NULL; - s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) * s->bc_len); + s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) * + s->bc_len); if (!s->catch_pos_tab) goto fail; @@ -33350,9 +34746,8 @@ static __exception int compute_stack_size(JSContext *ctx, goto fail; } oi = &short_opcode_info(op); -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_STACK - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_STACK)) - printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos); +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64) + printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos); #endif pos_next = pos + oi->size; if (pos_next > s->bc_len) { @@ -33363,8 +34758,12 @@ static __exception int compute_stack_size(JSContext *ctx, /* call pops a variable number of arguments */ if (oi->fmt == OP_FMT_npop || oi->fmt == OP_FMT_npop_u16) { n_pop += get_u16(bc_buf + pos + 1); - } else if (oi->fmt == OP_FMT_npopx) { - n_pop += op - OP_call0; + } else { +#if SHORT_OPCODES + if (oi->fmt == OP_FMT_npopx) { + n_pop += op - OP_call0; + } +#endif } if (stack_len < n_pop) { @@ -33393,6 +34792,7 @@ static __exception int compute_stack_size(JSContext *ctx, diff = get_u32(bc_buf + pos + 1); pos_next = pos + 1 + diff; break; +#if SHORT_OPCODES case OP_goto16: diff = (int16_t)get_u16(bc_buf + pos + 1); pos_next = pos + 1 + diff; @@ -33407,6 +34807,7 @@ static __exception int compute_stack_size(JSContext *ctx, if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos)) goto fail; break; +#endif case OP_if_true: case OP_if_false: diff = get_u32(bc_buf + pos + 1); @@ -33426,7 +34827,6 @@ static __exception int compute_stack_size(JSContext *ctx, break; case OP_with_make_ref: case OP_with_get_ref: - case OP_with_get_ref_undef: diff = get_u32(bc_buf + pos + 5); if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2, catch_pos)) goto fail; @@ -33518,8 +34918,8 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd) for(i = 0; i < fd->global_var_count; i++) { hf = &fd->global_vars[i]; - if (add_closure_var(ctx, fd, true, false, i, hf->var_name, hf->is_const, - hf->is_lexical, JS_VAR_NORMAL) < 0) + if (add_closure_var(ctx, fd, TRUE, FALSE, i, hf->var_name, hf->is_const, + hf->is_lexical, FALSE) < 0) return -1; } @@ -33529,7 +34929,6 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd) if (me->export_type == JS_EXPORT_TYPE_LOCAL) { idx = find_closure_var(ctx, fd, me->local_name); if (idx < 0) { - // XXX: add_module_variables() should take JSParseState *s and use js_parse_error_atom JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist", me->local_name); return -1; @@ -33582,10 +34981,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) are used to compile the eval and they must be ordered by scope, so it is necessary to create the closure variables before any other variable lookup is done. */ -#ifndef QJS_DISABLE_PARSER if (fd->has_eval_call) add_eval_variables(ctx, fd); -#endif // QJS_DISABLE_PARSER /* add the module global variables in the closure */ if (fd->module) { @@ -33608,14 +35005,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) fd->cpool[cpool_idx] = func_obj; } -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PASS1 - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PASS1)) { +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4) + if (!fd->strip_debug) { printf("pass 1\n"); dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size, fd->args, fd->arg_count, fd->vars, fd->var_count, fd->closure_var, fd->closure_var_count, - fd->cpool, fd->cpool_count, fd->source, fd->line_num, - fd->label_slots, NULL, 0); + fd->cpool, fd->cpool_count, fd->source, + fd->label_slots, NULL); printf("\n"); } #endif @@ -33623,14 +35020,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) if (resolve_variables(ctx, fd)) goto fail; -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_PASS2 - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_PASS2)) { +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2) + if (!fd->strip_debug) { printf("pass 2\n"); dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size, fd->args, fd->arg_count, fd->vars, fd->var_count, fd->closure_var, fd->closure_var_count, - fd->cpool, fd->cpool_count, fd->source, fd->line_num, - fd->label_slots, NULL, 0); + fd->cpool, fd->cpool_count, fd->source, + fd->label_slots, NULL); printf("\n"); } #endif @@ -33641,11 +35038,17 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) if (compute_stack_size(ctx, fd, &stack_size) < 0) goto fail; - function_size = sizeof(*b); + if (fd->strip_debug) { + function_size = offsetof(JSFunctionBytecode, debug); + } else { + function_size = sizeof(*b); + } cpool_offset = function_size; function_size += fd->cpool_count * sizeof(*fd->cpool); vardefs_offset = function_size; - function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs); + if (!fd->strip_debug || fd->has_eval_call) { + function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs); + } closure_var_offset = function_size; function_size += fd->closure_var_count * sizeof(*fd->closure_var); byte_code_offset = function_size; @@ -33664,17 +35067,29 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->func_name = fd->func_name; if (fd->arg_count + fd->var_count > 0) { - b->vardefs = (void *)((uint8_t*)b + vardefs_offset); - if (fd->arg_count > 0) - memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0])); - if (fd->var_count > 0) - memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0])); + if (fd->strip_debug && !fd->has_eval_call) { + /* Strip variable definitions not needed at runtime */ + int i; + for(i = 0; i < fd->var_count; i++) { + JS_FreeAtom(ctx, fd->vars[i].var_name); + } + for(i = 0; i < fd->arg_count; i++) { + JS_FreeAtom(ctx, fd->args[i].var_name); + } + for(i = 0; i < fd->closure_var_count; i++) { + JS_FreeAtom(ctx, fd->closure_var[i].var_name); + fd->closure_var[i].var_name = JS_ATOM_NULL; + } + } else { + b->vardefs = (void *)((uint8_t*)b + vardefs_offset); + memcpy_no_ub(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0])); + memcpy_no_ub(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0])); + } b->var_count = fd->var_count; b->arg_count = fd->arg_count; b->defined_arg_count = fd->defined_arg_count; js_free(ctx, fd->args); js_free(ctx, fd->vars); - js_free(ctx, fd->vars_htab); } b->cpool_count = fd->cpool_count; if (b->cpool_count) { @@ -33686,20 +35101,26 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->stack_size = stack_size; - /* XXX: source and pc2line info should be packed at the end of the - JSFunctionBytecode structure, avoiding allocation overhead - */ - b->filename = fd->filename; - b->line_num = fd->line_num; - b->col_num = fd->col_num; - - b->pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size); - if (!b->pc2line_buf) - b->pc2line_buf = fd->pc2line.buf; - b->pc2line_len = fd->pc2line.size; - b->source = fd->source; - b->source_len = fd->source_len; - + if (fd->strip_debug) { + JS_FreeAtom(ctx, fd->filename); + dbuf_free(&fd->pc2line); // probably useless + } else { + /* XXX: source and pc2line info should be packed at the end of the + JSFunctionBytecode structure, avoiding allocation overhead + */ + b->has_debug = 1; + b->debug.filename = fd->filename; + + //DynBuf pc2line; + //compute_pc2line_info(fd, &pc2line); + //js_free(ctx, fd->line_number_slots) + b->debug.pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size); + if (!b->debug.pc2line_buf) + b->debug.pc2line_buf = fd->pc2line.buf; + b->debug.pc2line_len = fd->pc2line.size; + b->debug.source = fd->source; + b->debug.source_len = fd->source_len; + } if (fd->scopes != fd->def_scope_array) js_free(ctx, fd->scopes); @@ -33713,7 +35134,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->has_prototype = fd->has_prototype; b->has_simple_parameter_list = fd->has_simple_parameter_list; - b->is_strict_mode = fd->is_strict_mode; + b->js_mode = fd->js_mode; b->is_derived_class_constructor = fd->is_derived_class_constructor; b->func_kind = fd->func_kind; b->need_home_object = (fd->home_object_var_idx >= 0 || @@ -33722,14 +35143,16 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->super_call_allowed = fd->super_call_allowed; b->super_allowed = fd->super_allowed; b->arguments_allowed = fd->arguments_allowed; - b->backtrace_barrier = fd->backtrace_barrier; + b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT || + fd->eval_type == JS_EVAL_TYPE_INDIRECT); b->realm = JS_DupContext(ctx); add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); -#ifdef ENABLE_DUMPS // JS_DUMP_BYTECODE_FINAL - if (check_dump_flag(ctx->rt, JS_DUMP_BYTECODE_FINAL)) +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1) + if (!fd->strip_debug) { js_dump_function_bytecode(ctx, b); + } #endif if (fd->parent) { @@ -33744,14 +35167,19 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) return JS_EXCEPTION; } -#endif // QJS_DISABLE_PARSER - static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) { int i; +#if 0 + { + char buf[ATOM_GET_STR_BUF_SIZE]; + printf("freeing %s\n", + JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); + } +#endif if (b->byte_code_buf) - free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, true); + free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE); if (b->vardefs) { for(i = 0; i < b->arg_count + b->var_count; i++) { @@ -33769,9 +35197,11 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) JS_FreeContext(b->realm); JS_FreeAtomRT(rt, b->func_name); - JS_FreeAtomRT(rt, b->filename); - js_free_rt(rt, b->pc2line_buf); - js_free_rt(rt, b->source); + if (b->has_debug) { + JS_FreeAtomRT(rt, b->debug.filename); + js_free_rt(rt, b->debug.pc2line_buf); + js_free_rt(rt, b->debug.source); + } remove_gc_object(&b->header); if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) { @@ -33781,13 +35211,11 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) } } -#ifndef QJS_DISABLE_PARSER - static __exception int js_parse_directives(JSParseState *s) { char str[20]; JSParsePos pos; - bool has_semi; + BOOL has_semi; if (s->token.val != TOK_STRING) return 0; @@ -33802,16 +35230,16 @@ static __exception int js_parse_directives(JSParseState *s) if (next_token(s)) return -1; - has_semi = false; + has_semi = FALSE; switch (s->token.val) { case ';': if (next_token(s)) return -1; - has_semi = true; + has_semi = TRUE; break; case '}': case TOK_EOF: - has_semi = true; + has_semi = TRUE; break; case TOK_NUMBER: case TOK_STRING: @@ -33854,7 +35282,7 @@ static __exception int js_parse_directives(JSParseState *s) case TOK_STATIC: /* automatic insertion of ';' */ if (s->got_lf) - has_semi = true; + has_semi = TRUE; break; default: break; @@ -33862,30 +35290,17 @@ static __exception int js_parse_directives(JSParseState *s) if (!has_semi) break; if (!strcmp(str, "use strict")) { - s->cur_func->has_use_strict = true; - s->cur_func->is_strict_mode = true; + s->cur_func->has_use_strict = TRUE; + s->cur_func->js_mode |= JS_MODE_STRICT; } } return js_parse_seek_token(s, &pos); } -static bool js_invalid_strict_name(JSAtom name) { - switch (name) { - case JS_ATOM_eval: - case JS_ATOM_arguments: - case JS_ATOM_implements: // future strict reserved words - case JS_ATOM_interface: - case JS_ATOM_let: - case JS_ATOM_package: - case JS_ATOM_private: - case JS_ATOM_protected: - case JS_ATOM_public: - case JS_ATOM_static: - case JS_ATOM_yield: - return true; - default: - return false; - } +/* return TRUE if the keyword is forbidden only in strict mode */ +static BOOL is_strict_future_keyword(JSAtom atom) +{ + return (atom >= JS_ATOM_LAST_KEYWORD + 1 && atom <= JS_ATOM_LAST_STRICT_KEYWORD); } static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, @@ -33894,22 +35309,25 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, JSAtom name; int i, idx; - if (fd->is_strict_mode) { + if (fd->js_mode & JS_MODE_STRICT) { if (!fd->has_simple_parameter_list && fd->has_use_strict) { return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter"); } - if (js_invalid_strict_name(func_name)) { + if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments || + is_strict_future_keyword(func_name)) { return js_parse_error(s, "invalid function name in strict code"); } for (idx = 0; idx < fd->arg_count; idx++) { name = fd->args[idx].var_name; - if (js_invalid_strict_name(name)) { + + if (name == JS_ATOM_eval || name == JS_ATOM_arguments || + is_strict_future_keyword(name)) { return js_parse_error(s, "invalid argument name in strict code"); } } } /* check async_generator case */ - if (fd->is_strict_mode + if ((fd->js_mode & JS_MODE_STRICT) || !fd->has_simple_parameter_list || (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC) || fd->func_type == JS_PARSE_FUNC_ARROW @@ -33934,7 +35352,7 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, return 0; duplicate: - return js_parse_error(s, "Duplicate parameter name not allowed in this context"); + return js_parse_error(s, "duplicate argument names not allowed in this context"); } /* create a function to initialize class fields */ @@ -33942,21 +35360,22 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) { JSFunctionDef *fd; - fd = js_new_function_def(s->ctx, s->cur_func, false, false, - s->filename, 0, 0); + fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE, + s->filename, s->buf_start, + &s->get_line_col_cache); if (!fd) return NULL; fd->func_name = JS_ATOM_NULL; - fd->has_prototype = false; - fd->has_home_object = true; - - fd->has_arguments_binding = false; - fd->has_this_binding = true; - fd->is_derived_class_constructor = false; - fd->new_target_allowed = true; - fd->super_call_allowed = false; + fd->has_prototype = FALSE; + fd->has_home_object = TRUE; + + fd->has_arguments_binding = FALSE; + fd->has_this_binding = TRUE; + fd->is_derived_class_constructor = FALSE; + fd->new_target_allowed = TRUE; + fd->super_call_allowed = FALSE; fd->super_allowed = fd->has_home_object; - fd->arguments_allowed = false; + fd->arguments_allowed = FALSE; fd->func_kind = JS_FUNC_NORMAL; fd->func_type = JS_PARSE_FUNC_METHOD; @@ -33970,17 +35389,15 @@ static __exception int js_parse_function_decl2(JSParseState *s, JSFunctionKindEnum func_kind, JSAtom func_name, const uint8_t *ptr, - int function_line_num, - int function_col_num, JSParseExportEnum export_flag, JSFunctionDef **pfd) { JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; - bool is_expr; + BOOL is_expr; int func_idx, lexical_func_idx = -1; - bool has_opt_arg; - bool create_func_var = false; + BOOL has_opt_arg; + BOOL create_func_var = FALSE; is_expr = (func_type != JS_PARSE_FUNC_STATEMENT && func_type != JS_PARSE_FUNC_VAR); @@ -33990,7 +35407,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, func_type == JS_PARSE_FUNC_EXPR) { if (func_kind == JS_FUNC_NORMAL && token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, true) != '\n') { + peek_token(s, TRUE) != '\n') { if (next_token(s)) return -1; func_kind = JS_FUNC_ASYNC; @@ -34016,7 +35433,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } if (s->token.val == TOK_IDENT || - (((s->token.val == TOK_YIELD && !fd->is_strict_mode) || + (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) || (s->token.val == TOK_AWAIT && !s->is_module)) && func_type == JS_PARSE_FUNC_EXPR)) { func_name = JS_DupAtom(ctx, s->token.u.ident.atom); @@ -34047,12 +35464,12 @@ static __exception int js_parse_function_decl2(JSParseState *s, } if (func_type == JS_PARSE_FUNC_VAR) { - if (!fd->is_strict_mode + if (!(fd->js_mode & JS_MODE_STRICT) && func_kind == JS_FUNC_NORMAL - && find_lexical_decl(ctx, fd, func_name, fd->scope_first, false) < 0 + && find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0 && !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET)) && !(func_name == JS_ATOM_arguments && fd->has_arguments_binding)) { - create_func_var = true; + create_func_var = TRUE; } /* Create the lexical name here so that the function closure contains it */ @@ -34085,8 +35502,9 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } - fd = js_new_function_def(ctx, fd, false, is_expr, s->filename, - function_line_num, function_col_num); + fd = js_new_function_def(ctx, fd, FALSE, is_expr, + s->filename, ptr, + &s->get_line_col_cache); if (!fd) { JS_FreeAtom(ctx, func_name); return -1; @@ -34115,18 +35533,18 @@ static __exception int js_parse_function_decl2(JSParseState *s, fd->super_allowed = fd->parent->super_allowed; fd->arguments_allowed = fd->parent->arguments_allowed; } else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) { - fd->new_target_allowed = true; // although new.target === undefined - fd->super_call_allowed = false; - fd->super_allowed = true; - fd->arguments_allowed = false; + fd->new_target_allowed = TRUE; // although new.target === undefined + fd->super_call_allowed = FALSE; + fd->super_allowed = TRUE; + fd->arguments_allowed = FALSE; } else { - fd->new_target_allowed = true; + fd->new_target_allowed = TRUE; fd->super_call_allowed = fd->is_derived_class_constructor; fd->super_allowed = fd->has_home_object; - fd->arguments_allowed = true; + fd->arguments_allowed = TRUE; } - /* fd->in_function_body == false prevents yield/await during the parsing + /* fd->in_function_body == FALSE prevents yield/await during the parsing of the arguments in generator/async functions. They are parsed as regular identifiers for other function kinds. */ fd->func_kind = func_kind; @@ -34143,9 +35561,9 @@ static __exception int js_parse_function_decl2(JSParseState *s, } /* parse arguments */ - fd->has_simple_parameter_list = true; - fd->has_parameter_expressions = false; - has_opt_arg = false; + fd->has_simple_parameter_list = TRUE; + fd->has_parameter_expressions = FALSE; + has_opt_arg = FALSE; if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) { JSAtom name; if (s->token.u.ident.is_reserved) { @@ -34161,9 +35579,9 @@ static __exception int js_parse_function_decl2(JSParseState *s, int skip_bits; /* if there is an '=' inside the parameter list, we consider there is a parameter expression inside */ - js_parse_skip_parens_token(s, &skip_bits, false); + js_parse_skip_parens_token(s, &skip_bits, FALSE); if (skip_bits & SKIP_HAS_ASSIGNMENT) - fd->has_parameter_expressions = true; + fd->has_parameter_expressions = TRUE; if (next_token(s)) goto fail; } else { @@ -34179,17 +35597,19 @@ static __exception int js_parse_function_decl2(JSParseState *s, while (s->token.val != ')') { JSAtom name; - bool rest = false; + BOOL rest = FALSE; int idx, has_initializer; if (s->token.val == TOK_ELLIPSIS) { - fd->has_simple_parameter_list = false; - rest = true; + if (func_type == JS_PARSE_FUNC_SETTER) + goto fail_accessor; + fd->has_simple_parameter_list = FALSE; + rest = TRUE; if (next_token(s)) goto fail; } if (s->token.val == '[' || s->token.val == '{') { - fd->has_simple_parameter_list = false; + fd->has_simple_parameter_list = FALSE; if (rest) { emit_op(s, OP_rest); emit_u16(s, fd->arg_count); @@ -34199,11 +35619,11 @@ static __exception int js_parse_function_decl2(JSParseState *s, emit_op(s, OP_get_arg); emit_u16(s, idx); } - has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, true, true, -1, true, false); + has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE, FALSE); if (has_initializer < 0) goto fail; if (has_initializer) - has_opt_arg = true; + has_opt_arg = TRUE; if (!has_opt_arg) fd->defined_arg_count++; } else if (s->token.val == TOK_IDENT) { @@ -34239,13 +35659,13 @@ static __exception int js_parse_function_decl2(JSParseState *s, } emit_op(s, OP_put_arg); emit_u16(s, idx); - fd->has_simple_parameter_list = false; - has_opt_arg = true; + fd->has_simple_parameter_list = FALSE; + has_opt_arg = TRUE; } else if (s->token.val == '=') { int label; - fd->has_simple_parameter_list = false; - has_opt_arg = true; + fd->has_simple_parameter_list = FALSE; + has_opt_arg = TRUE; if (next_token(s)) goto fail; @@ -34296,6 +35716,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } if ((func_type == JS_PARSE_FUNC_GETTER && fd->arg_count != 0) || (func_type == JS_PARSE_FUNC_SETTER && fd->arg_count != 1)) { + fail_accessor: js_parse_error(s, "invalid number of arguments for getter or setter"); goto fail; } @@ -34346,11 +35767,11 @@ static __exception int js_parse_function_decl2(JSParseState *s, /* in generators, yield expression is forbidden during the parsing of the arguments */ - fd->in_function_body = true; + fd->in_function_body = TRUE; push_scope(s); /* enter body scope */ fd->body_scope = fd->scope_level; - if (s->token.val == TOK_ARROW) { + if (s->token.val == TOK_ARROW && func_type == JS_PARSE_FUNC_ARROW) { if (next_token(s)) goto fail; @@ -34366,22 +35787,23 @@ static __exception int js_parse_function_decl2(JSParseState *s, else emit_op(s, OP_return); - /* save the function source code */ - /* the end of the function source code is after the last - token of the function source stored into s->last_ptr */ - fd->source_len = s->last_ptr - ptr; - fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); - if (!fd->source) - goto fail; - + if (!fd->strip_source) { + /* save the function source code */ + /* the end of the function source code is after the last + token of the function source stored into s->last_ptr */ + fd->source_len = s->last_ptr - ptr; + fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); + if (!fd->source) + goto fail; + } goto done; } } - // js_parse_class() already consumed the '{' - if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) + if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) { if (js_parse_expect(s, '{')) goto fail; + } if (js_parse_directives(s)) goto fail; @@ -34394,12 +35816,13 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (js_parse_source_element(s)) goto fail; } - - /* save the function source code */ - fd->source_len = s->buf_ptr - ptr; - fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); - if (!fd->source) - goto fail; + if (!fd->strip_source) { + /* save the function source code */ + fd->source_len = s->buf_ptr - ptr; + fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); + if (!fd->source) + goto fail; + } if (next_token(s)) { /* consume the '}' */ @@ -34408,9 +35831,9 @@ static __exception int js_parse_function_decl2(JSParseState *s, /* in case there is no return, add one */ if (js_is_live_code(s)) { - emit_return(s, false); + emit_return(s, FALSE); } -done: + done: s->cur_func = fd->parent; /* Reparse identifiers after the function is terminated so that @@ -34456,7 +35879,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, (needed for annex B.3.3.4 and B.3.3.5 checks) */ hf->scope_level = 0; - hf->force_init = s->cur_func->is_strict_mode; + hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0); /* store directly into global var, bypass lexical scope */ emit_op(s, OP_dup); emit_op(s, OP_scope_put_var); @@ -34533,12 +35956,9 @@ static __exception int js_parse_function_decl(JSParseState *s, JSParseFunctionEnum func_type, JSFunctionKindEnum func_kind, JSAtom func_name, - const uint8_t *ptr, - int start_line, - int start_col) + const uint8_t *ptr) { return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, - start_line, start_col, JS_PARSE_EXPORT_NONE, NULL); } @@ -34555,7 +35975,7 @@ static __exception int js_parse_program(JSParseState *s) fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) || (fd->eval_type == JS_EVAL_TYPE_MODULE) || - !fd->is_strict_mode; + !(fd->js_mode & JS_MODE_STRICT); if (!s->is_module) { /* hidden variable for the return value */ @@ -34586,32 +36006,30 @@ static __exception int js_parse_program(JSParseState *s) emit_op(s, OP_get_loc); emit_u16(s, fd->eval_ret_idx); } - emit_return(s, true); + emit_return(s, TRUE); } else { - emit_return(s, false); + emit_return(s, FALSE); } return 0; } -#endif // QJS_DISABLE_PARSER - static void js_parse_init(JSContext *ctx, JSParseState *s, const char *input, size_t input_len, - const char *filename, int line) + const char *filename) { memset(s, 0, sizeof(*s)); s->ctx = ctx; s->filename = filename; - s->line_num = line; - s->col_num = 1; s->buf_start = s->buf_ptr = (const uint8_t *)input; s->buf_end = s->buf_ptr + input_len; - s->mark = s->buf_ptr + min_int(1, input_len); - s->eol = s->buf_ptr; s->token.val = ' '; - s->token.line_num = 1; - s->token.col_num = 1; + s->token.ptr = s->buf_ptr; + + s->get_line_col_cache.ptr = s->buf_start; + s->get_line_col_cache.buf_start = s->buf_start; + s->get_line_col_cache.line_num = 0; + s->get_line_col_cache.col_num = 0; } static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj, @@ -34651,25 +36069,21 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj) return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_obj, NULL, NULL); } -#ifndef QJS_DISABLE_PARSER - /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ -/* `export_name` and `input` may be pure ASCII or UTF-8 encoded */ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, - const char *filename, int line, int flags, int scope_idx) + const char *filename, int flags, int scope_idx) { JSParseState s1, *s = &s1; - int err, eval_type; + int err, js_mode, eval_type; JSValue fun_obj, ret_val; JSStackFrame *sf; JSVarRef **var_refs; JSFunctionBytecode *b; JSFunctionDef *fd; JSModuleDef *m; - bool is_strict_mode; - js_parse_init(ctx, s, input, input_len, filename, line); + js_parse_init(ctx, s, input, input_len, filename); skip_shebang(&s->buf_ptr, s->buf_end); eval_type = flags & JS_EVAL_TYPE_MASK; @@ -34683,12 +36097,14 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, assert(js_class_has_bytecode(p->class_id)); b = p->u.func.function_bytecode; var_refs = p->u.func.var_refs; - is_strict_mode = b->is_strict_mode; + js_mode = b->js_mode; } else { sf = NULL; b = NULL; var_refs = NULL; - is_strict_mode = (flags & JS_EVAL_FLAG_STRICT) != 0; + js_mode = 0; + if (flags & JS_EVAL_FLAG_STRICT) + js_mode |= JS_MODE_STRICT; if (eval_type == JS_EVAL_TYPE_MODULE) { JSAtom module_name = JS_NewAtom(ctx, filename); if (module_name == JS_ATOM_NULL) @@ -34696,28 +36112,28 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, m = js_new_module_def(ctx, module_name); if (!m) return JS_EXCEPTION; - is_strict_mode = true; + js_mode |= JS_MODE_STRICT; } } - fd = js_new_function_def(ctx, NULL, true, false, filename, line, 1); + fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, + s->buf_start, &s->get_line_col_cache); if (!fd) goto fail1; s->cur_func = fd; fd->eval_type = eval_type; fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT); - fd->backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0); if (eval_type == JS_EVAL_TYPE_DIRECT) { fd->new_target_allowed = b->new_target_allowed; fd->super_call_allowed = b->super_call_allowed; fd->super_allowed = b->super_allowed; fd->arguments_allowed = b->arguments_allowed; } else { - fd->new_target_allowed = false; - fd->super_call_allowed = false; - fd->super_allowed = false; - fd->arguments_allowed = true; + fd->new_target_allowed = FALSE; + fd->super_call_allowed = FALSE; + fd->super_allowed = FALSE; + fd->arguments_allowed = TRUE; } - fd->is_strict_mode = is_strict_mode; + fd->js_mode = js_mode; fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_); if (b) { if (add_closure_variables(ctx, fd, b, scope_idx)) @@ -34725,7 +36141,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, } fd->module = m; if (m != NULL || (flags & JS_EVAL_FLAG_ASYNC)) { - fd->in_function_body = true; + fd->in_function_body = TRUE; fd->func_kind = JS_FUNC_ASYNC; } s->is_module = (m != NULL); @@ -34765,28 +36181,31 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, fail1: /* XXX: should free all the unresolved dependencies */ if (m) - js_free_module_def(ctx, m); + JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); return JS_EXCEPTION; } -#endif // QJS_DISABLE_PARSER - /* the indirection is needed to make 'eval' optional */ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, - const char *filename, int line, int flags, int scope_idx) + const char *filename, int flags, int scope_idx) { - JSRuntime *rt = ctx->rt; - + BOOL backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0); + int saved_js_mode = 0; + JSValue ret; + if (unlikely(!ctx->eval_internal)) { return JS_ThrowTypeError(ctx, "eval is not supported"); } - if (!rt->current_stack_frame) { - JS_FreeValueRT(rt, ctx->error_back_trace); - ctx->error_back_trace = JS_UNDEFINED; + if (backtrace_barrier && ctx->rt->current_stack_frame) { + saved_js_mode = ctx->rt->current_stack_frame->js_mode; + ctx->rt->current_stack_frame->js_mode |= JS_MODE_BACKTRACE_BARRIER; } - return ctx->eval_internal(ctx, this_obj, input, input_len, filename, line, - flags, scope_idx); + ret = ctx->eval_internal(ctx, this_obj, input, input_len, filename, + flags, scope_idx); + if (backtrace_barrier && ctx->rt->current_stack_frame) + ctx->rt->current_stack_frame->js_mode = saved_js_mode; + return ret; } static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, @@ -34797,11 +36216,11 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, size_t len; if (!JS_IsString(val)) - return js_dup(val); + return JS_DupValue(ctx, val); str = JS_ToCStringLen(ctx, &len, val); if (!str) return JS_EXCEPTION; - ret = JS_EvalInternal(ctx, this_obj, str, len, "", 1, flags, scope_idx); + ret = JS_EvalInternal(ctx, this_obj, str, len, "", flags, scope_idx); JS_FreeCString(ctx, str); return ret; @@ -34811,36 +36230,12 @@ JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int eval_flags) { - JSEvalOptions options = { - .version = JS_EVAL_OPTIONS_VERSION, - .filename = filename, - .line_num = 1, - .eval_flags = eval_flags - }; - return JS_EvalThis2(ctx, this_obj, input, input_len, &options); -} - -JSValue JS_EvalThis2(JSContext *ctx, JSValueConst this_obj, - const char *input, size_t input_len, - JSEvalOptions *options) -{ - const char *filename = ""; - int line = 1; - int eval_flags = 0; - if (options) { - if (options->version != JS_EVAL_OPTIONS_VERSION) - return JS_ThrowInternalError(ctx, "bad JSEvalOptions version"); - if (options->filename) - filename = options->filename; - if (options->line_num != 0) - line = options->line_num; - eval_flags = options->eval_flags; - } + int eval_type = eval_flags & JS_EVAL_TYPE_MASK; JSValue ret; - assert((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_GLOBAL || - (eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE); - ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, line, + assert(eval_type == JS_EVAL_TYPE_GLOBAL || + eval_type == JS_EVAL_TYPE_MODULE); + ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, eval_flags, -1); return ret; } @@ -34848,18 +36243,8 @@ JSValue JS_EvalThis2(JSContext *ctx, JSValueConst this_obj, JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int eval_flags) { - JSEvalOptions options = { - .version = JS_EVAL_OPTIONS_VERSION, - .filename = filename, - .line_num = 1, - .eval_flags = eval_flags - }; - return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, &options); -} - -JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len, JSEvalOptions *options) -{ - return JS_EvalThis2(ctx, ctx->global_obj, input, input_len, options); + return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename, + eval_flags); } int JS_ResolveModule(JSContext *ctx, JSValueConst obj) @@ -34998,25 +36383,19 @@ typedef enum BCTagEnum { BC_TAG_TYPED_ARRAY, BC_TAG_ARRAY_BUFFER, BC_TAG_SHARED_ARRAY_BUFFER, - BC_TAG_REGEXP, BC_TAG_DATE, BC_TAG_OBJECT_VALUE, BC_TAG_OBJECT_REFERENCE, - BC_TAG_MAP, - BC_TAG_SET, - BC_TAG_SYMBOL, } BCTagEnum; -#define BC_VERSION 21 +#define BC_VERSION 5 typedef struct BCWriterState { JSContext *ctx; DynBuf dbuf; - bool allow_bytecode; - bool allow_sab; - bool allow_reference; - bool allow_source; - bool allow_debug; + BOOL allow_bytecode : 8; + BOOL allow_sab : 8; + BOOL allow_reference : 8; uint32_t first_atom; uint32_t *atom_to_idx; int atom_to_idx_size; @@ -35026,11 +36405,11 @@ typedef struct BCWriterState { uint8_t **sab_tab; int sab_tab_len; int sab_tab_size; - /* list of referenced objects (used if allow_reference = true) */ + /* list of referenced objects (used if allow_reference = TRUE) */ JSObjectList object_list; } BCWriterState; -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT +#ifdef DUMP_READ_OBJECT static const char * const bc_tag_str[] = { "invalid", "null", @@ -35042,29 +36421,27 @@ static const char * const bc_tag_str[] = { "string", "object", "array", - "BigInt", + "bigint", "template", "function", "module", "TypedArray", "ArrayBuffer", "SharedArrayBuffer", - "RegExp", "Date", "ObjectValue", "ObjectReference", - "Map", - "Set", - "Symbol", }; +#endif -static const char *bc_tag_name(uint8_t tag) +static inline BOOL is_be(void) { - if (tag >= countof(bc_tag_str)) - return ""; - return bc_tag_str[tag]; + union { + uint16_t a; + uint8_t b; + } u = {0x100}; + return u.b; } -#endif static void bc_put_u8(BCWriterState *s, uint8_t v) { @@ -35224,18 +36601,17 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len) } static int JS_WriteFunctionBytecode(BCWriterState *s, - const JSFunctionBytecode *b) + const uint8_t *bc_buf1, int bc_len) { - int pos, len, bc_len, op; + int pos, len, op; JSAtom atom; uint8_t *bc_buf; uint32_t val; - bc_len = b->byte_code_len; bc_buf = js_malloc(s->ctx, bc_len); if (!bc_buf) return -1; - memcpy(bc_buf, b->byte_code_buf, bc_len); + memcpy(bc_buf, bc_buf1, bc_len); pos = 0; while (pos < bc_len) { @@ -35276,9 +36652,9 @@ static void JS_WriteString(BCWriterState *s, JSString *p) bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char); if (p->is_wide_char) { for(i = 0; i < p->len; i++) - bc_put_u16(s, str16(p)[i]); + bc_put_u16(s, p->u.str16[i]); } else { - dbuf_put(&s->dbuf, str8(p), p->len); + dbuf_put(&s->dbuf, p->u.str8, p->len); } } @@ -35289,7 +36665,7 @@ static int JS_WriteBigInt(BCWriterState *s, JSValueConst obj) uint32_t len, i; js_limb_t v, b; int shift; - + bc_put_u8(s, BC_TAG_BIG_INT); if (JS_VALUE_GET_TAG(obj) == JS_TAG_SHORT_BIG_INT) @@ -35318,7 +36694,11 @@ static int JS_WriteBigInt(BCWriterState *s, JSValueConst obj) bc_put_leb128(s, len); if (len > 0) { for(i = 0; i < (len / (JS_LIMB_BITS / 8)); i++) { +#if JS_LIMB_BITS == 32 bc_put_u32(s, p->tab[i]); +#else + bc_put_u64(s, p->tab[i]); +#endif } for(i = 0; i < len % (JS_LIMB_BITS / 8); i++) { bc_put_u8(s, (p->tab[p->len - 1] >> (i * 8)) & 0xff); @@ -35346,11 +36726,11 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_set_flags(&flags, &idx, b->super_call_allowed, 1); bc_set_flags(&flags, &idx, b->super_allowed, 1); bc_set_flags(&flags, &idx, b->arguments_allowed, 1); - bc_set_flags(&flags, &idx, b->backtrace_barrier, 1); - bc_set_flags(&flags, &idx, s->allow_debug, 1); + bc_set_flags(&flags, &idx, b->has_debug, 1); + bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1); assert(idx <= 16); bc_put_u16(s, flags); - bc_put_u8(s, b->is_strict_mode); + bc_put_u8(s, b->js_mode); bc_put_atom(s, b->func_name); bc_put_leb128(s, b->arg_count); @@ -35394,29 +36774,25 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_put_u8(s, flags); } - // write constant pool before code so code can be disassembled - // on the fly at read time - for(i = 0; i < b->cpool_count; i++) { - if (JS_WriteObjectRec(s, b->cpool[i])) - goto fail; - } - - if (JS_WriteFunctionBytecode(s, b)) + if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len)) goto fail; - if (s->allow_debug) { - bc_put_atom(s, b->filename); - bc_put_leb128(s, b->line_num); - bc_put_leb128(s, b->col_num); - bc_put_leb128(s, b->pc2line_len); - dbuf_put(&s->dbuf, b->pc2line_buf, b->pc2line_len); - if (s->allow_source && b->source) { - bc_put_leb128(s, b->source_len); - dbuf_put(&s->dbuf, b->source, b->source_len); + if (b->has_debug) { + bc_put_atom(s, b->debug.filename); + bc_put_leb128(s, b->debug.pc2line_len); + dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len); + if (b->debug.source) { + bc_put_leb128(s, b->debug.source_len); + dbuf_put(&s->dbuf, (uint8_t *)b->debug.source, b->debug.source_len); } else { bc_put_leb128(s, 0); } } + + for(i = 0; i < b->cpool_count; i++) { + if (JS_WriteObjectRec(s, b->cpool[i])) + goto fail; + } return 0; fail: return -1; @@ -35434,6 +36810,8 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; bc_put_atom(s, rme->module_name); + if (JS_WriteObjectRec(s, rme->attributes)) + goto fail; } bc_put_leb128(s, m->export_entries_count); @@ -35459,6 +36837,7 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) for(i = 0; i < m->import_entries_count; i++) { JSImportEntry *mi = &m->import_entries[i]; bc_put_leb128(s, mi->var_idx); + bc_put_u8(s, mi->is_star); bc_put_atom(s, mi->import_name); bc_put_leb128(s, mi->req_module_idx); } @@ -35478,16 +36857,16 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj) uint32_t i, len; JSValue val; int ret; - bool is_template; + BOOL is_template; if (s->allow_bytecode && !p->extensible) { /* not extensible array: we consider it is a template when we are saving bytecode */ bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT); - is_template = true; + is_template = TRUE; } else { bc_put_u8(s, BC_TAG_ARRAY); - is_template = false; + is_template = FALSE; } if (js_get_length32(s->ctx, &len, obj)) goto fail1; @@ -35532,7 +36911,9 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) bc_put_leb128(s, prop_count); for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { atom = pr->atom; - if (atom != JS_ATOM_NULL && (pr->flags & JS_PROP_ENUMERABLE)) { + if (atom != JS_ATOM_NULL && + JS_AtomIsString(s->ctx, atom) && + (pr->flags & JS_PROP_ENUMERABLE)) { if (pr->flags & JS_PROP_TMASK) { JS_ThrowTypeError(s->ctx, "only value properties are supported"); goto fail; @@ -35598,27 +36979,6 @@ static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj) return 0; } -static int JS_WriteRegExp(BCWriterState *s, JSRegExp regexp) -{ - JSString *bc = regexp.bytecode; - assert(!bc->is_wide_char); - - JS_WriteString(s, regexp.pattern); - - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/false); - - JS_WriteString(s, bc); - - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/true); - - return 0; -} - -static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state); -static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state); - static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) { uint32_t tag; @@ -35658,6 +37018,16 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) JS_WriteString(s, p); } break; + case JS_TAG_STRING_ROPE: + { + JSValue str; + str = JS_ToString(s->ctx, obj); + if (JS_IsException(str)) + goto fail; + JS_WriteObjectRec(s, str); + JS_FreeValue(s->ctx, str); + } + break; case JS_TAG_FUNCTION_BYTECODE: if (!s->allow_bytecode) goto invalid_tag; @@ -35707,10 +37077,6 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) goto invalid_tag; ret = JS_WriteSharedArrayBuffer(s, obj); break; - case JS_CLASS_REGEXP: - bc_put_u8(s, BC_TAG_REGEXP); - ret = JS_WriteRegExp(s, p->u.regexp); - break; case JS_CLASS_DATE: bc_put_u8(s, BC_TAG_DATE); ret = JS_WriteObjectRec(s, p->u.object_data); @@ -35722,16 +37088,9 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_put_u8(s, BC_TAG_OBJECT_VALUE); ret = JS_WriteObjectRec(s, p->u.object_data); break; - case JS_CLASS_MAP: - bc_put_u8(s, BC_TAG_MAP); - ret = JS_WriteMap(s, p->u.map_state); - break; - case JS_CLASS_SET: - bc_put_u8(s, BC_TAG_SET); - ret = JS_WriteSet(s, p->u.map_state); - break; default: - if (is_typed_array(p->class_id)) { + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_WriteTypedArray(s, obj); } else { JS_ThrowTypeError(s->ctx, "unsupported object class"); @@ -35749,18 +37108,6 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) if (JS_WriteBigInt(s, obj)) goto fail; break; - case JS_TAG_SYMBOL: - { - JSAtomStruct *p = JS_VALUE_GET_PTR(obj); - if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL && p->atom_type != JS_ATOM_TYPE_SYMBOL) { - JS_ThrowTypeError(s->ctx, "unsupported symbol type"); - goto fail; - } - JSAtom atom = js_get_atom_index(s->ctx->rt, p); - bc_put_u8(s, BC_TAG_SYMBOL); - bc_put_atom(s, atom); - } - break; default: invalid_tag: JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag); @@ -35785,19 +37132,8 @@ static int JS_WriteObjectAtoms(BCWriterState *s) bc_put_leb128(s, s->idx_to_atom_count); for(i = 0; i < s->idx_to_atom_count; i++) { - JSAtom atom = s->idx_to_atom[i]; - if (__JS_AtomIsConst(atom)) { - bc_put_u8(s, 0 /* the type */); - /* TODO(saghul): encoding for tagged integers and keyword-ish atoms could be - more efficient. */ - bc_put_u32(s, atom); - } else { - JSAtomStruct *p = rt->atom_array[atom]; - uint8_t type = p->atom_type; - assert(type != JS_ATOM_TYPE_PRIVATE); - bc_put_u8(s, type); - JS_WriteString(s, p); - } + JSAtomStruct *p = rt->atom_array[s->idx_to_atom[i]]; + JS_WriteString(s, p); } /* XXX: should check for OOM in above phase */ @@ -35805,7 +37141,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) /* XXX: could just append dbuf1 data, but it uses more memory if dbuf1 is larger than dbuf */ atoms_size = s->dbuf.size; - if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size)) + if (dbuf_claim(&dbuf1, atoms_size)) goto fail; memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size); memcpy(dbuf1.buf, s->dbuf.buf, atoms_size); @@ -35819,7 +37155,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) } uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, - int flags, JSSABTab *psab_tab) + int flags, uint8_t ***psab_tab, size_t *psab_tab_len) { BCWriterState ss, *s = &ss; @@ -35828,8 +37164,6 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0); s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0); s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0); - s->allow_source = ((flags & JS_WRITE_OBJ_STRIP_SOURCE) == 0); - s->allow_debug = ((flags & JS_WRITE_OBJ_STRIP_DEBUG) == 0); /* XXX: could use a different version when bytecode is included */ if (s->allow_bytecode) s->first_atom = JS_ATOM_END; @@ -35846,12 +37180,10 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, js_free(ctx, s->atom_to_idx); js_free(ctx, s->idx_to_atom); *psize = s->dbuf.size; - if (psab_tab) { - psab_tab->tab = s->sab_tab; - psab_tab->len = s->sab_tab_len; - } else { - js_free(ctx, s->sab_tab); - } + if (psab_tab) + *psab_tab = s->sab_tab; + if (psab_tab_len) + *psab_tab_len = s->sab_tab_len; return s->dbuf.buf; fail: js_object_list_end(ctx, &s->object_list); @@ -35859,17 +37191,17 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, js_free(ctx, s->idx_to_atom); dbuf_free(&s->dbuf); *psize = 0; - if (psab_tab) { - psab_tab->tab = NULL; - psab_tab->len = 0; - } + if (psab_tab) + *psab_tab = NULL; + if (psab_tab_len) + *psab_tab_len = 0; return NULL; } uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, int flags) { - return JS_WriteObject2(ctx, psize, obj, flags, NULL); + return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL); } typedef struct BCReaderState { @@ -35879,30 +37211,26 @@ typedef struct BCReaderState { uint32_t idx_to_atom_count; JSAtom *idx_to_atom; int error_state; - bool allow_sab; - bool allow_bytecode; - bool allow_reference; + BOOL allow_sab : 8; + BOOL allow_bytecode : 8; + BOOL is_rom_data : 8; + BOOL allow_reference : 8; /* object references */ JSObject **objects; int objects_count; int objects_size; - /* SAB references */ - uint8_t **sab_tab; - int sab_tab_len; - int sab_tab_size; - /* used for JS_DUMP_READ_OBJECT */ + +#ifdef DUMP_READ_OBJECT const uint8_t *ptr_last; int level; +#endif } BCReaderState; -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT -static void JS_PRINTF_FORMAT_ATTR(2, 3) bc_read_trace(BCReaderState *s, JS_PRINTF_FORMAT const char *fmt, ...) { +#ifdef DUMP_READ_OBJECT +static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s, const char *fmt, ...) { va_list ap; int i, n, n0; - if (!check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) - return; - if (!s->ptr_last) s->ptr_last = s->buf_start; @@ -36033,7 +37361,7 @@ static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval) return 0; } -static int bc_get_buf(BCReaderState *s, void *buf, uint32_t buf_len) +static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len) { if (buf_len != 0) { if (unlikely(!buf || s->buf_end - s->ptr < buf_len)) @@ -36083,7 +37411,7 @@ static JSString *JS_ReadString(BCReaderState *s) { uint32_t len; size_t size; - bool is_wide_char; + BOOL is_wide_char; JSString *p; if (bc_get_leb128(s, &len)) @@ -36105,23 +37433,19 @@ static JSString *JS_ReadString(BCReaderState *s) js_free_string(s->ctx->rt, p); return NULL; } - memcpy(str8(p), s->ptr, size); + memcpy(p->u.str8, s->ptr, size); s->ptr += size; if (is_wide_char) { if (is_be()) { uint32_t i; for (i = 0; i < len; i++) - str16(p)[i] = bswap16(str16(p)[i]); + p->u.str16[i] = bswap16(p->u.str16[i]); } } else { - str8(p)[size] = '\0'; /* add the trailing zero for 8 bit strings */ - } -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "%s", ""); // hex dump and indentation - JS_DumpString(s->ctx->rt, p); - printf("\n"); + p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */ } +#ifdef DUMP_READ_OBJECT + JS_DumpString(s->ctx->rt, p); printf("\n"); #endif return p; } @@ -36143,9 +37467,17 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, JSAtom atom; uint32_t idx; - bc_buf = (uint8_t*)b + byte_code_offset; - if (bc_get_buf(s, bc_buf, bc_len)) - return -1; + if (s->is_rom_data) { + /* directly use the input buffer */ + if (unlikely(s->buf_end - s->ptr < bc_len)) + return bc_read_error_end(s); + bc_buf = (uint8_t *)s->ptr; + s->ptr += bc_len; + } else { + bc_buf = (void *)((uint8_t*)b + byte_code_offset); + if (bc_get_buf(s, bc_buf, bc_len)) + return -1; + } b->byte_code_buf = bc_buf; if (is_be()) @@ -36162,28 +37494,24 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, case OP_FMT_atom_label_u8: case OP_FMT_atom_label_u16: idx = get_u32(bc_buf + pos + 1); - if (bc_idx_to_atom(s, &atom, idx)) { - /* Note: the atoms will be freed up to this position */ - b->byte_code_len = pos; - return -1; + if (s->is_rom_data) { + /* just increment the reference count of the atom */ + JS_DupAtom(s->ctx, (JSAtom)idx); + } else { + if (bc_idx_to_atom(s, &atom, idx)) { + /* Note: the atoms will be freed up to this position */ + b->byte_code_len = pos; + return -1; + } + put_u32(bc_buf + pos + 1, atom); +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "at %d, fixup atom: ", pos + 1); print_atom(s->ctx, atom); printf("\n"); +#endif } - put_u32(bc_buf + pos + 1, atom); break; default: break; } -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - const uint8_t *save_ptr = s->ptr; - s->ptr = s->ptr_last + len; - s->level -= 4; - bc_read_trace(s, "%s", ""); // hex dump + indent - dump_single_byte_code(s->ctx, bc_buf + pos, b, - s->ptr - s->buf_start - len); - s->level += 4; - s->ptr = save_ptr; - } -#endif pos += len; } return 0; @@ -36196,7 +37524,7 @@ static JSValue JS_ReadBigInt(BCReaderState *s) JSBigInt *p; js_limb_t v; uint8_t v8; - + if (bc_get_leb128(s, &len)) goto fail; bc_read_trace(s, "len=%" PRId64 "\n", (int64_t)len); @@ -36209,8 +37537,13 @@ static JSValue JS_ReadBigInt(BCReaderState *s) if (!p) goto fail; for(i = 0; i < len / (JS_LIMB_BITS / 8); i++) { +#if JS_LIMB_BITS == 32 if (bc_get_u32(s, &v)) goto fail; +#else + if (bc_get_u64(s, &v)) + goto fail; +#endif p->tab[i] = v; } n = len % (JS_LIMB_BITS / 8); @@ -36250,7 +37583,7 @@ static int BC_add_object_ref1(BCReaderState *s, JSObject *p) return 0; } -static int BC_add_object_ref(BCReaderState *s, JSValue obj) +static int BC_add_object_ref(BCReaderState *s, JSValueConst obj) { return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj)); } @@ -36262,7 +37595,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) JSValue obj = JS_UNDEFINED; uint16_t v16; uint8_t v8; - int idx, i, local_count, has_debug_info; + int idx, i, local_count; int function_size, cpool_offset, byte_code_offset; int closure_var_offset, vardefs_offset; @@ -36282,12 +37615,13 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) bc.super_call_allowed = bc_get_flags(v16, &idx, 1); bc.super_allowed = bc_get_flags(v16, &idx, 1); bc.arguments_allowed = bc_get_flags(v16, &idx, 1); - bc.backtrace_barrier = bc_get_flags(v16, &idx, 1); - has_debug_info = bc_get_flags(v16, &idx, 1); + bc.has_debug = bc_get_flags(v16, &idx, 1); + bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1); + bc.read_only_bytecode = s->is_rom_data; if (bc_get_u8(s, &v8)) goto fail; - bc.is_strict_mode = (v8 > 0); - if (bc_get_atom(s, &bc.func_name)) + bc.js_mode = v8; + if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure goto fail; if (bc_get_leb128_u16(s, &bc.arg_count)) goto fail; @@ -36306,7 +37640,11 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) if (bc_get_leb128_int(s, &local_count)) goto fail; - function_size = sizeof(*b); + if (bc.has_debug) { + function_size = sizeof(*b); + } else { + function_size = offsetof(JSFunctionBytecode, debug); + } cpool_offset = function_size; function_size += bc.cpool_count * sizeof(*bc.cpool); vardefs_offset = function_size; @@ -36314,14 +37652,15 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) closure_var_offset = function_size; function_size += bc.closure_var_count * sizeof(*bc.closure_var); byte_code_offset = function_size; - function_size += bc.byte_code_len; + if (!bc.read_only_bytecode) { + function_size += bc.byte_code_len; + } b = js_mallocz(ctx, function_size); if (!b) - goto fail; + return JS_EXCEPTION; - memcpy(b, &bc, sizeof(*b)); - bc.func_name = JS_ATOM_NULL; + memcpy(b, &bc, offsetof(JSFunctionBytecode, debug)); b->header.ref_count = 1; if (local_count != 0) { b->vardefs = (void *)((uint8_t*)b + vardefs_offset); @@ -36337,14 +37676,8 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b); -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - if (b->func_name) { - bc_read_trace(s, "name: "); - print_atom(s->ctx, b->func_name); - printf("\n"); - } - } +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n"); #endif bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n", b->arg_count, b->var_count, b->defined_arg_count, @@ -36354,7 +37687,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) if (local_count != 0) { bc_read_trace(s, "vars {\n"); - bc_read_trace(s, "off flags scope name\n"); for(i = 0; i < local_count; i++) { JSVarDef *vd = &b->vardefs[i]; if (bc_get_atom(s, &vd->var_name)) @@ -36371,24 +37703,14 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) vd->is_const = bc_get_flags(v8, &idx, 1); vd->is_lexical = bc_get_flags(v8, &idx, 1); vd->is_captured = bc_get_flags(v8, &idx, 1); -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "%3d %d%c%c%c %4d ", - i, vd->var_kind, - vd->is_const ? 'C' : '.', - vd->is_lexical ? 'L' : '.', - vd->is_captured ? 'X' : '.', - vd->scope_level); - print_atom(s->ctx, vd->var_name); - printf("\n"); - } +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n"); #endif } bc_read_trace(s, "}\n"); } if (b->closure_var_count != 0) { bc_read_trace(s, "closure vars {\n"); - bc_read_trace(s, "off flags idx name\n"); for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; int var_idx; @@ -36405,88 +37727,61 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) cv->is_const = bc_get_flags(v8, &idx, 1); cv->is_lexical = bc_get_flags(v8, &idx, 1); cv->var_kind = bc_get_flags(v8, &idx, 4); -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "%3d %d%c%c%c%c %3d ", - i, cv->var_kind, - cv->is_local ? 'L' : '.', - cv->is_arg ? 'A' : '.', - cv->is_const ? 'C' : '.', - cv->is_lexical ? 'X' : '.', - cv->var_idx); - print_atom(s->ctx, cv->var_name); - printf("\n"); - } +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); #endif } bc_read_trace(s, "}\n"); } - if (b->cpool_count != 0) { - bc_read_trace(s, "cpool {\n"); - for(i = 0; i < b->cpool_count; i++) { - JSValue val; - val = JS_ReadObjectRec(s); - if (JS_IsException(val)) - goto fail; - b->cpool[i] = val; - } - bc_read_trace(s, "}\n"); - } { bc_read_trace(s, "bytecode {\n"); if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len)) goto fail; bc_read_trace(s, "}\n"); } - if (!has_debug_info) - goto nodebug; - - /* read optional debug information */ - bc_read_trace(s, "debug {\n"); - if (bc_get_atom(s, &b->filename)) - goto fail; - if (bc_get_leb128_int(s, &b->line_num)) - goto fail; - if (bc_get_leb128_int(s, &b->col_num)) - goto fail; -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "filename: "); - print_atom(s->ctx, b->filename); - printf(", line: %d, column: %d\n", b->line_num, b->col_num); - } + if (b->has_debug) { + /* read optional debug information */ + bc_read_trace(s, "debug {\n"); + if (bc_get_atom(s, &b->debug.filename)) + goto fail; +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n"); #endif - if (bc_get_leb128_int(s, &b->pc2line_len)) - goto fail; - if (b->pc2line_len) { - bc_read_trace(s, "positions: %d bytes\n", b->pc2line_len); - b->pc2line_buf = js_mallocz(ctx, b->pc2line_len); - if (!b->pc2line_buf) + if (bc_get_leb128_int(s, &b->debug.pc2line_len)) goto fail; - if (bc_get_buf(s, b->pc2line_buf, b->pc2line_len)) + if (b->debug.pc2line_len) { + b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len); + if (!b->debug.pc2line_buf) + goto fail; + if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len)) + goto fail; + } + if (bc_get_leb128_int(s, &b->debug.source_len)) goto fail; + if (b->debug.source_len) { + bc_read_trace(s, "source: %d bytes\n", b->source_len); + b->debug.source = js_mallocz(ctx, b->debug.source_len); + if (!b->debug.source) + goto fail; + if (bc_get_buf(s, (uint8_t *)b->debug.source, b->debug.source_len)) + goto fail; + } + bc_read_trace(s, "}\n"); } - if (bc_get_leb128_int(s, &b->source_len)) - goto fail; - if (b->source_len) { - bc_read_trace(s, "source: %d bytes\n", b->source_len); - if (s->ptr_last) - s->ptr_last += b->source_len; // omit source code hex dump - /* b->source is a UTF-8 encoded null terminated C string */ - b->source = js_mallocz(ctx, b->source_len + 1); - if (!b->source) - goto fail; - if (bc_get_buf(s, b->source, b->source_len)) - goto fail; + if (b->cpool_count != 0) { + bc_read_trace(s, "cpool {\n"); + for(i = 0; i < b->cpool_count; i++) { + JSValue val; + val = JS_ReadObjectRec(s); + if (JS_IsException(val)) + goto fail; + b->cpool[i] = val; + } + bc_read_trace(s, "}\n"); } - bc_read_trace(s, "}\n"); - - nodebug: b->realm = JS_DupContext(ctx); return obj; - fail: - JS_FreeAtom(ctx, bc.func_name); JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -36502,20 +37797,15 @@ static JSValue JS_ReadModule(BCReaderState *s) if (bc_get_atom(s, &module_name)) goto fail; -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "name: "); - print_atom(s->ctx, module_name); - printf("\n"); - } +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n"); #endif m = js_new_module_def(ctx, module_name); if (!m) goto fail; - obj = js_dup(JS_MKPTR(JS_TAG_MODULE, m)); + obj = JS_NewModuleValue(ctx, m); if (bc_get_leb128_int(s, &m->req_module_entries_count)) goto fail; - obj = JS_NewModuleValue(ctx, m); if (m->req_module_entries_count != 0) { m->req_module_entries_size = m->req_module_entries_count; m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size); @@ -36523,21 +37813,13 @@ static JSValue JS_ReadModule(BCReaderState *s) goto fail; for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; - JSModuleDef **pm = &rme->module; + JSValue val; if (bc_get_atom(s, &rme->module_name)) goto fail; - // Resolves a module either from the cache or by requesting - // it from the module loader. From cache is not ideal because - // the module may not be the one it was a time of serialization - // but directly petitioning the module loader is not correct - // either because then the same module can get loaded twice. - // JS_WriteModule() does not serialize modules transitively - // because that doesn't work for C modules and is also prone - // to loading the same JS module twice. - *pm = js_host_resolve_imported_module_atom(s->ctx, m->module_name, - rme->module_name); - if (!*pm) + val = JS_ReadObjectRec(s); + if (JS_IsException(val)) goto fail; + rme->attributes = val; } } @@ -36590,8 +37872,12 @@ static JSValue JS_ReadModule(BCReaderState *s) goto fail; for(i = 0; i < m->import_entries_count; i++) { JSImportEntry *mi = &m->import_entries[i]; + uint8_t v8; if (bc_get_leb128_int(s, &mi->var_idx)) goto fail; + if (bc_get_u8(s, &v8)) + goto fail; + mi->is_star = (v8 != 0); if (bc_get_atom(s, &mi->import_name)) goto fail; if (bc_get_leb128_int(s, &mi->req_module_idx)) @@ -36609,7 +37895,7 @@ static JSValue JS_ReadModule(BCReaderState *s) return obj; fail: if (m) { - js_free_module_def(ctx, m); + JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); } return JS_EXCEPTION; } @@ -36631,12 +37917,8 @@ static JSValue JS_ReadObjectTag(BCReaderState *s) for(i = 0; i < prop_count; i++) { if (bc_get_atom(s, &atom)) goto fail; -#ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT - if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "propname: "); - print_atom(s->ctx, atom); - printf("\n"); - } +#ifdef DUMP_READ_OBJECT + bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n"); #endif val = JS_ReadObjectRec(s); if (JS_IsException(val)) { @@ -36661,7 +37943,7 @@ static JSValue JS_ReadArray(BCReaderState *s, int tag) uint32_t len, i; JSValue val; int ret, prop_flags; - bool is_template; + BOOL is_template; obj = JS_NewArray(ctx); if (BC_add_object_ref(s, obj)) @@ -36728,8 +38010,8 @@ static JSValue JS_ReadTypedArray(BCReaderState *s) return JS_EXCEPTION; } args[0] = array_buffer; - args[1] = js_int64(offset); - args[2] = js_int64(len); + args[1] = JS_NewInt64(ctx, offset); + args[2] = JS_NewInt64(ctx, len); obj = js_typed_array_constructor(ctx, JS_UNDEFINED, 3, args, JS_CLASS_UINT8C_ARRAY + array_tag); @@ -36773,7 +38055,7 @@ static JSValue JS_ReadArrayBuffer(BCReaderState *s) JS_CLASS_ARRAY_BUFFER, (uint8_t*)s->ptr, js_array_buffer_free, NULL, - /*alloc_flag*/true); + /*alloc_flag*/TRUE); if (JS_IsException(obj)) goto fail; if (BC_add_object_ref(s, obj)) @@ -36807,17 +38089,12 @@ static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) if (bc_get_u64(s, &u64)) return JS_EXCEPTION; data_ptr = (uint8_t *)(uintptr_t)u64; - if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]), - &s->sab_tab_size, s->sab_tab_len + 1)) - return JS_EXCEPTION; - /* keep the SAB pointer so that the user can clone it or free it */ - s->sab_tab[s->sab_tab_len++] = data_ptr; /* the SharedArrayBuffer is cloned */ obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length, pmax_byte_length, JS_CLASS_SHARED_ARRAY_BUFFER, data_ptr, - NULL, NULL, false); + NULL, NULL, FALSE); if (JS_IsException(obj)) goto fail; if (BC_add_object_ref(s, obj)) @@ -36828,36 +38105,6 @@ static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) return JS_EXCEPTION; } -static JSValue JS_ReadRegExp(BCReaderState *s) -{ - JSContext *ctx = s->ctx; - JSString *pattern; - JSString *bc; - - pattern = JS_ReadString(s); - if (!pattern) - return JS_EXCEPTION; - - bc = JS_ReadString(s); - if (!bc) { - js_free_string(ctx->rt, pattern); - return JS_EXCEPTION; - } - - if (bc->is_wide_char) { - js_free_string(ctx->rt, pattern); - js_free_string(ctx->rt, bc); - return JS_ThrowInternalError(ctx, "bad regexp bytecode"); - } - - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/true); - - return js_regexp_constructor_internal(ctx, JS_UNDEFINED, - JS_MKPTR(JS_TAG_STRING, pattern), - JS_MKPTR(JS_TAG_STRING, bc)); -} - static JSValue JS_ReadDate(BCReaderState *s) { JSContext *ctx = s->ctx; @@ -36905,9 +38152,6 @@ static JSValue JS_ReadObjectValue(BCReaderState *s) return JS_EXCEPTION; } -static JSValue JS_ReadMap(BCReaderState *s); -static JSValue JS_ReadSet(BCReaderState *s); - static JSValue JS_ReadObjectRec(BCReaderState *s) { JSContext *ctx = s->ctx; @@ -36920,7 +38164,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_u8(s, &tag)) return JS_EXCEPTION; - bc_read_trace(s, "%s {\n", bc_tag_name(tag)); + bc_read_trace(s, "%s {\n", bc_tag_str[tag]); switch(tag) { case BC_TAG_NULL: @@ -36931,7 +38175,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) break; case BC_TAG_BOOL_FALSE: case BC_TAG_BOOL_TRUE: - obj = js_bool(tag - BC_TAG_BOOL_FALSE); + obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE); break; case BC_TAG_INT32: { @@ -36939,7 +38183,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_sleb128(s, &val)) return JS_EXCEPTION; bc_read_trace(s, "%d\n", val); - obj = js_int32(val); + obj = JS_NewInt32(ctx, val); } break; case BC_TAG_FLOAT64: @@ -36948,7 +38192,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_u64(s, &u.u64)) return JS_EXCEPTION; bc_read_trace(s, "%g\n", u.d); - obj = js_float64(u.d); + obj = __JS_NewFloat64(ctx, u.d); } break; case BC_TAG_STRING: @@ -36962,14 +38206,12 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) break; case BC_TAG_FUNCTION_BYTECODE: if (!s->allow_bytecode) - goto no_allow_bytecode; + goto invalid_tag; obj = JS_ReadFunctionTag(s); break; case BC_TAG_MODULE: - if (!s->allow_bytecode) { - no_allow_bytecode: - return JS_ThrowSyntaxError(ctx, "no bytecode allowed"); - } + if (!s->allow_bytecode) + goto invalid_tag; obj = JS_ReadModule(s); break; case BC_TAG_OBJECT: @@ -36990,9 +38232,6 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) goto invalid_tag; obj = JS_ReadSharedArrayBuffer(s); break; - case BC_TAG_REGEXP: - obj = JS_ReadRegExp(s); - break; case BC_TAG_DATE: obj = JS_ReadDate(s); break; @@ -37014,26 +38253,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)", val, s->objects_count); } - obj = js_dup(JS_MKPTR(JS_TAG_OBJECT, s->objects[val])); - } - break; - case BC_TAG_MAP: - obj = JS_ReadMap(s); - break; - case BC_TAG_SET: - obj = JS_ReadSet(s); - break; - case BC_TAG_SYMBOL: - { - JSAtom atom; - if (bc_get_atom(s, &atom)) - return JS_EXCEPTION; - if (__JS_AtomIsConst(atom)) { - obj = JS_AtomToValue(s->ctx, atom); - } else { - JSAtomStruct *p = s->ctx->rt->atom_array[atom]; - obj = JS_NewSymbolFromAtom(s->ctx, atom, p->atom_type); - } + obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val])); } break; default: @@ -37047,7 +38267,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) static int JS_ReadObjectAtoms(BCReaderState *s) { - uint8_t v8, type; + uint8_t v8; JSString *p; int i; JSAtom atom; @@ -37061,13 +38281,8 @@ static int JS_ReadObjectAtoms(BCReaderState *s) } if (bc_get_leb128(s, &s->idx_to_atom_count)) return -1; - if (s->idx_to_atom_count > 1000*1000) { - JS_ThrowInternalError(s->ctx, "unreasonable atom count: %u", - s->idx_to_atom_count); - return -1; - } - bc_read_trace(s, "%u atom indexes {\n", s->idx_to_atom_count); + bc_read_trace(s, "%d atom indexes {\n", s->idx_to_atom_count); if (s->idx_to_atom_count != 0) { s->idx_to_atom = js_mallocz(s->ctx, s->idx_to_atom_count * @@ -37076,29 +38291,15 @@ static int JS_ReadObjectAtoms(BCReaderState *s) return s->error_state = -1; } for(i = 0; i < s->idx_to_atom_count; i++) { - if (bc_get_u8(s, &type)) { + p = JS_ReadString(s); + if (!p) return -1; - } - if (type == 0) { - if (bc_get_u32(s, &atom)) - return -1; - if (!__JS_AtomIsConst(atom)) { - JS_ThrowInternalError(s->ctx, "out of range atom"); - return -1; - } - } else { - if (type < JS_ATOM_TYPE_STRING || type >= JS_ATOM_TYPE_PRIVATE) { - JS_ThrowInternalError(s->ctx, "invalid symbol type %d", type); - return -1; - } - p = JS_ReadString(s); - if (!p) - return -1; - atom = __JS_NewAtom(s->ctx->rt, p, type); - } + atom = JS_NewAtomStr(s->ctx, p); if (atom == JS_ATOM_NULL) return s->error_state = -1; s->idx_to_atom[i] = atom; + if (s->is_rom_data && (atom != (i + s->first_atom))) + s->is_rom_data = FALSE; /* atoms must be relocated */ } bc_read_trace(s, "}\n"); return 0; @@ -37116,8 +38317,8 @@ static void bc_reader_free(BCReaderState *s) js_free(s->ctx, s->objects); } -JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags, JSSABTab *psab_tab) +JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags) { BCReaderState ss, *s = &ss; JSValue obj; @@ -37131,6 +38332,7 @@ JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, s->buf_end = buf + buf_len; s->ptr = buf; s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0); + s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0); s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0); s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0); if (s->allow_bytecode) @@ -37142,22 +38344,10 @@ JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, } else { obj = JS_ReadObjectRec(s); } - if (psab_tab) { - psab_tab->tab = s->sab_tab; - psab_tab->len = s->sab_tab_len; - } else { - js_free(ctx, s->sab_tab); - } bc_reader_free(s); return obj; } -JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags) -{ - return JS_ReadObject2(ctx, buf, buf_len, flags, NULL); -} - /*******************************************************************/ /* runtime functions & objects */ @@ -37172,7 +38362,7 @@ static int check_function(JSContext *ctx, JSValueConst obj) { if (likely(JS_IsFunction(ctx, obj))) return 0; - JS_ThrowTypeErrorNotAFunction(ctx); + JS_ThrowTypeError(ctx, "not a function"); return -1; } @@ -37182,7 +38372,6 @@ static int check_exception_free(JSContext *ctx, JSValue obj) return JS_IsException(obj); } -/* `export_name` may be pure ASCII or UTF-8 encoded */ static JSAtom find_atom(JSContext *ctx, const char *name) { JSAtom atom; @@ -37196,7 +38385,7 @@ static JSAtom find_atom(JSContext *ctx, const char *name) for(atom = JS_ATOM_Symbol_toPrimitive; atom < JS_ATOM_END; atom++) { JSAtomStruct *p = ctx->rt->atom_array[atom]; JSString *str = p; - if (str->len == len && !memcmp(str8(str), name, len)) + if (str->len == len && !memcmp(str->u.str8, name, len)) return JS_DupAtom(ctx, atom); } abort(); @@ -37206,11 +38395,25 @@ static JSAtom find_atom(JSContext *ctx, const char *name) return atom; } +static JSValue JS_NewObjectProtoList(JSContext *ctx, JSValueConst proto, + const JSCFunctionListEntry *fields, int n_fields) +{ + JSValue obj; + obj = JS_NewObjectProtoClassAlloc(ctx, proto, JS_CLASS_OBJECT, n_fields); + if (JS_IsException(obj)) + return obj; + if (JS_SetPropertyFunctionList(ctx, obj, fields, n_fields)) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + return obj; +} + static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { const JSCFunctionListEntry *e = opaque; - JSValue val; + JSValue val, proto; switch(e->def_type) { case JS_DEF_CFUNC: @@ -37221,8 +38424,13 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, val = JS_NewAtomString(ctx, e->u.str); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + /* XXX: could add a flag */ + if (atom == JS_ATOM_Symbol_unscopables) + proto = JS_NULL; + else + proto = ctx->class_proto[JS_CLASS_OBJECT]; + val = JS_NewObjectProtoList(ctx, proto, + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -37300,17 +38508,23 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, } break; case JS_DEF_PROP_INT32: - val = js_int32(e->u.i32); + val = JS_NewInt32(ctx, e->u.i32); break; case JS_DEF_PROP_INT64: - val = js_int64(e->u.i64); + val = JS_NewInt64(ctx, e->u.i64); break; case JS_DEF_PROP_DOUBLE: - val = js_float64(e->u.f64); + val = __JS_NewFloat64(ctx, e->u.f64); break; case JS_DEF_PROP_UNDEFINED: val = JS_UNDEFINED; break; + case JS_DEF_PROP_ATOM: + val = JS_AtomToValue(ctx, e->u.i32); + break; + case JS_DEF_PROP_BOOL: + val = JS_NewBool(ctx, e->u.i32); + break; case JS_DEF_PROP_STRING: case JS_DEF_OBJECT: JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP, @@ -37324,7 +38538,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, } int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, - const JSCFunctionListEntry *tab, int len) + const JSCFunctionListEntry *tab, int len) { int i, ret; @@ -37366,21 +38580,20 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, e->name, e->u.func.length, e->u.func.cproto, e->magic); break; case JS_DEF_PROP_STRING: - /* `e->u.str` may be pure ASCII or UTF-8 encoded */ val = JS_NewString(ctx, e->u.str); break; case JS_DEF_PROP_INT32: - val = js_int32(e->u.i32); + val = JS_NewInt32(ctx, e->u.i32); break; case JS_DEF_PROP_INT64: - val = js_int64(e->u.i64); + val = JS_NewInt64(ctx, e->u.i64); break; case JS_DEF_PROP_DOUBLE: - val = js_float64(e->u.f64); + val = __JS_NewFloat64(ctx, e->u.f64); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + val = JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -37392,54 +38605,107 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, } /* Note: 'func_obj' is not necessarily a constructor */ -static void JS_SetConstructor2(JSContext *ctx, - JSValueConst func_obj, - JSValueConst proto, - int proto_flags, int ctor_flags) +static int JS_SetConstructor2(JSContext *ctx, + JSValueConst func_obj, + JSValueConst proto, + int proto_flags, int ctor_flags) { - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, - js_dup(proto), proto_flags); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, - js_dup(func_obj), ctor_flags); + if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, + JS_DupValue(ctx, proto), proto_flags) < 0) + return -1; + if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, + JS_DupValue(ctx, func_obj), + ctor_flags) < 0) + return -1; + set_cycle_flag(ctx, func_obj); + set_cycle_flag(ctx, proto); + return 0; } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto) +/* return 0 if OK, -1 if exception */ +int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto) { - JS_SetConstructor2(ctx, func_obj, proto, - 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + return JS_SetConstructor2(ctx, func_obj, proto, + 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } -static void JS_NewGlobalCConstructor2(JSContext *ctx, - JSValue func_obj, - const char *name, - JSValueConst proto) -{ - JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, - js_dup(func_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_SetConstructor(ctx, func_obj, proto); - JS_FreeValue(ctx, func_obj); -} +#define JS_NEW_CTOR_NO_GLOBAL (1 << 0) /* don't create a global binding */ +#define JS_NEW_CTOR_PROTO_CLASS (1 << 1) /* the prototype class is 'class_id' instead of JS_CLASS_OBJECT */ +#define JS_NEW_CTOR_PROTO_EXIST (1 << 2) /* the prototype is already defined */ +#define JS_NEW_CTOR_READONLY (1 << 3) /* read-only constructor field */ -static JSValue JS_NewGlobalCConstructor(JSContext *ctx, const char *name, - JSCFunction *func, int length, - JSValueConst proto) +/* Return the constructor and. Define it as a global variable unless + JS_NEW_CTOR_NO_GLOBAL is set. The new class inherit from + parent_ctor if it is not JS_UNDEFINED. if class_id is != -1, + class_proto[class_id] is set. */ +static JSValue JS_NewCConstructor(JSContext *ctx, int class_id, const char *name, + JSCFunction *func, int length, JSCFunctionEnum cproto, int magic, + JSValueConst parent_ctor, + const JSCFunctionListEntry *ctor_fields, int n_ctor_fields, + const JSCFunctionListEntry *proto_fields, int n_proto_fields, + int flags) { - JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0); - JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); - return func_obj; -} + JSValue ctor = JS_UNDEFINED, proto, parent_proto; + int proto_class_id, proto_flags, ctor_flags; -static JSValue JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name, - JSCFunction *func, int length, - JSValue proto) -{ - JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0); - JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); - return func_obj; + proto_flags = 0; + if (flags & JS_NEW_CTOR_READONLY) { + ctor_flags = JS_PROP_CONFIGURABLE; + } else { + ctor_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE; + } + + if (JS_IsUndefined(parent_ctor)) { + parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]); + parent_ctor = ctx->function_proto; + } else { + parent_proto = JS_GetProperty(ctx, parent_ctor, JS_ATOM_prototype); + if (JS_IsException(parent_proto)) + return JS_EXCEPTION; + } + + if (flags & JS_NEW_CTOR_PROTO_EXIST) { + proto = JS_DupValue(ctx, ctx->class_proto[class_id]); + } else { + if (flags & JS_NEW_CTOR_PROTO_CLASS) + proto_class_id = class_id; + else + proto_class_id = JS_CLASS_OBJECT; + /* one additional field: constructor */ + proto = JS_NewObjectProtoClassAlloc(ctx, parent_proto, proto_class_id, + n_proto_fields + 1); + if (JS_IsException(proto)) + goto fail; + if (class_id >= 0) + ctx->class_proto[class_id] = JS_DupValue(ctx, proto); + } + if (JS_SetPropertyFunctionList(ctx, proto, proto_fields, n_proto_fields)) + goto fail; + + /* additional fields: name, length, prototype */ + ctor = JS_NewCFunction3(ctx, func, name, length, cproto, magic, parent_ctor, + n_ctor_fields + 3); + if (JS_IsException(ctor)) + goto fail; + if (JS_SetPropertyFunctionList(ctx, ctor, ctor_fields, n_ctor_fields)) + goto fail; + if (!(flags & JS_NEW_CTOR_NO_GLOBAL)) { + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, + JS_DupValue(ctx, ctor), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + } + JS_SetConstructor2(ctx, ctor, proto, proto_flags, ctor_flags); + + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + return ctor; + fail: + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + JS_FreeValue(ctx, ctor); + return JS_EXCEPTION; } static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val, @@ -37455,39 +38721,21 @@ static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val, if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - return js_bool(isnan(d)); + return JS_NewBool(ctx, isnan(d)); } static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - bool res; double d; if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - res = isfinite(d); - return js_bool(res); -} - -static JSValue js_microtask_job(JSContext *ctx, - int argc, JSValueConst *argv) -{ - return JS_Call(ctx, argv[0], ctx->global_obj, 0, NULL); -} - -static JSValue js_global_queueMicrotask(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - if (check_function(ctx, argv[0])) - return JS_EXCEPTION; - if (JS_EnqueueJob(ctx, js_microtask_job, 1, &argv[0])) - return JS_EXCEPTION; - return JS_UNDEFINED; + return JS_NewBool(ctx, isfinite(d)); } /* Object class */ -JSValue JS_ToObject(JSContext *ctx, JSValueConst val) +static JSValue JS_ToObject(JSContext *ctx, JSValueConst val) { int tag = JS_VALUE_GET_NORM_TAG(val); JSValue obj; @@ -37496,10 +38744,10 @@ JSValue JS_ToObject(JSContext *ctx, JSValueConst val) default: case JS_TAG_NULL: case JS_TAG_UNDEFINED: - return JS_ThrowTypeError(ctx, "Cannot convert undefined or null to object"); + return JS_ThrowTypeError(ctx, "cannot convert to object"); case JS_TAG_OBJECT: case JS_TAG_EXCEPTION: - return js_dup(val); + return JS_DupValue(ctx, val); case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT); @@ -37509,13 +38757,22 @@ JSValue JS_ToObject(JSContext *ctx, JSValueConst val) obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER); goto set_value; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: /* XXX: should call the string constructor */ { - JSString *p1 = JS_VALUE_GET_STRING(val); + JSValue str; + str = JS_ToString(ctx, val); /* ensure that we never store a rope */ + if (JS_IsException(str)) + return JS_EXCEPTION; obj = JS_NewObjectClass(ctx, JS_CLASS_STRING); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0); + if (!JS_IsException(obj)) { + JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, + JS_NewInt32(ctx, JS_VALUE_GET_STRING(str)->len), 0); + JS_SetObjectData(ctx, obj, JS_DupValue(ctx, str)); + } + JS_FreeValue(ctx, str); + return obj; } - goto set_value; case JS_TAG_BOOL: obj = JS_NewObjectClass(ctx, JS_CLASS_BOOLEAN); goto set_value; @@ -37523,7 +38780,7 @@ JSValue JS_ToObject(JSContext *ctx, JSValueConst val) obj = JS_NewObjectClass(ctx, JS_CLASS_SYMBOL); set_value: if (!JS_IsException(obj)) - JS_SetObjectData(ctx, obj, js_dup(val)); + JS_SetObjectData(ctx, obj, JS_DupValue(ctx, val)); return obj; } } @@ -37539,21 +38796,17 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, JSValueConst desc) { JSValue val, getter, setter; - int present; int flags; if (!JS_IsObject(desc)) { - JS_ThrowTypeError(ctx, "Property description must be an object"); + JS_ThrowTypeErrorNotAnObject(ctx); return -1; } flags = 0; val = JS_UNDEFINED; getter = JS_UNDEFINED; setter = JS_UNDEFINED; - present = JS_HasProperty(ctx, desc, JS_ATOM_enumerable); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) { JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable); if (JS_IsException(prop)) goto fail; @@ -37561,10 +38814,7 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, if (JS_ToBoolFree(ctx, prop)) flags |= JS_PROP_ENUMERABLE; } - present = JS_HasProperty(ctx, desc, JS_ATOM_configurable); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) { JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable); if (JS_IsException(prop)) goto fail; @@ -37572,19 +38822,13 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, if (JS_ToBoolFree(ctx, prop)) flags |= JS_PROP_CONFIGURABLE; } - present = JS_HasProperty(ctx, desc, JS_ATOM_value); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_value)) { flags |= JS_PROP_HAS_VALUE; val = JS_GetProperty(ctx, desc, JS_ATOM_value); if (JS_IsException(val)) goto fail; } - present = JS_HasProperty(ctx, desc, JS_ATOM_writable); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) { JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable); if (JS_IsException(prop)) goto fail; @@ -37592,33 +38836,27 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, if (JS_ToBoolFree(ctx, prop)) flags |= JS_PROP_WRITABLE; } - present = JS_HasProperty(ctx, desc, JS_ATOM_get); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_get)) { flags |= JS_PROP_HAS_GET; getter = JS_GetProperty(ctx, desc, JS_ATOM_get); if (JS_IsException(getter) || !(JS_IsUndefined(getter) || JS_IsFunction(ctx, getter))) { - JS_ThrowTypeError(ctx, "Getter must be a function"); + JS_ThrowTypeError(ctx, "invalid getter"); goto fail; } } - present = JS_HasProperty(ctx, desc, JS_ATOM_set); - if (present < 0) - goto fail; - if (present) { + if (JS_HasProperty(ctx, desc, JS_ATOM_set)) { flags |= JS_PROP_HAS_SET; setter = JS_GetProperty(ctx, desc, JS_ATOM_set); if (JS_IsException(setter) || !(JS_IsUndefined(setter) || JS_IsFunction(ctx, setter))) { - JS_ThrowTypeError(ctx, "Setter must be a function"); + JS_ThrowTypeError(ctx, "invalid setter"); goto fail; } } if ((flags & (JS_PROP_HAS_SET | JS_PROP_HAS_GET)) && (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE))) { - JS_ThrowTypeError(ctx, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute"); + JS_ThrowTypeError(ctx, "cannot have setter/getter and value or writable"); goto fail; } d->flags = flags; @@ -37660,7 +38898,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, int ret = -1; if (!JS_IsObject(obj)) { - JS_ThrowTypeError(ctx, "Object.defineProperties called on non-object"); + JS_ThrowTypeErrorNotAnObject(ctx); return -1; } desc = JS_UNDEFINED; @@ -37668,24 +38906,21 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, if (JS_IsException(props)) return -1; p = JS_VALUE_GET_OBJ(props); + /* XXX: not done in the same order as the spec */ if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0) goto exception; - // XXX: ECMA specifies that all descriptions should be validated before - // modifying the object. This would require allocating an array - // JSPropertyDescriptor and use 2 separate loops. for(i = 0; i < len; i++) { JS_FreeValue(ctx, desc); desc = JS_GetProperty(ctx, props, atoms[i].atom); if (JS_IsException(desc)) goto exception; - if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, - JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY) < 0) + if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, JS_PROP_THROW) < 0) goto exception; } ret = 0; exception: - js_free_prop_enum(ctx, atoms, len); + JS_FreePropertyEnum(ctx, atoms, len); JS_FreeValue(ctx, props); JS_FreeValue(ctx, desc); return ret; @@ -37722,7 +38957,7 @@ static JSValue js_object_create(JSContext *ctx, JSValueConst this_val, proto = argv[0]; if (!JS_IsObject(proto) && !JS_IsNull(proto)) - return JS_ThrowTypeError(ctx, "object prototype may only be an Object or null"); + return JS_ThrowTypeError(ctx, "not a prototype"); obj = JS_NewObjectProto(ctx, proto); if (JS_IsException(obj)) return JS_EXCEPTION; @@ -37739,7 +38974,9 @@ static JSValue js_object_create(JSContext *ctx, JSValueConst this_val, static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { - JSValueConst val = argv[0]; + JSValueConst val; + + val = argv[0]; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) { /* ES6 feature non compatible with ES5.1: primitive types are accepted */ @@ -37753,10 +38990,11 @@ static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValueConst obj = argv[0]; - if (JS_SetPrototypeInternal(ctx, obj, argv[1], true) < 0) + JSValueConst obj; + obj = argv[0]; + if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0) return JS_EXCEPTION; - return js_dup(obj); + return JS_DupValue(ctx, obj); } /* magic = 1 if called as Reflect.defineProperty */ @@ -37776,17 +39014,17 @@ static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; - flags = JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY; - if (magic) - flags = JS_PROP_REFLECT_DEFINE_PROPERTY; + flags = 0; + if (!magic) + flags |= JS_PROP_THROW; ret = JS_DefinePropertyDesc(ctx, obj, atom, desc, flags); JS_FreeAtom(ctx, atom); if (ret < 0) { return JS_EXCEPTION; } else if (magic) { - return js_bool(ret); + return JS_NewBool(ctx, ret); } else { - return js_dup(obj); + return JS_DupValue(ctx, obj); } } @@ -37795,9 +39033,11 @@ static JSValue js_object_defineProperties(JSContext *ctx, JSValueConst this_val, { // defineProperties(obj, properties) JSValueConst obj = argv[0]; + if (JS_ObjectDefineProperties(ctx, obj, argv[1])) return JS_EXCEPTION; - return js_dup(obj); + else + return JS_DupValue(ctx, obj); } /* magic = 1 if called as __defineSetter__ */ @@ -37860,7 +39100,7 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t /* Reflect.getOwnPropertyDescriptor case */ if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - obj = js_dup(argv[0]); + obj = JS_DupValue(ctx, argv[0]); } else { obj = JS_ToObject(ctx, argv[0]); if (JS_IsException(obj)) @@ -37881,22 +39121,19 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t goto exception1; flags = JS_PROP_C_W_E | JS_PROP_THROW; if (desc.flags & JS_PROP_GETSET) { - if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(desc.getter), flags) < 0 - || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(desc.setter), flags) < 0) + if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, desc.getter), flags) < 0 + || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, desc.setter), flags) < 0) goto exception1; } else { - if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(desc.value), flags) < 0 + if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - js_bool(desc.flags & JS_PROP_WRITABLE), - flags) < 0) + JS_NewBool(ctx, desc.flags & JS_PROP_WRITABLE), flags) < 0) goto exception1; } if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - js_bool(desc.flags & JS_PROP_ENUMERABLE), - flags) < 0 + JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE), flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - js_bool(desc.flags & JS_PROP_CONFIGURABLE), - flags) < 0) + JS_NewBool(ctx, desc.flags & JS_PROP_CONFIGURABLE), flags) < 0) goto exception1; js_free_desc(ctx, &desc); } @@ -37954,12 +39191,12 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst goto exception; } } - js_free_prop_enum(ctx, props, len); + JS_FreePropertyEnum(ctx, props, len); JS_FreeValue(ctx, obj); return r; exception: - js_free_prop_enum(ctx, props, len); + JS_FreePropertyEnum(ctx, props, len); JS_FreeValue(ctx, obj); JS_FreeValue(ctx, r); return JS_EXCEPTION; @@ -38039,7 +39276,7 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, JS_FreeValue(ctx, r); r = JS_EXCEPTION; done: - js_free_prop_enum(ctx, atoms, len); + JS_FreePropertyEnum(ctx, atoms, len); JS_FreeValue(ctx, obj); return r; } @@ -38058,96 +39295,6 @@ static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValueConst this JS_GPN_SYMBOL_MASK, JS_ITERATOR_KIND_KEY); } -static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue res, iter, next, groups, k, v, prop; - JSValueConst cb, args[2]; - int64_t idx; - int done; - - // "is function?" check must be observed before argv[0] is accessed - cb = argv[1]; - if (check_function(ctx, cb)) - return JS_EXCEPTION; - - // TODO(bnoordhuis) add fast path for arrays but as groupBy() is - // defined in terms of iterators, the fast path must check that - // this[Symbol.iterator] is the built-in array iterator - iter = JS_GetIterator(ctx, argv[0], /*is_async*/false); - if (JS_IsException(iter)) - return JS_EXCEPTION; - - k = JS_UNDEFINED; - v = JS_UNDEFINED; - prop = JS_UNDEFINED; - groups = JS_UNDEFINED; - - next = JS_GetProperty(ctx, iter, JS_ATOM_next); - if (JS_IsException(next)) - goto exception; - - groups = JS_NewObjectProto(ctx, JS_NULL); - if (JS_IsException(groups)) - goto exception; - - for (idx = 0; ; idx++) { - v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); - if (JS_IsException(v)) - goto exception; - if (done) - break; // v is JS_UNDEFINED - - args[0] = v; - args[1] = js_int64(idx); - k = JS_Call(ctx, cb, ctx->global_obj, 2, args); - if (JS_IsException(k)) - goto exception; - - k = js_dup(k); - prop = JS_GetPropertyValue(ctx, groups, k); - if (JS_IsException(prop)) - goto exception; - - if (JS_IsUndefined(prop)) { - prop = JS_NewArray(ctx); - if (JS_IsException(prop)) - goto exception; - k = js_dup(k); - prop = js_dup(prop); - if (JS_SetPropertyValue(ctx, groups, k, prop, - JS_PROP_C_W_E|JS_PROP_THROW) < 0) { - goto exception; - } - } - - res = js_array_push(ctx, prop, 1, vc(&v), /*unshift*/0); - if (JS_IsException(res)) - goto exception; - // res is an int64 - - JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, k); - JS_FreeValue(ctx, v); - prop = JS_UNDEFINED; - k = JS_UNDEFINED; - v = JS_UNDEFINED; - } - - JS_FreeValue(ctx, iter); - JS_FreeValue(ctx, next); - return groups; - -exception: - JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, k); - JS_FreeValue(ctx, v); - JS_FreeValue(ctx, groups); - JS_FreeValue(ctx, iter); - JS_FreeValue(ctx, next); - return JS_EXCEPTION; -} - static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int kind) { @@ -38172,7 +39319,7 @@ static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val, @@ -38186,17 +39333,17 @@ static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val if (reflect) return JS_ThrowTypeErrorNotAnObject(ctx); else - return js_dup(obj); + return JS_DupValue(ctx, obj); } ret = JS_PreventExtensions(ctx, obj); if (ret < 0) return JS_EXCEPTION; if (reflect) { - return js_bool(ret); + return JS_NewBool(ctx, ret); } else { if (!ret) return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); - return js_dup(obj); + return JS_DupValue(ctx, obj); } } @@ -38206,7 +39353,7 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, JSValue obj; JSAtom atom; JSObject *p; - int ret; + BOOL ret; atom = JS_ValueToAtom(ctx, argv[0]); /* must be done first */ if (unlikely(atom == JS_ATOM_NULL)) @@ -38223,7 +39370,7 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val, @@ -38232,7 +39379,7 @@ static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val, JSValue obj; JSAtom atom; JSObject *p; - int ret; + BOOL ret; obj = JS_ToObject(ctx, argv[0]); if (JS_IsException(obj)) @@ -38249,7 +39396,7 @@ static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val, @@ -38274,7 +39421,7 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val, obj = JS_ToObject(ctx, this_val); if (JS_IsException(obj)) return obj; - is_array = js_is_array(ctx, obj); + is_array = JS_IsArray(ctx, obj); if (is_array < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -38313,11 +39460,6 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val, return JS_ConcatString3(ctx, "[object ", tag, "]"); } -JSValue JS_ToObjectString(JSContext *ctx, JSValueConst val) -{ - return js_object_toString(ctx, val, 0, NULL); -} - static JSValue js_object_toLocaleString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -38340,7 +39482,7 @@ static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val, s = JS_ToObject(ctx, argv[i]); if (JS_IsException(s)) goto exception; - if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, true)) + if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, TRUE)) goto exception; JS_FreeValue(ctx, s); } @@ -38357,20 +39499,12 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, { JSValueConst obj = argv[0]; JSObject *p; - JSTypedArray *ta; - JSArrayBuffer *abuf; JSPropertyEnum *props; uint32_t len, i; int flags, desc_flags, res; if (!JS_IsObject(obj)) - return js_dup(obj); - - p = JS_VALUE_GET_OBJ(obj); - if (p->class_id == JS_CLASS_MODULE_NS) { - return JS_ThrowTypeError(ctx, "cannot %s module namespace", - freeze_flag ? "freeze" : "seal"); - } + return JS_DupValue(ctx, obj); res = JS_PreventExtensions(ctx, obj); if (res < 0) @@ -38379,13 +39513,7 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); } - if (freeze_flag && is_typed_array(p->class_id)) { - ta = p->u.typed_array; - abuf = ta->buffer->u.array_buffer; - if (array_buffer_is_resizable(abuf) || typed_array_is_oob(p)) - return JS_ThrowTypeError(ctx, "cannot freeze resizable typed array"); - } - + p = JS_VALUE_GET_OBJ(obj); flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK; if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags)) return JS_EXCEPTION; @@ -38409,11 +39537,11 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, JS_UNDEFINED, JS_UNDEFINED, desc_flags) < 0) goto exception; } - js_free_prop_enum(ctx, props, len); - return js_dup(obj); + JS_FreePropertyEnum(ctx, props, len); + return JS_DupValue(ctx, obj); exception: - js_free_prop_enum(ctx, props, len); + JS_FreePropertyEnum(ctx, props, len); return JS_EXCEPTION; } @@ -38445,7 +39573,7 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, js_free_desc(ctx, &desc); if ((desc.flags & JS_PROP_CONFIGURABLE) || (is_frozen && (desc.flags & JS_PROP_WRITABLE))) { - res = false; + res = FALSE; goto done; } } @@ -38455,36 +39583,20 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; res ^= 1; done: - js_free_prop_enum(ctx, props, len); - return js_bool(res); + JS_FreePropertyEnum(ctx, props, len); + return JS_NewBool(ctx, res); exception: - js_free_prop_enum(ctx, props, len); + JS_FreePropertyEnum(ctx, props, len); return JS_EXCEPTION; } -int JS_SealObject(JSContext *ctx, JSValueConst obj) -{ - JSValue value = js_object_seal(ctx, JS_UNDEFINED, 1, &obj, 0); - int result = JS_IsException(value) ? -1 : true; - JS_FreeValue(ctx, value); - return result; -} - -int JS_FreezeObject(JSContext *ctx, JSValueConst obj) -{ - JSValue value = js_object_seal(ctx, JS_UNDEFINED, 1, &obj, 1); - int result = JS_IsException(value) ? -1 : true; - JS_FreeValue(ctx, value); - return result; -} - static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue obj, iter, next_method = JS_UNDEFINED; JSValueConst iterable; - int done; + BOOL done; /* RequireObjectCoercible() not necessary because it is tested in JS_GetIterator() by JS_GetProperty() */ @@ -38494,7 +39606,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, if (JS_IsException(obj)) return obj; - iter = JS_GetIterator(ctx, iterable, false); + iter = JS_GetIterator(ctx, iterable, FALSE); if (JS_IsException(iter)) goto fail; next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); @@ -38537,7 +39649,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, fail: if (JS_IsObject(iter)) { /* close the iterator object, preserving pending exception */ - JS_IteratorClose(ctx, iter, true); + JS_IteratorClose(ctx, iter, TRUE); } JS_FreeValue(ctx, next_method); JS_FreeValue(ctx, iter); @@ -38548,7 +39660,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, static JSValue js_object_is(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - return js_bool(js_same_value(ctx, argv[0], argv[1])); + return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1])); } static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, @@ -38562,7 +39674,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, if (JS_IsException(ctor)) return ctor; if (JS_IsUndefined(ctor)) - return js_dup(defaultConstructor); + return JS_DupValue(ctx, defaultConstructor); if (!JS_IsObject(ctor)) { JS_FreeValue(ctx, ctor); return JS_ThrowTypeErrorNotAnObject(ctx); @@ -38572,7 +39684,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, if (JS_IsException(species)) return species; if (JS_IsUndefined(species) || JS_IsNull(species)) - return js_dup(defaultConstructor); + return JS_DupValue(ctx, defaultConstructor); if (!JS_IsConstructor(ctx, species)) { JS_FreeValue(ctx, species); return JS_ThrowTypeError(ctx, "not a constructor"); @@ -38599,7 +39711,7 @@ static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeErrorNotAnObject(ctx); if (!JS_IsObject(proto) && !JS_IsNull(proto)) return JS_UNDEFINED; - if (JS_SetPrototypeInternal(ctx, this_val, proto, true) < 0) + if (JS_SetPrototypeInternal(ctx, this_val, proto, TRUE) < 0) return JS_EXCEPTION; else return JS_UNDEFINED; @@ -38618,17 +39730,17 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, obj = JS_ToObject(ctx, this_val); if (JS_IsException(obj)) return JS_EXCEPTION; - v1 = js_dup(v); + v1 = JS_DupValue(ctx, v); for(;;) { v1 = JS_GetPrototypeFree(ctx, v1); if (JS_IsException(v1)) goto exception; if (JS_IsNull(v1)) { - res = false; + res = FALSE; break; } if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) { - res = true; + res = TRUE; break; } /* avoid infinite loop (possible with proxies) */ @@ -38637,7 +39749,7 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, v1); JS_FreeValue(ctx, obj); - return js_bool(res); + return JS_NewBool(ctx, res); exception: JS_FreeValue(ctx, v1); @@ -38648,23 +39760,23 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue obj, res = JS_EXCEPTION; - JSAtom prop = JS_ATOM_NULL; + JSValue obj = JS_UNDEFINED, res = JS_EXCEPTION; + JSAtom prop; JSPropertyDescriptor desc; int has_prop; - obj = JS_ToObject(ctx, this_val); - if (JS_IsException(obj)) - goto exception; prop = JS_ValueToAtom(ctx, argv[0]); if (unlikely(prop == JS_ATOM_NULL)) goto exception; + obj = JS_ToObject(ctx, this_val); + if (JS_IsException(obj)) + goto exception; has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop); if (has_prop < 0) goto exception; if (has_prop) { - res = js_bool(desc.flags & JS_PROP_ENUMERABLE); + res = JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE); js_free_desc(ctx, &desc); } else { res = JS_FALSE; @@ -38697,7 +39809,7 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, goto exception; if (has_prop) { if (desc.flags & JS_PROP_GETSET) - res = js_dup(setter ? desc.setter : desc.getter); + res = JS_DupValue(ctx, setter ? desc.setter : desc.getter); else res = JS_UNDEFINED; js_free_desc(ctx, &desc); @@ -38729,7 +39841,7 @@ static const JSCFunctionListEntry js_object_funcs[] = { JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ), JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ), JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ), - JS_CFUNC_DEF("groupBy", 2, js_object_groupBy ), + JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 0 ), JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ), JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ), JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ), @@ -38824,9 +39936,9 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, realm = JS_GetFunctionRealm(ctx, new_target); if (!realm) goto fail1; - proto = js_dup(realm->class_proto[func_kind_to_class_id[func_kind]]); + proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]); } - ret = JS_SetPrototypeInternal(ctx, obj, proto, true); + ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE); JS_FreeValue(ctx, proto); if (ret < 0) goto fail1; @@ -38864,12 +39976,6 @@ static __exception int js_get_length64(JSContext *ctx, int64_t *pres, return JS_ToLengthFree(ctx, pres, len_val); } -static __exception int js_set_length64(JSContext *ctx, JSValueConst obj, - int64_t len) -{ - return JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(len)); -} - static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len) { uint32_t i; @@ -38884,6 +39990,7 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, JSValueConst array_arg) { uint32_t len, i; + int64_t len64; JSValue *tab, ret; JSObject *p; @@ -38891,14 +39998,15 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, JS_ThrowTypeError(ctx, "not a object"); return NULL; } - if (js_get_length32(ctx, &len, array_arg)) + if (js_get_length64(ctx, &len64, array_arg)) return NULL; - if (len > JS_MAX_LOCAL_VARS) { + if (len64 > JS_MAX_LOCAL_VARS) { // XXX: check for stack overflow? JS_ThrowRangeError(ctx, "too many arguments in function call (only %d allowed)", JS_MAX_LOCAL_VARS); return NULL; } + len = len64; /* avoid allocating 0 bytes */ tab = js_mallocz(ctx, sizeof(tab[0]) * max_uint32(1, len)); if (!tab) @@ -38908,7 +40016,7 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, p->fast_array && len == p->u.array.count) { for(i = 0; i < len; i++) { - tab[i] = js_dup(p->u.array.u.values[i]); + tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]); } } else { for(i = 0; i < len; i++) { @@ -38945,9 +40053,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, if (!tab) return JS_EXCEPTION; if (magic & 1) { - ret = JS_CallConstructor2(ctx, this_val, this_arg, len, vc(tab)); + ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab); } else { - ret = JS_Call(ctx, this_val, this_arg, len, vc(tab)); + ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab); } free_arg_list(ctx, tab, len); return ret; @@ -38984,11 +40092,11 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, bf = js_malloc(ctx, sizeof(*bf) + arg_count * sizeof(JSValue)); if (!bf) goto exception; - bf->func_obj = js_dup(this_val); - bf->this_val = js_dup(argv[0]); + bf->func_obj = JS_DupValue(ctx, this_val); + bf->this_val = JS_DupValue(ctx, argv[0]); bf->argc = arg_count; for(i = 0; i < arg_count; i++) { - bf->argv[i] = js_dup(argv[i + 1]); + bf->argv[i] = JS_DupValue(ctx, argv[i + 1]); } p->u.bound_function = bf; @@ -38997,7 +40105,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, if (ret < 0) goto exception; if (!ret) { - len_val = js_int32(0); + len_val = JS_NewInt32(ctx, 0); } else { len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length); if (JS_IsException(len_val)) @@ -39009,7 +40117,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, len1 = 0; else len1 -= arg_count; - len_val = js_int32(len1); + len_val = JS_NewInt32(ctx, len1); } else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) { double d = JS_VALUE_GET_FLOAT64(len_val); if (isnan(d)) { @@ -39021,10 +40129,10 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, else d -= (double)arg_count; /* also converts -0 to +0 */ } - len_val = js_number(d); + len_val = JS_NewFloat64(ctx, d); } else { JS_FreeValue(ctx, len_val); - len_val = js_int32(0); + len_val = JS_NewInt32(ctx, 0); } } JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, @@ -39035,7 +40143,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, goto exception; if (!JS_IsString(name1)) { JS_FreeValue(ctx, name1); - name1 = js_empty_string(ctx->rt); + name1 = JS_AtomToString(ctx, JS_ATOM_empty_string); } name1 = JS_ConcatString3(ctx, "bound ", name1, ""); if (JS_IsException(name1)) @@ -39060,9 +40168,10 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_OBJ(this_val); if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; - /* `b->source` must be pure ASCII or UTF-8 encoded */ - if (b->source) - return JS_NewStringLen(ctx, b->source, b->source_len); + if (b->has_debug && b->debug.source) { + return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len); + } + func_kind = b->func_kind; } { JSValue name; @@ -39086,7 +40195,7 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, suff = "() {\n [native code]\n}"; name = JS_GetProperty(ctx, this_val, JS_ATOM_name); if (JS_IsUndefined(name)) - name = js_empty_string(ctx->rt); + name = JS_AtomToString(ctx, JS_ATOM_empty_string); return JS_ConcatString3(ctx, pref, name, suff); } } @@ -39099,7 +40208,7 @@ static JSValue js_function_hasInstance(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static const JSCFunctionListEntry js_function_proto_funcs[] = { @@ -39109,10 +40218,8 @@ static const JSCFunctionListEntry js_function_proto_funcs[] = { JS_CFUNC_DEF("toString", 0, js_function_toString ), JS_CFUNC_DEF("[Symbol.hasInstance]", 1, js_function_hasInstance ), JS_CGETSET_DEF("fileName", js_function_proto_fileName, NULL ), - JS_CGETSET_MAGIC_DEF("lineNumber", js_function_proto_int32, NULL, - offsetof(JSFunctionBytecode, line_num)), - JS_CGETSET_MAGIC_DEF("columnNumber", js_function_proto_int32, NULL, - offsetof(JSFunctionBytecode, col_num)), + JS_CGETSET_MAGIC_DEF("lineNumber", js_function_proto_lineNumber, NULL, 0 ), + JS_CGETSET_MAGIC_DEF("columnNumber", js_function_proto_lineNumber, NULL, 1 ), }; /* Error class */ @@ -39122,9 +40229,9 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) JSValue iter, next_method = JS_UNDEFINED; JSValue v, r = JS_UNDEFINED; int64_t k; - int done; + BOOL done; - iter = JS_GetIterator(ctx, items, false); + iter = JS_GetIterator(ctx, items, FALSE); if (JS_IsException(iter)) goto exception; next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); @@ -39148,7 +40255,7 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) JS_FreeValue(ctx, iter); return r; exception_close: - JS_IteratorClose(ctx, iter, true); + JS_IteratorClose(ctx, iter, TRUE); exception: JS_FreeValue(ctx, r); r = JS_EXCEPTION; @@ -39158,9 +40265,9 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic) { - JSValue obj, msg, proto, cause; - JSValueConst message; - int present, opts; + JSValue obj, msg, proto; + JSValueConst message, options; + int arg_index; if (JS_IsUndefined(new_target)) new_target = JS_GetActiveFunction(ctx); @@ -39169,7 +40276,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, return proto; if (!JS_IsObject(proto)) { JSContext *realm; - JSValue proto1; + JSValueConst proto1; JS_FreeValue(ctx, proto); realm = JS_GetFunctionRealm(ctx, new_target); @@ -39180,20 +40287,15 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, } else { proto1 = realm->native_error_proto[magic]; } - proto = js_dup(proto1); + proto = JS_DupValue(ctx, proto1); } obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR); JS_FreeValue(ctx, proto); if (JS_IsException(obj)) return obj; - if (magic == JS_AGGREGATE_ERROR) { - message = argv[1]; - opts = 2; - } else { - message = argv[0]; - opts = 1; - } + arg_index = (magic == JS_AGGREGATE_ERROR); + message = argv[arg_index++]; if (!JS_IsUndefined(message)) { msg = JS_ToString(ctx, message); if (unlikely(JS_IsException(msg))) @@ -39202,16 +40304,19 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } - if (argc > opts && JS_VALUE_GET_TAG(argv[opts]) == JS_TAG_OBJECT) { - present = JS_HasProperty(ctx, argv[opts], JS_ATOM_cause); - if (unlikely(present < 0)) - goto exception; - if (present) { - cause = JS_GetProperty(ctx, argv[opts], JS_ATOM_cause); - if (unlikely(JS_IsException(cause))) + if (arg_index < argc) { + options = argv[arg_index]; + if (JS_IsObject(options)) { + int present = JS_HasProperty(ctx, options, JS_ATOM_cause); + if (present < 0) goto exception; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (present) { + JSValue cause = JS_GetProperty(ctx, options, JS_ATOM_cause); + if (JS_IsException(cause)) + goto exception; + JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + } } } @@ -39224,7 +40329,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, } /* skip the Error() function in the backtrace */ - build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); + build_backtrace(ctx, obj, NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); return obj; exception: JS_FreeValue(ctx, obj); @@ -39248,7 +40353,7 @@ static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, msg = JS_GetProperty(ctx, this_val, JS_ATOM_message); if (JS_IsUndefined(msg)) - msg = js_empty_string(ctx->rt); + msg = JS_AtomToString(ctx, JS_ATOM_empty_string); else msg = JS_ToStringFree(ctx, msg); if (JS_IsException(msg)) { @@ -39266,66 +40371,33 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = { JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; +/* 2 entries for each native error class */ +/* Note: we use an atom to avoid the autoinit definition which does + not work in get_prop_string() */ +static const JSCFunctionListEntry js_native_error_proto_funcs[] = { +#define DEF(name) \ + JS_PROP_ATOM_DEF("name", name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),\ + JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), + + DEF(JS_ATOM_EvalError) + DEF(JS_ATOM_RangeError) + DEF(JS_ATOM_ReferenceError) + DEF(JS_ATOM_SyntaxError) + DEF(JS_ATOM_TypeError) + DEF(JS_ATOM_URIError) + DEF(JS_ATOM_InternalError) + DEF(JS_ATOM_AggregateError) +#undef DEF +}; + static JSValue js_error_isError(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - return js_bool(JS_IsError(ctx, argv[0])); -} - -static JSValue js_error_get_stackTraceLimit(JSContext *ctx, JSValueConst this_val) -{ - JSValue val; - - val = JS_ToObject(ctx, this_val); - if (JS_IsException(val)) - return val; - JS_FreeValue(ctx, val); - return js_dup(ctx->error_stack_trace_limit); -} - -static JSValue js_error_set_stackTraceLimit(JSContext *ctx, JSValueConst this_val, JSValueConst value) -{ - if (JS_IsUndefined(this_val) || JS_IsNull(this_val)) - return JS_ThrowTypeErrorNotAnObject(ctx); - ctx->error_stack_trace_limit = js_dup(value); - return JS_UNDEFINED; -} - -static JSValue js_error_get_prepareStackTrace(JSContext *ctx, JSValueConst this_val) -{ - JSValue val; - - val = JS_ToObject(ctx, this_val); - if (JS_IsException(val)) - return val; - JS_FreeValue(ctx, val); - return js_dup(ctx->error_prepare_stack); -} - -static JSValue js_error_set_prepareStackTrace(JSContext *ctx, JSValueConst this_val, JSValueConst value) -{ - if (JS_IsUndefined(this_val) || JS_IsNull(this_val)) - return JS_ThrowTypeErrorNotAnObject(ctx); - JS_FreeValue(ctx, ctx->error_prepare_stack); - ctx->error_prepare_stack = js_dup(value); - return JS_UNDEFINED; -} - -static JSValue js_error_capture_stack_trace(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst v = argv[0]; - if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) - return JS_ThrowTypeErrorNotAnObject(ctx); - build_backtrace(ctx, v, argv[1], NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL|JS_BACKTRACE_FLAG_FILTER_FUNC); - return JS_UNDEFINED; + return JS_NewBool(ctx, JS_IsError(ctx, argv[0])); } static const JSCFunctionListEntry js_error_funcs[] = { - JS_CFUNC_DEF("isError", 1, js_error_isError ), - JS_CFUNC_DEF("captureStackTrace", 2, js_error_capture_stack_trace), - JS_CGETSET_DEF("stackTraceLimit", js_error_get_stackTraceLimit, js_error_set_stackTraceLimit ), - JS_CGETSET_DEF("prepareStackTrace", js_error_get_prepareStackTrace, js_error_set_prepareStackTrace ), + JS_CFUNC_DEF("isError", 1, js_error_isError), }; /* AggregateError */ @@ -39341,7 +40413,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx, JS_CLASS_ERROR); if (JS_IsException(obj)) return obj; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, js_dup(errors), + JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); return obj; } @@ -39349,7 +40421,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx, /* Array */ static int JS_CopySubArray(JSContext *ctx, - JSValue obj, int64_t to_pos, + JSValueConst obj, int64_t to_pos, int64_t from_pos, int64_t count, int dir) { JSObject *p; @@ -39386,14 +40458,14 @@ static int JS_CopySubArray(JSContext *ctx, l = min_int64(l, to + 1); for(j = 0; j < l; j++) { set_value(ctx, &p->u.array.u.values[to - j], - js_dup(p->u.array.u.values[from - j])); + JS_DupValue(ctx, p->u.array.u.values[from - j])); } } else { l = min_int64(l, len - from); l = min_int64(l, len - to); for(j = 0; j < l; j++) { set_value(ctx, &p->u.array.u.values[to + j], - js_dup(p->u.array.u.values[from + j])); + JS_DupValue(ctx, p->u.array.u.values[from + j])); } } i += l; @@ -39429,13 +40501,13 @@ static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target, return obj; if (argc == 1 && JS_IsNumber(argv[0])) { uint32_t len; - if (JS_ToArrayLengthFree(ctx, &len, js_dup(argv[0]), true)) + if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]), TRUE)) goto fail; - if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(len)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0) goto fail; } else { for(i = 0; i < argc; i++) { - if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0) + if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0) goto fail; } } @@ -39451,18 +40523,18 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, // from(items, mapfn = void 0, this_arg = void 0) JSValueConst items = argv[0], mapfn, this_arg; JSValueConst args[2]; - JSValue stack[2]; - JSValue iter, r, v, v2, arrayLike; + JSValue iter, r, v, v2, arrayLike, next_method, enum_obj; int64_t k, len; int done, mapping; - mapping = false; + mapping = FALSE; mapfn = JS_UNDEFINED; this_arg = JS_UNDEFINED; r = JS_UNDEFINED; arrayLike = JS_UNDEFINED; - stack[0] = JS_UNDEFINED; - stack[1] = JS_UNDEFINED; + iter = JS_UNDEFINED; + enum_obj = JS_UNDEFINED; + next_method = JS_UNDEFINED; if (argc > 1) { mapfn = argv[1]; @@ -39477,26 +40549,32 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator); if (JS_IsException(iter)) goto exception; - if (!JS_IsUndefined(iter)) { - JS_FreeValue(ctx, iter); + if (!JS_IsUndefined(iter) && !JS_IsNull(iter)) { + if (!JS_IsFunction(ctx, iter)) { + JS_ThrowTypeError(ctx, "value is not iterable"); + goto exception; + } if (JS_IsConstructor(ctx, this_val)) r = JS_CallConstructor(ctx, this_val, 0, NULL); else r = JS_NewArray(ctx); if (JS_IsException(r)) goto exception; - stack[0] = js_dup(items); - if (js_for_of_start(ctx, &stack[1], false)) + enum_obj = JS_GetIterator2(ctx, items, iter); + if (JS_IsException(enum_obj)) + goto exception; + next_method = JS_GetProperty(ctx, enum_obj, JS_ATOM_next); + if (JS_IsException(next_method)) goto exception; for (k = 0;; k++) { - v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done); + v = JS_IteratorNext(ctx, enum_obj, next_method, 0, NULL, &done); if (JS_IsException(v)) - goto exception_close; + goto exception; if (done) break; if (mapping) { args[0] = v; - args[1] = js_int32(k); + args[1] = JS_NewInt32(ctx, k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -39513,7 +40591,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, goto exception; if (js_get_length64(ctx, &len, arrayLike) < 0) goto exception; - v = js_int64(len); + v = JS_NewInt64(ctx, len); args[0] = v; if (JS_IsConstructor(ctx, this_val)) { r = JS_CallConstructor(ctx, this_val, 1, args); @@ -39529,7 +40607,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, goto exception; if (mapping) { args[0] = v; - args[1] = js_int32(k); + args[1] = JS_NewInt32(ctx, k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -39541,44 +40619,44 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, r, JS_ATOM_length, js_uint32(k)) < 0) + if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0) goto exception; goto done; exception_close: - if (!JS_IsUndefined(stack[0])) - JS_IteratorClose(ctx, stack[0], true); + JS_IteratorClose(ctx, enum_obj, TRUE); exception: JS_FreeValue(ctx, r); r = JS_EXCEPTION; done: JS_FreeValue(ctx, arrayLike); - JS_FreeValue(ctx, stack[0]); - JS_FreeValue(ctx, stack[1]); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, enum_obj); + JS_FreeValue(ctx, next_method); return r; } static JSValue js_array_of(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue n, obj; + JSValue obj, args[1]; int i; if (JS_IsConstructor(ctx, this_val)) { - n = js_int32(argc); - obj = JS_CallConstructor(ctx, this_val, 1, vc(&n)); + args[0] = JS_NewInt32(ctx, argc); + obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args); } else { obj = JS_NewArray(ctx); } if (JS_IsException(obj)) return JS_EXCEPTION; for(i = 0; i < argc; i++) { - if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(argv[i]), + if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i]), JS_PROP_THROW) < 0) { goto fail; } } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(argc)) < 0) { + if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) { fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -39590,16 +40668,17 @@ static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { int ret; - ret = js_is_array(ctx, argv[0]); + ret = JS_IsArray(ctx, argv[0]); if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } -static JSValue js_get_this(JSContext *ctx, JSValueConst this_val) +static JSValue js_get_this(JSContext *ctx, + JSValueConst this_val) { - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj, @@ -39609,7 +40688,7 @@ static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj, int res; JSContext *realm; - res = js_is_array(ctx, obj); + res = JS_IsArray(ctx, obj); if (res < 0) return JS_EXCEPTION; if (!res) @@ -39660,13 +40739,13 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj) JSValue val; if (!JS_IsObject(obj)) - return false; + return FALSE; val = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_isConcatSpreadable); if (JS_IsException(val)) return -1; if (!JS_IsUndefined(val)) return JS_ToBoolFree(ctx, val); - return js_is_array(ctx, obj); + return JS_IsArray(ctx, obj); } static JSValue js_array_at(JSContext *ctx, JSValueConst this_val, @@ -39674,8 +40753,9 @@ static JSValue js_array_at(JSContext *ctx, JSValueConst this_val, { JSValue obj, ret; int64_t len, idx; + JSValue *arrp; + uint32_t count; - ret = JS_EXCEPTION; obj = JS_ToObject(ctx, this_val); if (js_get_length64(ctx, &len, obj)) goto exception; @@ -39685,16 +40765,22 @@ static JSValue js_array_at(JSContext *ctx, JSValueConst this_val, if (idx < 0) idx = len + idx; - if (idx < 0 || idx >= len) { ret = JS_UNDEFINED; + } else if (js_get_fast_array(ctx, obj, &arrp, &count) && idx < count) { + ret = JS_DupValue(ctx, arrp[idx]); } else { - ret = JS_GetPropertyInt64(ctx, obj, idx); + int present = JS_TryGetPropertyInt64(ctx, obj, idx, &ret); + if (present < 0) + goto exception; + if (!present) + ret = JS_UNDEFINED; } - - exception: JS_FreeValue(ctx, obj); return ret; + exception: + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; } static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, @@ -39711,11 +40797,6 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - if (JS_ToInt64Sat(ctx, &idx, argv[0])) goto exception; @@ -39727,28 +40808,24 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, goto exception; } - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; - i = 0; pval = p->u.array.u.values; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { for (; i < idx; i++, pval++) - *pval = js_dup(arrp[i]); - *pval = js_dup(argv[1]); + *pval = JS_DupValue(ctx, arrp[i]); + *pval = JS_DupValue(ctx, argv[1]); for (i++, pval++; i < len; i++, pval++) - *pval = js_dup(arrp[i]); + *pval = JS_DupValue(ctx, arrp[i]); } else { for (; i < idx; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto fill_and_fail; - *pval = js_dup(argv[1]); + *pval = JS_DupValue(ctx, argv[1]); for (i++, pval++; i < len; i++, pval++) { if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { fill_and_fail: @@ -39759,7 +40836,7 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) goto exception; ret = arr; @@ -39784,7 +40861,7 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, if (JS_IsException(obj)) goto exception; - arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); + arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); if (JS_IsException(arr)) goto exception; n = 0; @@ -39819,13 +40896,13 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, JS_ThrowTypeError(ctx, "Array loo long"); goto exception; } - if (JS_DefinePropertyValueInt64(ctx, arr, n, js_dup(e), + if (JS_DefinePropertyValueInt64(ctx, arr, n, JS_DupValue(ctx, e), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; n++; } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0) goto exception; JS_FreeValue(ctx, obj); @@ -39844,41 +40921,6 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, #define special_filter 4 #define special_TA 8 -static JSObject *get_typed_array(JSContext *ctx, JSValueConst this_val) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) - goto fail; - p = JS_VALUE_GET_OBJ(this_val); - if (!is_typed_array(p->class_id)) { - fail: - JS_ThrowTypeError(ctx, "not a TypedArray"); - return NULL; - } - return p; -} - -// Be *very* careful if you touch the typed array's memory directly: -// the length is only valid until the next call into JS land because -// JS code can detach or resize the backing array buffer. Functions -// like JS_GetProperty and JS_ToIndex call JS code. -// -// Exclusively reading or writing elements with JS_GetProperty, -// JS_GetPropertyInt64, JS_SetProperty, etc. is safe because they -// perform bounds checks, as does js_get_fast_array_element. -static int js_typed_array_get_length_unsafe(JSContext *ctx, JSValueConst obj) -{ - JSObject *p; - p = get_typed_array(ctx, obj); - if (!p) - return -1; - if (typed_array_is_oob(p)) { - JS_ThrowTypeErrorArrayBufferOOB(ctx); - return -1; - } - return p->u.array.count; -} - static JSValue js_typed_array___speciesCreate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); @@ -39895,7 +40937,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; val = JS_UNDEFINED; if (special & special_TA) { - obj = js_dup(this_val); + obj = JS_DupValue(ctx, this_val); len = js_typed_array_get_length_unsafe(ctx, obj); if (len < 0) goto exception; @@ -39923,18 +40965,18 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, break; case special_map: /* XXX: JS_ArraySpeciesCreate should take int64_t */ - ret = JS_ArraySpeciesCreate(ctx, obj, js_int64(len)); + ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt64(ctx, len)); if (JS_IsException(ret)) goto exception; break; case special_filter: - ret = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); + ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); if (JS_IsException(ret)) goto exception; break; case special_map | special_TA: args[0] = obj; - args[1] = js_int32(len); + args[1] = JS_NewInt32(ctx, len); ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(ret)) goto exception; @@ -39952,14 +40994,16 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, val = JS_GetPropertyInt64(ctx, obj, k); if (JS_IsException(val)) goto exception; - present = true; + present = TRUE; } else { present = JS_TryGetPropertyInt64(ctx, obj, k, &val); if (present < 0) goto exception; } if (present) { - index_val = js_int64(k); + index_val = JS_NewInt64(ctx, k); + if (JS_IsException(index_val)) + goto exception; args[0] = val; args[1] = index_val; args[2] = obj; @@ -39988,13 +41032,13 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, goto exception; break; case special_map | special_TA: - if (JS_SetPropertyValue(ctx, ret, js_int32(k), res, JS_PROP_THROW) < 0) + if (JS_SetPropertyValue(ctx, ret, JS_NewInt32(ctx, k), res, JS_PROP_THROW) < 0) goto exception; break; case special_filter: case special_filter | special_TA: if (JS_ToBoolFree(ctx, res)) { - if (JS_DefinePropertyValueInt64(ctx, ret, n++, js_dup(val), + if (JS_DefinePropertyValueInt64(ctx, ret, n++, JS_DupValue(ctx, val), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } @@ -40011,7 +41055,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, if (special == (special_filter | special_TA)) { JSValue arr; args[0] = obj; - args[1] = js_int32(n); + args[1] = JS_NewInt32(ctx, n); arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(arr)) goto exception; @@ -40050,7 +41094,7 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, acc = JS_UNDEFINED; val = JS_UNDEFINED; if (special & special_TA) { - obj = js_dup(this_val); + obj = JS_DupValue(ctx, this_val); len = js_typed_array_get_length_unsafe(ctx, obj); if (len < 0) goto exception; @@ -40066,7 +41110,7 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, k = 0; if (argc > 1) { - acc = js_dup(argv[1]); + acc = JS_DupValue(ctx, argv[1]); } else { for(;;) { if (k >= len) { @@ -40095,14 +41139,16 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, val = JS_GetPropertyInt64(ctx, obj, k1); if (JS_IsException(val)) goto exception; - present = true; + present = TRUE; } else { present = JS_TryGetPropertyInt64(ctx, obj, k1, &val); if (present < 0) goto exception; } if (present) { - index_val = js_int64(k1); + index_val = JS_NewInt64(ctx, k1); + if (JS_IsException(index_val)) + goto exception; args[0] = acc; args[1] = val; args[2] = index_val; @@ -40151,7 +41197,8 @@ static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val, /* XXX: should special case fast arrays */ while (start < end) { - if (JS_SetPropertyInt64(ctx, obj, start, js_dup(argv[0])) < 0) + if (JS_SetPropertyInt64(ctx, obj, start, + JS_DupValue(ctx, argv[0])) < 0) goto exception; start++; } @@ -40175,7 +41222,7 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - res = true; + res = FALSE; if (len > 0) { n = 0; if (argc > 1) { @@ -40184,8 +41231,10 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, } if (js_get_fast_array(ctx, obj, &arrp, &count)) { for (; n < count; n++) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), + if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), + JS_DupValue(ctx, arrp[n]), JS_EQ_SAME_VALUE_ZERO)) { + res = TRUE; goto done; } } @@ -40194,16 +41243,16 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, val = JS_GetPropertyInt64(ctx, obj, n); if (JS_IsException(val)) goto exception; - if (js_strict_eq2(ctx, js_dup(argv[0]), val, + if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_SAME_VALUE_ZERO)) { - goto done; + res = TRUE; + break; } } } - res = false; done: JS_FreeValue(ctx, obj); - return js_bool(res); + return JS_NewBool(ctx, res); exception: JS_FreeValue(ctx, obj); @@ -40214,7 +41263,7 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue obj, val; - int64_t len, n; + int64_t len, n, res; JSValue *arrp; uint32_t count; @@ -40222,6 +41271,7 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; + res = -1; if (len > 0) { n = 0; if (argc > 1) { @@ -40230,8 +41280,9 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, } if (js_get_fast_array(ctx, obj, &arrp, &count)) { for (; n < count; n++) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), - JS_EQ_STRICT)) { + if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), + JS_DupValue(ctx, arrp[n]), JS_EQ_STRICT)) { + res = n; goto done; } } @@ -40241,16 +41292,16 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { - goto done; + if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) { + res = n; + break; } } } } - n = -1; done: JS_FreeValue(ctx, obj); - return js_int64(n); + return JS_NewInt64(ctx, res); exception: JS_FreeValue(ctx, obj); @@ -40261,43 +41312,35 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue obj, val; - int64_t len, n; - JSValue *arrp; - uint32_t count; + int64_t len, n, res; + int present; obj = JS_ToObject(ctx, this_val); if (js_get_length64(ctx, &len, obj)) goto exception; + res = -1; if (len > 0) { n = len - 1; if (argc > 1) { if (JS_ToInt64Clamp(ctx, &n, argv[1], -1, len - 1, len)) goto exception; } - if (js_get_fast_array(ctx, obj, &arrp, &count) && count == len) { - for (; n >= 0; n--) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), - JS_EQ_STRICT)) { - goto done; - } - } - } + /* XXX: should special case fast arrays */ for (; n >= 0; n--) { - int present = JS_TryGetPropertyInt64(ctx, obj, n, &val); + present = JS_TryGetPropertyInt64(ctx, obj, n, &val); if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { - goto done; + if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) { + res = n; + break; } } } } - n = -1; - done: JS_FreeValue(ctx, obj); - return js_int64(n); + return JS_NewInt64(ctx, res); exception: JS_FreeValue(ctx, obj); @@ -40345,7 +41388,9 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, // TODO(bnoordhuis) add fast path for fast arrays for(; k != end; k += dir) { - index_val = js_int64(k); + index_val = JS_NewInt64(ctx, k); + if (JS_IsException(index_val)) + goto exception; val = JS_GetPropertyValue(ctx, obj, index_val); if (JS_IsException(val)) goto exception; @@ -40371,7 +41416,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, obj); if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) - return js_int32(-1); + return JS_NewInt32(ctx, -1); else return JS_UNDEFINED; @@ -40425,7 +41470,7 @@ static JSValue js_array_join(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(sep); if (p->len == 1 && !p->is_wide_char) - c = str8(p)[0]; + c = p->u.str8[0]; else c = -1; } @@ -40503,7 +41548,7 @@ static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0) goto exception; JS_FreeValue(ctx, obj); @@ -40537,14 +41582,15 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, from = 0; } for(i = 0; i < argc; i++) { - if (JS_SetPropertyInt64(ctx, obj, from + i, js_dup(argv[i])) < 0) + if (JS_SetPropertyInt64(ctx, obj, from + i, + JS_DupValue(ctx, argv[i])) < 0) goto exception; } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0) goto exception; JS_FreeValue(ctx, obj); - return js_int64(newLen); + return JS_NewInt64(ctx, newLen); exception: JS_FreeValue(ctx, obj); @@ -40638,26 +41684,18 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; if (len > 0) { p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; i = len - 1; pval = p->u.array.u.values; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { for (; i >= 0; i--, pval++) - *pval = js_dup(arrp[i]); + *pval = JS_DupValue(ctx, arrp[i]); } else { // Query order is observable; test262 expects descending order. for (; i >= 0; i--, pval++) { @@ -40670,7 +41708,7 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) goto exception; } @@ -40704,7 +41742,8 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, if (argc == 0) { item_count = 0; del_count = 0; - } else if (argc == 1) { + } else + if (argc == 1) { item_count = 0; del_count = len - start; } else { @@ -40726,7 +41765,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, } count = max_int64(final - start, 0); } - len_val = js_int64(count); + len_val = JS_NewInt64(ctx, count); arr = JS_ArraySpeciesCreate(ctx, obj, len_val); JS_FreeValue(ctx, len_val); if (JS_IsException(arr)) @@ -40743,7 +41782,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, js_is_fast_array(ctx, arr)) { /* XXX: should share code with fast array constructor */ for (; k < final && k < count32; k++, n++) { - if (JS_CreateDataPropertyUint32(ctx, arr, n, js_dup(arrp[k]), JS_PROP_THROW) < 0) + if (JS_CreateDataPropertyUint32(ctx, arr, n, JS_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0) goto exception; } } @@ -40757,7 +41796,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0) goto exception; if (splice) { @@ -40774,10 +41813,10 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, } } for (i = 0; i < item_count; i++) { - if (JS_SetPropertyInt64(ctx, obj, start + i, js_dup(argv[i + 2])) < 0) + if (JS_SetPropertyInt64(ctx, obj, start + i, JS_DupValue(ctx, argv[i + 2])) < 0) goto exception; } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(new_len)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, new_len)) < 0) goto exception; } JS_FreeValue(ctx, obj); @@ -40823,17 +41862,12 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, add = argc - 2; newlen = len + add - del; - if (newlen > UINT32_MAX) { - // Per spec: TypeError if newlen >= 2**53, RangeError below - if (newlen > MAX_SAFE_INTEGER) { - JS_ThrowTypeError(ctx, "invalid array length"); - } else { - JS_ThrowRangeError(ctx, "invalid array length"); - } + if (newlen > MAX_SAFE_INTEGER) { + JS_ThrowTypeError(ctx, "invalid array length"); goto exception; } - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, newlen); if (JS_IsException(arr)) goto exception; @@ -40841,26 +41875,22 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, goto done; p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, newlen) < 0) - goto exception; - - p->u.array.count = newlen; pval = &p->u.array.u.values[0]; last = &p->u.array.u.values[newlen]; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { for (i = 0; i < start; i++, pval++) - *pval = js_dup(arrp[i]); + *pval = JS_DupValue(ctx, arrp[i]); for (j = 0; j < add; j++, pval++) - *pval = js_dup(argv[2 + j]); + *pval = JS_DupValue(ctx, argv[2 + j]); for (i += del; i < len; i++, pval++) - *pval = js_dup(arrp[i]); + *pval = JS_DupValue(ctx, arrp[i]); } else { for (i = 0; i < start; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; for (j = 0; j < add; j++, pval++) - *pval = js_dup(argv[2 + j]); + *pval = JS_DupValue(ctx, argv[2 + j]); for (i += del; i < len; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; @@ -40868,7 +41898,7 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, assert(pval == last); - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(newlen)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, newlen)) < 0) goto exception; done: @@ -40941,17 +41971,15 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target, if (!present) continue; if (!JS_IsUndefined(mapperFunction)) { - JSValue index = js_int64(sourceIndex); - JSValueConst args[3] = { element, index, source }; - JSValue ret = JS_Call(ctx, mapperFunction, thisArg, 3, args); - JS_FreeValue(ctx, element); - JS_FreeValue(ctx, index); - if (JS_IsException(ret)) + JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source }; + element = JS_Call(ctx, mapperFunction, thisArg, 3, args); + JS_FreeValue(ctx, JS_VALUE_CONST_CAST(args[0])); + JS_FreeValue(ctx, JS_VALUE_CONST_CAST(args[1])); + if (JS_IsException(element)) return -1; - element = ret; } if (depth > 0) { - is_array = js_is_array(ctx, element); + is_array = JS_IsArray(ctx, element); if (is_array < 0) goto fail; if (is_array) { @@ -41012,7 +42040,7 @@ static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val, goto exception; } } - arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); + arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); if (JS_IsException(arr)) goto exception; if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum, @@ -41090,7 +42118,7 @@ static int js_array_cmp_generic(const void *a, const void *b, void *opaque) { goto exception; bp->str = JS_VALUE_GET_STRING(str); } - cmp = js_string_compare(ap->str, bp->str); + cmp = js_string_compare(ctx, ap->str, bp->str); } if (cmp != 0) return cmp; @@ -41200,10 +42228,11 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, JSObject *p; int64_t i, len; uint32_t count32; + int ok; - if (!JS_IsUndefined(argv[0])) - if (check_function(ctx, argv[0])) - return JS_EXCEPTION; + ok = JS_IsUndefined(argv[0]) || JS_IsFunction(ctx, argv[0]); + if (!ok) + return JS_ThrowTypeError(ctx, "not a function"); ret = JS_EXCEPTION; arr = JS_UNDEFINED; @@ -41211,26 +42240,17 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; if (len > 0) { p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; - i = 0; pval = p->u.array.u.values; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { for (; i < len; i++, pval++) - *pval = js_dup(arrp[i]); + *pval = JS_DupValue(ctx, arrp[i]); } else { for (; i < len; i++, pval++) { if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { @@ -41241,7 +42261,7 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) goto exception; } @@ -41265,7 +42285,7 @@ typedef struct JSArrayIteratorData { uint32_t idx; } JSArrayIteratorData; -static void js_array_iterator_finalizer(JSRuntime *rt, JSValueConst val) +static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSArrayIteratorData *it = p->u.array_iterator_data; @@ -41285,23 +42305,6 @@ static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, } } -static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) -{ - JSValue obj; - int i; - - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - return JS_EXCEPTION; - for(i = 0; i < len; i++) { - if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(tab[i]), 0) < 0) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - } - return obj; -} - static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -41330,7 +42333,7 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, it->obj = arr; it->kind = kind; it->idx = 0; - JS_SetOpaqueInternal(enum_obj, it); + JS_SetOpaque(enum_obj, it); return enum_obj; fail1: JS_FreeValue(ctx, enum_obj); @@ -41341,7 +42344,7 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic) + BOOL *pdone, int magic) { JSArrayIteratorData *it; uint32_t len, idx; @@ -41354,7 +42357,8 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, if (JS_IsUndefined(it->obj)) goto done; p = JS_VALUE_GET_OBJ(it->obj); - if (is_typed_array(p->class_id)) { + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { if (typed_array_is_oob(p)) { JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail1; @@ -41363,7 +42367,7 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, } else { if (js_get_length32(ctx, &len, it->obj)) { fail1: - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } } @@ -41372,13 +42376,13 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, it->obj); it->obj = JS_UNDEFINED; done: - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } it->idx = idx + 1; - *pdone = false; + *pdone = FALSE; if (it->kind == JS_ITERATOR_KIND_KEY) { - return js_uint32(idx); + return JS_NewUint32(ctx, idx); } else { val = JS_GetPropertyUint32(ctx, it->obj, idx); if (JS_IsException(val)) @@ -41388,7 +42392,7 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, } else { JSValueConst args[2]; JSValue num; - num = js_uint32(idx); + num = JS_NewUint32(ctx, idx); args[0] = num; args[1] = val; obj = js_create_array(ctx, 2, args); @@ -41399,12 +42403,14 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, } } +/* Iterator Wrap */ + typedef struct JSIteratorWrapData { JSValue wrapped_iter; JSValue wrapped_next; } JSIteratorWrapData; -static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValueConst val) +static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSIteratorWrapData *it = p->u.iterator_wrap_data; @@ -41435,18 +42441,20 @@ static JSValue js_iterator_wrap_next(JSContext *ctx, JSValueConst this_val, it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_WRAP); if (!it) return JS_EXCEPTION; - if (magic == GEN_MAGIC_NEXT) - return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, argc, argv, pdone); - method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return); - if (JS_IsException(method)) - return JS_EXCEPTION; - if (JS_IsNull(method) || JS_IsUndefined(method)) { - *pdone = true; - return JS_UNDEFINED; + if (magic == GEN_MAGIC_NEXT) { + return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, 0, NULL, pdone); + } else { + method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (JS_IsNull(method) || JS_IsUndefined(method)) { + *pdone = TRUE; + return JS_UNDEFINED; + } + ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + return ret; } - ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, argc, argv, pdone); - JS_FreeValue(ctx, method); - return ret; } static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = { @@ -41454,11 +42462,13 @@ static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = { JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ), }; +/* Iterator */ + static JSValue js_iterator_constructor_getset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + JSValue *func_data) { int ret; @@ -41466,12 +42476,14 @@ static JSValue js_iterator_constructor_getset(JSContext *ctx, if (!JS_IsObject(argv[0])) return JS_ThrowTypeErrorNotAnObject(ctx); ret = JS_DefinePropertyValue(ctx, this_val, JS_ATOM_constructor, - js_dup(argv[0]), + JS_DupValue(ctx, argv[0]), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (ret < 0) return JS_EXCEPTION; + return JS_UNDEFINED; + } else { + return JS_DupValue(ctx, func_data[0]); } - return js_dup(func_data[0]); } static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target, @@ -41482,280 +42494,79 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target, if (JS_TAG_OBJECT != JS_VALUE_GET_TAG(new_target)) return JS_ThrowTypeError(ctx, "constructor requires 'new'"); p = JS_VALUE_GET_OBJ(new_target); - if (p->class_id == JS_CLASS_C_FUNCTION) - if (p->u.cfunc.c_function.generic == js_iterator_constructor) - return JS_ThrowTypeError(ctx, "abstract class not constructable"); - return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR); -} - -// note: deliberately doesn't use space-saving bit fields for -// |index|, |count| and |running| because tcc miscompiles them -typedef struct JSIteratorConcatData { - int index, count; // elements (not pairs!) in values[] array - bool running; - JSValue iter, next, values[]; // array of (object, method) pairs -} JSIteratorConcatData; - -static void js_iterator_concat_finalizer(JSRuntime *rt, JSValueConst val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSIteratorConcatData *it = p->u.iterator_concat_data; - if (it) { - JS_FreeValueRT(rt, it->iter); - JS_FreeValueRT(rt, it->next); - for (int i = it->index; i < it->count; i++) - JS_FreeValueRT(rt, it->values[i]); - js_free_rt(rt, it); + if (p->class_id == JS_CLASS_C_FUNCTION && + p->u.cfunc.c_function.generic == js_iterator_constructor) { + return JS_ThrowTypeError(ctx, "abstract class not constructable"); } -} - -static void js_iterator_concat_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSIteratorConcatData *it = p->u.iterator_concat_data; - if (it) { - JS_MarkValue(rt, it->iter, mark_func); - JS_MarkValue(rt, it->next, mark_func); - for (int i = it->index; i < it->count; i++) - JS_MarkValue(rt, it->values[i], mark_func); - } -} - -static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue iter, item, next, val, *obj, *meth; - JSIteratorConcatData *it; - JSPropertyDescriptor d; - int done, ret; - - it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT); - if (!it) - return JS_EXCEPTION; - if (it->running) - return JS_ThrowTypeError(ctx, "already running"); -next: - if (it->index >= it->count) - return js_create_iterator_result(ctx, JS_UNDEFINED, /*done*/true); - obj = &it->values[it->index + 0]; - meth = &it->values[it->index + 1]; - iter = it->iter; - if (JS_IsUndefined(iter)) { - iter = JS_GetIterator2(ctx, *obj, *meth); - if (JS_IsException(iter)) - return JS_EXCEPTION; - it->iter = iter; - } - next = it->next; - if (JS_IsUndefined(next)) { - next = JS_GetProperty(ctx, iter, JS_ATOM_next); - if (JS_IsException(next)) - return JS_EXCEPTION; - it->next = next; - } - it->running = true; - item = JS_IteratorNext2(ctx, iter, next, 0, NULL, &done); - it->running = false; - if (JS_IsException(item)) - return JS_EXCEPTION; - if (!done) - return js_create_iterator_result(ctx, item, /*done*/false); - // done==1 means really done, done==2 means "unknown, inspect object" - if (done == 2) { - val = JS_GetProperty(ctx, item, JS_ATOM_done); - if (JS_IsException(val)) { - JS_FreeValue(ctx, item); - return JS_EXCEPTION; - } - done = JS_ToBoolFree(ctx, val); - } - if (done) { - JS_FreeValue(ctx, item); - JS_FreeValue(ctx, iter); - JS_FreeValue(ctx, next); - it->iter = JS_UNDEFINED; - it->next = JS_UNDEFINED; - JS_FreeValue(ctx, *meth); - JS_FreeValue(ctx, *obj); - it->index += 2; - goto next; - } - // not done, construct { done: false, value: xxx } object - // copy .value verbatim from source object, spec doesn't - // allow dereferencing getters here - d = (JSPropertyDescriptor){ - .value = JS_UNDEFINED, - .getter = JS_UNDEFINED, - .setter = JS_UNDEFINED, - }; - ret = JS_GetOwnProperty(ctx, &d, item, JS_ATOM_value); - JS_FreeValue(ctx, item); - if (ret < 0) - return JS_EXCEPTION; - if (d.flags & JS_PROP_GETSET) { - d.flags |= JS_PROP_HAS_GET | JS_PROP_HAS_SET; - } else { - d.flags |= JS_PROP_HAS_VALUE; - } - item = JS_NewObject(ctx); - if (JS_IsException(item)) - goto fail; - if (JS_DefinePropertyValue(ctx, item, JS_ATOM_done, JS_FALSE, - JS_PROP_C_W_E) < 0) { - goto fail; - } - if (JS_DefineProperty(ctx, item, JS_ATOM_value, d.value, d.getter, - d.setter, d.flags | JS_PROP_C_W_E) < 0) { - fail: - JS_FreeValue(ctx, item); - item = JS_EXCEPTION; - } - js_free_desc(ctx, &d); - return item; -} - -static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSIteratorConcatData *it; - JSValue ret; - - it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT); - if (!it) - return JS_EXCEPTION; - if (it->running) - return JS_ThrowTypeError(ctx, "already running"); - ret = JS_UNDEFINED; - if (!JS_IsUndefined(it->iter)) { - ret = JS_GetProperty(ctx, it->iter, JS_ATOM_return); - if (JS_IsException(ret)) - return JS_EXCEPTION; - it->running = true; - ret = JS_CallFree(ctx, ret, it->iter, 0, NULL); - it->running = false; - } - while (it->index < it->count) - JS_FreeValue(ctx, it->values[it->index++]); - JS_FreeValue(ctx, it->iter); - JS_FreeValue(ctx, it->next); - it->iter = JS_UNDEFINED; - it->next = JS_UNDEFINED; - return ret; -} - -// note: |next| and |return| don't use JS_ITERATOR_NEXT_DEF because |next| -// has to return a full { value: xxx, done: xxx } step object - it must -// copy getters and setters from the inner iterator's step object -// slightly inefficient because of the intermediate step object that is -// created but that can't be helped right now -static const JSCFunctionListEntry js_iterator_concat_proto_funcs[] = { - JS_CFUNC_DEF("next", 1, js_iterator_concat_next ), - JS_CFUNC_DEF("return", 1, js_iterator_concat_return ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Concat", JS_PROP_CONFIGURABLE ), -}; - -static JSValue js_iterator_concat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSIteratorConcatData *it; - JSValue obj, method; - - it = js_malloc(ctx, sizeof(*it) + 2*argc * sizeof(it->values[0])); - if (!it) - return JS_EXCEPTION; - it->running = false; - it->index = 0; - it->count = 0; - it->iter = JS_UNDEFINED; - it->next = JS_UNDEFINED; - for (int i = 0; i < argc; i++) { - JSValueConst obj = argv[i]; - if (!JS_IsObject(obj)) { - JS_ThrowTypeErrorNotAnObject(ctx); - goto fail; - } - method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); - if (JS_IsException(method)) - goto fail; - if (!JS_IsFunction(ctx, method)) { - JS_ThrowTypeErrorNotAFunction(ctx); - JS_FreeValue(ctx, method); - goto fail; - } - it->values[it->count++] = js_dup(obj); - it->values[it->count++] = method; - } - obj = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_CONCAT); - if (JS_IsException(obj)) - goto fail; - JS_SetOpaqueInternal(obj, it); - return obj; -fail: - for (int i = 0; i < it->count; i++) - JS_FreeValue(ctx, it->values[i]); - js_free(ctx, it); - return JS_EXCEPTION; + return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR); } static JSValue js_iterator_from(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue method, iter; + JSValueConst obj = argv[0]; + JSValue method, iter, wrapper; JSIteratorWrapData *it; int ret; - JSValueConst obj = argv[0]; - if (JS_IsString(obj)) { - method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); - if (JS_IsException(method)) - return JS_EXCEPTION; - return JS_CallFree(ctx, method, obj, 0, NULL); + if (!JS_IsObject(obj)) { + if (!JS_IsString(obj)) + return JS_ThrowTypeError(ctx, "Iterator.from called on non-object"); } - if (!JS_IsObject(obj)) - return JS_ThrowTypeError(ctx, "Iterator.from called on non-object"); - ret = JS_OrdinaryIsInstanceOf(ctx, obj, ctx->iterator_ctor); - if (ret < 0) - return JS_EXCEPTION; - if (ret) - return js_dup(obj); method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); if (JS_IsException(method)) return JS_EXCEPTION; if (JS_IsNull(method) || JS_IsUndefined(method)) { - method = JS_GetProperty(ctx, obj, JS_ATOM_next); - if (JS_IsException(method)) - return JS_EXCEPTION; - iter = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP); - if (JS_IsException(iter)) - goto fail; - it = js_malloc(ctx, sizeof(*it)); - if (!it) - goto fail; - it->wrapped_iter = js_dup(obj); - it->wrapped_next = method; - JS_SetOpaqueInternal(iter, it); + iter = JS_DupValue(ctx, obj); } else { iter = JS_GetIterator2(ctx, obj, method); JS_FreeValue(ctx, method); if (JS_IsException(iter)) return JS_EXCEPTION; } - return iter; -fail: + + wrapper = JS_UNDEFINED; + method = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(method)) + goto fail; + + ret = JS_OrdinaryIsInstanceOf(ctx, iter, ctx->iterator_ctor); + if (ret < 0) + goto fail; + if (ret) { + JS_FreeValue(ctx, method); + return iter; + } + + wrapper = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP); + if (JS_IsException(wrapper)) + goto fail; + it = js_malloc(ctx, sizeof(*it)); + if (!it) + goto fail; + it->wrapped_iter = iter; + it->wrapped_next = method; + JS_SetOpaque(wrapper, it); + return wrapper; + + fail: JS_FreeValue(ctx, method); JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, wrapper); return JS_EXCEPTION; } -static int check_iterator(JSContext *ctx, JSValueConst obj) -{ - if (!JS_IsObject(obj)) { - JS_ThrowTypeErrorNotAnObject(ctx); - return -1; - } - return 0; -} +typedef enum JSIteratorHelperKindEnum { + JS_ITERATOR_HELPER_KIND_DROP, + JS_ITERATOR_HELPER_KIND_EVERY, + JS_ITERATOR_HELPER_KIND_FILTER, + JS_ITERATOR_HELPER_KIND_FIND, + JS_ITERATOR_HELPER_KIND_FLAT_MAP, + JS_ITERATOR_HELPER_KIND_FOR_EACH, + JS_ITERATOR_HELPER_KIND_MAP, + JS_ITERATOR_HELPER_KIND_SOME, + JS_ITERATOR_HELPER_KIND_TAKE, +} JSIteratorHelperKindEnum; typedef struct JSIteratorHelperData { JSValue obj; @@ -41776,8 +42587,8 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, int64_t count; JSIteratorHelperData *it; - if (check_iterator(ctx, this_val) < 0) - return JS_EXCEPTION; + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); func = JS_UNDEFINED; count = 0; @@ -41845,19 +42656,19 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, goto fail; } it->kind = magic; - it->obj = js_dup(this_val); - it->func = js_dup(func); + it->obj = JS_DupValue(ctx, this_val); + it->func = JS_DupValue(ctx, func); it->next = method; it->inner = JS_UNDEFINED; it->count = count; it->executing = 0; it->done = 0; - JS_SetOpaqueInternal(obj, it); + JS_SetOpaque(obj, it); return obj; range_error: JS_ThrowRangeError(ctx, "must be positive"); fail: - JS_IteratorClose(ctx, this_val, true); + JS_IteratorClose(ctx, this_val, TRUE); return JS_EXCEPTION; } @@ -41869,16 +42680,17 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, int64_t idx; int done; - if (check_iterator(ctx, this_val) < 0) - return JS_EXCEPTION; + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); func = JS_UNDEFINED; method = JS_UNDEFINED; + if (check_function(ctx, argv[0])) goto fail; - func = js_dup(argv[0]); + func = JS_DupValue(ctx, argv[0]); method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) - goto fail; + goto fail_no_close; r = JS_UNDEFINED; @@ -41889,10 +42701,10 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (done) break; - index_val = js_int64(idx); + index_val = JS_NewInt64(ctx, idx); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); @@ -41901,7 +42713,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, if (JS_IsException(ret)) goto fail; if (!JS_ToBoolFree(ctx, ret)) { - if (JS_IteratorClose(ctx, this_val, false) < 0) + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) r = JS_EXCEPTION; else r = JS_FALSE; @@ -41918,10 +42730,10 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (done) break; - index_val = js_int64(idx); + index_val = JS_NewInt64(ctx, idx); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); @@ -41931,7 +42743,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, goto fail; } if (JS_ToBoolFree(ctx, ret)) { - if (JS_IteratorClose(ctx, this_val, false) < 0) { + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) { JS_FreeValue(ctx, item); r = JS_EXCEPTION; } else { @@ -41939,6 +42751,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, } break; } + JS_FreeValue(ctx, item); index_val = JS_UNDEFINED; ret = JS_UNDEFINED; item = JS_UNDEFINED; @@ -41950,10 +42763,10 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (done) break; - index_val = js_int64(idx); + index_val = JS_NewInt64(ctx, idx); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); @@ -41974,10 +42787,10 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (done) break; - index_val = js_int64(idx); + index_val = JS_NewInt64(ctx, idx); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); @@ -41986,7 +42799,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, if (JS_IsException(ret)) goto fail; if (JS_ToBoolFree(ctx, ret)) { - if (JS_IteratorClose(ctx, this_val, false) < 0) + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) r = JS_EXCEPTION; else r = JS_TRUE; @@ -42006,8 +42819,9 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); return r; -fail: - JS_IteratorClose(ctx, this_val, true); + fail: + JS_IteratorClose(ctx, this_val, TRUE); + fail_no_close: JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); return JS_EXCEPTION; @@ -42021,24 +42835,24 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, int64_t idx; int done; - if (check_iterator(ctx, this_val) < 0) - return JS_EXCEPTION; + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); acc = JS_UNDEFINED; func = JS_UNDEFINED; method = JS_UNDEFINED; if (check_function(ctx, argv[0])) goto exception; - func = js_dup(argv[0]); + func = JS_DupValue(ctx, argv[0]); method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) goto exception; if (argc > 1) { - acc = js_dup(argv[1]); + acc = JS_DupValue(ctx, argv[1]); idx = 0; } else { acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(acc)) - goto exception; + goto exception_no_close; if (done) { JS_ThrowTypeError(ctx, "empty iterator"); goto exception; @@ -42048,10 +42862,10 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, for (/* empty */; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto exception; + goto exception_no_close; if (done) break; - index_val = js_int64(idx); + index_val = JS_NewInt64(ctx, idx); args[0] = acc; args[1] = item; args[2] = index_val; @@ -42069,8 +42883,9 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); return acc; -exception: - JS_IteratorClose(ctx, this_val, true); + exception: + JS_IteratorClose(ctx, this_val, TRUE); + exception_no_close: JS_FreeValue(ctx, acc); JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); @@ -42085,8 +42900,8 @@ static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val, int done; result = JS_UNDEFINED; - if (check_iterator(ctx, this_val) < 0) - return JS_EXCEPTION; + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) return JS_EXCEPTION; @@ -42103,7 +42918,7 @@ static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } - if (JS_SetProperty(ctx, result, JS_ATOM_length, js_uint32(idx)) < 0) + if (JS_SetProperty(ctx, result, JS_ATOM_length, JS_NewUint32(ctx, idx)) < 0) goto exception; JS_FreeValue(ctx, method); return result; @@ -42116,7 +42931,7 @@ static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val, static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue js_iterator_proto_get_toStringTag(JSContext *ctx, JSValueConst this_val) @@ -42128,24 +42943,26 @@ static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValueConst th { int res; - if (check_iterator(ctx, this_val) < 0) - return JS_EXCEPTION; + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_ITERATOR])) return JS_ThrowTypeError(ctx, "Cannot assign to read only property"); res = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_Symbol_toStringTag); if (res < 0) return JS_EXCEPTION; if (res) { - if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val)) < 0) + if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, JS_DupValue(ctx, val)) < 0) return JS_EXCEPTION; } else { - if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val), JS_PROP_C_W_E) < 0) + if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, JS_DupValue(ctx, val), JS_PROP_C_W_E) < 0) return JS_EXCEPTION; } return JS_UNDEFINED; } -static void js_iterator_helper_finalizer(JSRuntime *rt, JSValueConst val) +/* Iterator Helper */ + +static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSIteratorHelperData *it = p->u.iterator_helper_data; @@ -42178,7 +42995,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, JSIteratorHelperData *it; JSValue ret; - *pdone = false; + *pdone = FALSE; it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER); if (!it) @@ -42186,7 +43003,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, if (it->executing) return JS_ThrowTypeError(ctx, "cannot invoke a running iterator"); if (it->done) { - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } @@ -42197,7 +43014,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, { JSValue item, method; if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); + method = JS_DupValue(ctx, it->next); } else { method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); if (JS_IsException(method)) @@ -42208,11 +43025,11 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); if (JS_IsException(item)) { JS_FreeValue(ctx, method); - goto fail; + goto fail_no_close; } JS_FreeValue(ctx, item); if (magic == GEN_MAGIC_RETURN) - *pdone = true; + *pdone = TRUE; if (*pdone) { JS_FreeValue(ctx, method); ret = JS_UNDEFINED; @@ -42223,7 +43040,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); JS_FreeValue(ctx, method); if (JS_IsException(item)) - goto fail; + goto fail_no_close; ret = item; goto done; } @@ -42233,7 +43050,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, JSValue item, method, selected, index_val; JSValueConst args[2]; if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); + method = JS_DupValue(ctx, it->next); } else { method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); if (JS_IsException(method)) @@ -42243,19 +43060,20 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); if (JS_IsException(item)) { JS_FreeValue(ctx, method); - goto fail; + goto fail_no_close; } if (*pdone || magic == GEN_MAGIC_RETURN) { JS_FreeValue(ctx, method); ret = item; goto done; } - index_val = js_int64(it->count++); + index_val = JS_NewInt64(ctx, it->count++); args[0] = item; args[1] = index_val; selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); JS_FreeValue(ctx, index_val); if (JS_IsException(selected)) { + JS_FreeValue(ctx, item); JS_FreeValue(ctx, method); goto fail; } @@ -42264,6 +43082,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, ret = item; goto done; } + JS_FreeValue(ctx, item); goto filter_again; } break; @@ -42274,7 +43093,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, flat_map_again: if (JS_IsUndefined(it->inner)) { if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); + method = JS_DupValue(ctx, it->next); } else { method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); if (JS_IsException(method)) @@ -42283,12 +43102,12 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); JS_FreeValue(ctx, method); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (*pdone || magic == GEN_MAGIC_RETURN) { ret = item; goto done; } - index_val = js_int64(it->count++); + index_val = JS_NewInt64(ctx, it->count++); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); @@ -42326,7 +43145,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, method = JS_GetProperty(ctx, it->inner, JS_ATOM_return); if (JS_IsException(method)) { inner_fail: - JS_IteratorClose(ctx, it->inner, false); + JS_IteratorClose(ctx, it->inner, FALSE); JS_FreeValue(ctx, it->inner); it->inner = JS_UNDEFINED; goto fail; @@ -42341,8 +43160,8 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, } if (*pdone) { inner_end: - *pdone = false; // The outer iterator must continue. - JS_IteratorClose(ctx, it->inner, false); + *pdone = FALSE; // The outer iterator must continue. + JS_IteratorClose(ctx, it->inner, FALSE); JS_FreeValue(ctx, it->inner); it->inner = JS_UNDEFINED; goto flat_map_again; @@ -42356,7 +43175,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, JSValue item, method, index_val; JSValueConst args[2]; if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); + method = JS_DupValue(ctx, it->next); } else { method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); if (JS_IsException(method)) @@ -42365,12 +43184,12 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); JS_FreeValue(ctx, method); if (JS_IsException(item)) - goto fail; + goto fail_no_close; if (*pdone || magic == GEN_MAGIC_RETURN) { ret = item; goto done; } - index_val = js_int64(it->count++); + index_val = JS_NewInt64(ctx, it->count++); args[0] = item; args[1] = index_val; ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); @@ -42385,7 +43204,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, JSValue item, method; if (it->count > 0) { if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); + method = JS_DupValue(ctx, it->next); } else { method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); if (JS_IsException(method)) @@ -42395,13 +43214,13 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); JS_FreeValue(ctx, method); if (JS_IsException(item)) - goto fail; + goto fail_no_close; ret = item; goto done; } - *pdone = true; - if (JS_IteratorClose(ctx, it->obj, false)) + *pdone = TRUE; + if (JS_IteratorClose(ctx, it->obj, FALSE)) ret = JS_EXCEPTION; else ret = JS_UNDEFINED; @@ -42412,19 +43231,19 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, abort(); } -done: + done: it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1; it->executing = 0; return ret; -fail: + fail: /* close the iterator object, preserving pending exception */ - JS_IteratorClose(ctx, it->obj, true); + JS_IteratorClose(ctx, it->obj, TRUE); + fail_no_close: ret = JS_EXCEPTION; goto done; } static const JSCFunctionListEntry js_iterator_funcs[] = { - JS_CFUNC_DEF("concat", 0, js_iterator_concat ), JS_CFUNC_DEF("from", 1, js_iterator_from ), }; @@ -42450,6 +43269,25 @@ static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ), }; +static const JSCFunctionListEntry js_array_unscopables_funcs[] = { + JS_PROP_BOOL_DEF("at", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("copyWithin", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("entries", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("fill", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("find", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findIndex", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLast", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLastIndex", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flat", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flatMap", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("includes", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("keys", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toReversed", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSorted", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSpliced", TRUE, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("values", TRUE, JS_PROP_C_W_E), +}; + static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_DEF("at", 1, js_array_at ), JS_CFUNC_DEF("with", 2, js_array_with ), @@ -42490,6 +43328,7 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_ALIAS_DEF("[Symbol.iterator]", "values" ), JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ), JS_CFUNC_MAGIC_DEF("entries", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ), + JS_OBJECT_DEF("[Symbol.unscopables]", js_array_unscopables_funcs, countof(js_array_unscopables_funcs), JS_PROP_CONFIGURABLE ), }; static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = { @@ -42504,14 +43343,14 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target, { JSValue val, obj; if (argc == 0) { - val = js_int32(0); + val = JS_NewInt32(ctx, 0); } else { val = JS_ToNumeric(ctx, argv[0]); if (JS_IsException(val)) return val; switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_SHORT_BIG_INT: - val = js_int64(JS_VALUE_GET_SHORT_BIG_INT(val)); + val = JS_NewInt64(ctx, JS_VALUE_GET_SHORT_BIG_INT(val)); if (JS_IsException(val)) return val; break; @@ -42521,7 +43360,7 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target, double d; d = js_bigint_to_float64(ctx, p); JS_FreeValue(ctx, val); - val = js_float64(d); + val = JS_NewFloat64(ctx, d); } break; default: @@ -42538,6 +43377,23 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target, } } +#if 0 +static JSValue js_number___toInteger(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[0])); +} + +static JSValue js_number___toLength(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int64_t v; + if (JS_ToLengthFree(ctx, &v, JS_DupValue(ctx, argv[0]))) + return JS_EXCEPTION; + return JS_NewInt64(ctx, v); +} +#endif + static JSValue js_number_isNaN(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -42562,7 +43418,7 @@ static JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val, @@ -42573,7 +43429,7 @@ static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val, return JS_FALSE; if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - return js_bool(is_safe_integer(d)); + return JS_NewBool(ctx, is_safe_integer(d)); } static const JSCFunctionListEntry js_number_funcs[] = { @@ -42586,24 +43442,26 @@ static const JSCFunctionListEntry js_number_funcs[] = { JS_CFUNC_DEF("isSafeInteger", 1, js_number_isSafeInteger ), JS_PROP_DOUBLE_DEF("MAX_VALUE", 1.7976931348623157e+308, 0 ), JS_PROP_DOUBLE_DEF("MIN_VALUE", 5e-324, 0 ), - JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc + JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ), JS_PROP_DOUBLE_DEF("NEGATIVE_INFINITY", -INFINITY, 0 ), JS_PROP_DOUBLE_DEF("POSITIVE_INFINITY", INFINITY, 0 ), JS_PROP_DOUBLE_DEF("EPSILON", 2.220446049250313e-16, 0 ), /* ES6 */ JS_PROP_DOUBLE_DEF("MAX_SAFE_INTEGER", 9007199254740991.0, 0 ), /* ES6 */ JS_PROP_DOUBLE_DEF("MIN_SAFE_INTEGER", -9007199254740991.0, 0 ), /* ES6 */ + //JS_CFUNC_DEF("__toInteger", 1, js_number___toInteger ), + //JS_CFUNC_DEF("__toLength", 1, js_number___toLength ), }; static JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val) { if (JS_IsNumber(this_val)) - return js_dup(this_val); + return JS_DupValue(ctx, this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); if (p->class_id == JS_CLASS_NUMBER) { if (JS_IsNumber(p->u.object_data)) - return js_dup(p->u.object_data); + return JS_DupValue(ctx, p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a number"); @@ -42621,7 +43479,7 @@ static int js_get_radix(JSContext *ctx, JSValueConst val) if (JS_ToInt32Sat(ctx, &radix, val)) return -1; if (radix < 2 || radix > 36) { - JS_ThrowRangeError(ctx, "toString() radix argument must be between 2 and 36"); + JS_ThrowRangeError(ctx, "radix must be between 2 and 36"); return -1; } return radix; @@ -42699,7 +43557,7 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val, if (JS_ToInt32Sat(ctx, &f, argv[0])) return JS_EXCEPTION; if (!isfinite(d)) { - return JS_ToStringFree(ctx, __JS_NewFloat64(d)); + return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d)); } if (JS_IsUndefined(argv[0])) { flags = JS_DTOA_FORMAT_FREE; @@ -42731,7 +43589,7 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (!isfinite(d)) { to_string: - return JS_ToStringFree(ctx, __JS_NewFloat64(d)); + return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d)); } if (p < 1 || p > 100) return JS_ThrowRangeError(ctx, "invalid number of digits"); @@ -42794,7 +43652,7 @@ static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { JSValue val, obj; - val = js_bool(JS_ToBool(ctx, argv[0])); + val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0])); if (!JS_IsUndefined(new_target)) { obj = js_create_from_ctor(ctx, new_target, JS_CLASS_BOOLEAN); if (!JS_IsException(obj)) @@ -42808,7 +43666,7 @@ static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target, static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL) - return js_dup(this_val); + return JS_DupValue(ctx, this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); @@ -42865,11 +43723,11 @@ static int js_string_get_own_property(JSContext *ctx, desc->getter = JS_UNDEFINED; desc->setter = JS_UNDEFINED; } - return true; + return TRUE; } } } - return false; + return FALSE; } static int js_string_define_own_property(JSContext *ctx, @@ -42904,7 +43762,7 @@ static int js_string_define_own_property(JSContext *ctx, return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable"); } } - return true; + return TRUE; } else { def: return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, @@ -42920,10 +43778,10 @@ static int js_string_delete_property(JSContext *ctx, if (__JS_AtomIsTaggedInt(prop)) { idx = __JS_AtomToUInt32(prop); if (idx < js_string_obj_get_length(ctx, obj)) { - return false; + return FALSE; } } - return true; + return TRUE; } static const JSClassExoticMethods js_string_exotic_methods = { @@ -42937,7 +43795,7 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, { JSValue val, obj; if (argc == 0) { - val = js_empty_string(ctx->rt); + val = JS_AtomToString(ctx, JS_ATOM_empty_string); } else { if (JS_IsUndefined(new_target) && JS_IsSymbol(argv[0])) { JSAtomStruct *p = JS_VALUE_GET_PTR(argv[0]); @@ -42956,7 +43814,7 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, JS_FreeValue(ctx, val); } else { JS_SetObjectData(ctx, obj, val); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0); + JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0); } return obj; } else { @@ -42966,14 +43824,15 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val) { - if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING) - return js_dup(this_val); + if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING || + JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING_ROPE) + return JS_DupValue(ctx, this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); if (p->class_id == JS_CLASS_STRING) { if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) - return js_dup(p->u.object_data); + return JS_DupValue(ctx, p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a string"); @@ -42985,12 +43844,6 @@ static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val, int i; StringBuffer b_s, *b = &b_s; - // shortcut for single argument common case - if (argc == 1 && JS_VALUE_GET_TAG(argv[0]) == JS_TAG_INT) { - uint16_t c16 = JS_VALUE_GET_INT(argv[0]); - return js_new_string_char(ctx, c16); - } - string_buffer_init(ctx, b, argc); for(i = 0; i < argc; i++) { @@ -43008,25 +43861,10 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val, { double d; int i, c; - StringBuffer b_s, *b = NULL; - - // shortcut for single argument common case - if (argc == 1 && JS_VALUE_GET_TAG(argv[0]) == JS_TAG_INT) { - c = JS_VALUE_GET_INT(argv[0]); - if (c < 0 || c > 0x10ffff) - goto range_error; - if (c <= 0xffff) { - return js_new_string_char(ctx, c); - } else { - uint16_t c16[2]; - c16[0] = get_hi_surrogate(c); - c16[1] = get_lo_surrogate(c); - return js_new_string16_len(ctx, c16, 2); - } - } + StringBuffer b_s, *b = &b_s; /* XXX: could pre-compute string length if all arguments are JS_TAG_INT */ - b = &b_s; + if (string_buffer_init(ctx, b, argc)) goto fail; for(i = 0; i < argc; i++) { @@ -43037,7 +43875,7 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val, } else { if (JS_ToFloat64(ctx, &d, argv[i])) goto fail; - if (!(d >= 0 && d <= 0x10ffff) || (c = (int)d) != d) + if (isnan(d) || d < 0 || d > 0x10ffff || (c = (int)d) != d) goto range_error; } if (string_buffer_putc(b, c)) @@ -43048,7 +43886,7 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val, range_error: JS_ThrowRangeError(ctx, "invalid code point"); fail: - if (b) string_buffer_free(b); + string_buffer_free(b); return JS_EXCEPTION; } @@ -43119,32 +43957,16 @@ JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, return string_buffer_end(b); } -static JSValue js_string_at(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#if 0 +static JSValue js_string___isSpace(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) { - JSValue val, ret; - JSString *p; - int idx, c; - - val = JS_ToStringCheckObject(ctx, this_val); - if (JS_IsException(val)) - return val; - p = JS_VALUE_GET_STRING(val); - if (JS_ToInt32Sat(ctx, &idx, argv[0])) { - JS_FreeValue(ctx, val); + int c; + if (JS_ToInt32(ctx, &c, argv[0])) return JS_EXCEPTION; - } - if (idx < 0) - idx = p->len + idx; - if (idx < 0 || idx >= p->len) { - ret = JS_UNDEFINED; - } else { - c = string_get(p, idx); - ret = js_new_string_char(ctx, c); - } - JS_FreeValue(ctx, val); - return ret; + return JS_NewBool(ctx, lre_is_space(c)); } +#endif static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -43165,14 +43987,14 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val, ret = JS_NAN; } else { c = string_get(p, idx); - ret = js_int32(c); + ret = JS_NewInt32(ctx, c); } JS_FreeValue(ctx, val); return ret; } static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, int is_at) { JSValue val, ret; JSString *p; @@ -43186,8 +44008,13 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, val); return JS_EXCEPTION; } + if (idx < 0 && is_at) + idx += p->len; if (idx < 0 || idx >= p->len) { - ret = js_empty_string(ctx->rt); + if (is_at) + ret = JS_UNDEFINED; + else + ret = JS_AtomToString(ctx, JS_ATOM_empty_string); } else { c = string_get(p, idx); ret = js_new_string_char(ctx, c); @@ -43215,7 +44042,7 @@ static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; } else { c = string_getc(p, &idx); - ret = js_int32(c); + ret = JS_NewInt32(ctx, c); } JS_FreeValue(ctx, val); return ret; @@ -43234,7 +44061,7 @@ static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val, for (i = 0; i < argc; i++) { if (JS_IsException(r)) break; - r = JS_ConcatString(ctx, r, js_dup(argv[i])); + r = JS_ConcatString(ctx, r, JS_DupValue(ctx, argv[i])); } return r; } @@ -43255,13 +44082,13 @@ static int string_indexof_char(JSString *p, int c, int from) int i, len = p->len; if (p->is_wide_char) { for (i = from; i < len; i++) { - if (str16(p)[i] == c) + if (p->u.str16[i] == c) return i; } } else { if ((c & ~0xff) == 0) { for (i = from; i < len; i++) { - if (str8(p)[i] == (uint8_t)c) + if (p->u.str8[i] == (uint8_t)c) return i; } } @@ -43285,7 +44112,7 @@ static int string_indexof(JSString *p1, JSString *p2, int from) return -1; } -static int64_t string_advance_index(JSString *p, int64_t index, bool unicode) +static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode) { if (!unicode || index >= p->len || !p->is_wide_char) { index++; @@ -43297,78 +44124,77 @@ static int64_t string_advance_index(JSString *p, int64_t index, bool unicode) return index; } +/* return the position of the first invalid character in the string or + -1 if none */ +static int js_string_find_invalid_codepoint(JSString *p) +{ + int i; + if (!p->is_wide_char) + return -1; + for(i = 0; i < p->len; i++) { + uint32_t c = p->u.str16[i]; + if (is_surrogate(c)) { + if (is_hi_surrogate(c) && (i + 1) < p->len + && is_lo_surrogate(p->u.str16[i + 1])) { + i++; + } else { + return i; + } + } + } + return -1; +} + static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue str; - JSValue ret; JSString *p; - uint32_t c, i, n; + BOOL ret; - ret = JS_TRUE; str = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(str)) return JS_EXCEPTION; - p = JS_VALUE_GET_STRING(str); - if (!p->is_wide_char || p->len == 0) - goto done; // by definition well-formed - - for (i = 0, n = p->len; i < n; i++) { - c = str16(p)[i]; - if (!is_surrogate(c)) - continue; - if (is_lo_surrogate(c) || i + 1 == n) - break; - c = str16(p)[++i]; - if (!is_lo_surrogate(c)) - break; - } - - if (i < n) - ret = JS_FALSE; - -done: + ret = (js_string_find_invalid_codepoint(p) < 0); JS_FreeValue(ctx, str); - return ret; + return JS_NewBool(ctx, ret); } static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue str; - JSValue ret; + JSValue str, ret; JSString *p; - uint32_t c, i, n; + int i; str = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(str)) return JS_EXCEPTION; p = JS_VALUE_GET_STRING(str); - if (!p->is_wide_char || p->len == 0) - return str; // by definition well-formed + /* avoid reallocating the string if it is well-formed */ + i = js_string_find_invalid_codepoint(p); + if (i < 0) + return str; - // TODO(bnoordhuis) don't clone when input is well-formed - ret = js_new_string16_len(ctx, str16(p), p->len); + ret = js_new_string16_len(ctx, p->u.str16, p->len); JS_FreeValue(ctx, str); if (JS_IsException(ret)) return JS_EXCEPTION; p = JS_VALUE_GET_STRING(ret); - for (i = 0, n = p->len; i < n; i++) { - c = str16(p)[i]; - if (!is_surrogate(c)) - continue; - if (is_lo_surrogate(c) || i + 1 == n) { - str16(p)[i] = 0xFFFD; - continue; + for (; i < p->len; i++) { + uint32_t c = p->u.str16[i]; + if (is_surrogate(c)) { + if (is_hi_surrogate(c) && (i + 1) < p->len + && is_lo_surrogate(p->u.str16[i + 1])) { + i++; + } else { + p->u.str16[i] = 0xFFFD; + } } - c = str16(p)[++i]; - if (!is_lo_surrogate(c)) - str16(p)[--i] = 0xFFFD; } - return ret; } @@ -43429,7 +44255,7 @@ static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, str); JS_FreeValue(ctx, v); - return js_int32(ret); + return JS_NewInt32(ctx, ret); fail: JS_FreeValue(ctx, str); @@ -43437,7 +44263,7 @@ static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -/* return < 0 if exception or true/false */ +/* return < 0 if exception or TRUE/FALSE */ static int js_is_regexp(JSContext *ctx, JSValueConst obj); static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, @@ -43496,7 +44322,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, done: JS_FreeValue(ctx, str); JS_FreeValue(ctx, v); - return js_bool(ret); + return JS_NewBool(ctx, ret); fail: JS_FreeValue(ctx, str); @@ -43545,7 +44371,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, if (JS_IsUndefined(O) || JS_IsNull(O)) return JS_ThrowTypeError(ctx, "cannot convert to object"); - if (JS_IsObject(regexp)) { + if (!JS_IsUndefined(regexp) && !JS_IsNull(regexp)) { matcher = JS_GetProperty(ctx, regexp, atom); if (JS_IsException(matcher)) return JS_EXCEPTION; @@ -43569,7 +44395,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, str = js_new_string8(ctx, "g"); if (JS_IsException(str)) goto fail; - args[args_len++] = str; + args[args_len++] = JS_VALUE_MAKE_CONST(str); } rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args); JS_FreeValue(ctx, str); @@ -43578,7 +44404,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, S); return JS_EXCEPTION; } - result = JS_InvokeFree(ctx, rx, atom, 1, vc(&S)); + result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S); JS_FreeValue(ctx, S); return result; } @@ -43702,7 +44528,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, JSString *sp, *searchp; StringBuffer b_s, *b = &b_s; int pos, functionalReplace, endOfLastMatch; - bool is_first; + BOOL is_first; if (JS_IsUndefined(O) || JS_IsNull(O)) return JS_ThrowTypeError(ctx, "cannot convert to object"); @@ -43711,7 +44537,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, replaceValue_str = JS_UNDEFINED; repl_str = JS_UNDEFINED; - if (JS_IsObject(searchValue)) { + if (!JS_IsUndefined(searchValue) && !JS_IsNull(searchValue)) { JSValue replacer; if (is_replaceAll) { if (check_regexp_g_flag(ctx, searchValue) < 0) @@ -43744,7 +44570,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, sp = JS_VALUE_GET_STRING(str); searchp = JS_VALUE_GET_STRING(search_str); endOfLastMatch = 0; - is_first = true; + is_first = TRUE; for(;;) { if (unlikely(searchp->len == 0)) { if (is_first) @@ -43768,13 +44594,13 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, } if (functionalReplace) { args[0] = search_str; - args[1] = js_int32(pos); + args[1] = JS_NewInt32(ctx, pos); args[2] = str; repl_str = JS_ToStringFree(ctx, JS_Call(ctx, replaceValue, JS_UNDEFINED, 3, args)); } else { args[0] = search_str; args[1] = str; - args[2] = js_int32(pos); + args[2] = JS_NewInt32(ctx, pos); args[3] = JS_UNDEFINED; args[4] = JS_UNDEFINED; args[5] = replaceValue_str; @@ -43786,7 +44612,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, string_buffer_concat(b, sp, endOfLastMatch, pos); string_buffer_concat_value_free(b, repl_str); endOfLastMatch = pos + searchp->len; - is_first = false; + is_first = FALSE; if (!is_replaceAll) break; } @@ -43822,7 +44648,7 @@ static JSValue js_string_split(JSContext *ctx, JSValueConst this_val, A = JS_UNDEFINED; R = JS_UNDEFINED; - if (JS_IsObject(separator)) { + if (!JS_IsUndefined(separator) && !JS_IsNull(separator)) { JSValue splitter; splitter = JS_GetProperty(ctx, separator, JS_ATOM_Symbol_split); if (JS_IsException(splitter)) @@ -44078,6 +44904,7 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val, len = p->len; if (len == 0 || n == 1) return str; + // XXX: potential arithmetic overflow if (val * len > JS_STRING_LEN_MAX) { JS_ThrowRangeError(ctx, "invalid string length"); goto fail; @@ -44135,22 +44962,22 @@ static int string_prevc(JSString *p, int *pidx) return 0; idx--; if (p->is_wide_char) { - c = str16(p)[idx]; + c = p->u.str16[idx]; if (is_lo_surrogate(c) && idx > 0) { - c1 = str16(p)[idx - 1]; + c1 = p->u.str16[idx - 1]; if (is_hi_surrogate(c1)) { c = from_surrogate(c1, c); idx--; } } } else { - c = str8(p)[idx]; + c = p->u.str8[idx]; } *pidx = idx; return c; } -static bool test_final_sigma(JSString *p, int sigma_pos) +static BOOL test_final_sigma(JSString *p, int sigma_pos) { int k, c1; @@ -44163,14 +44990,14 @@ static bool test_final_sigma(JSString *p, int sigma_pos) break; } if (!lre_is_cased(c1)) - return false; + return FALSE; /* after C: skip case ignorable chars and check there is no cased letter */ k = sigma_pos + 1; for(;;) { if (k >= p->len) - return true; + return TRUE; c1 = string_getc(p, &k); if (!lre_is_case_ignorable(c1)) break; @@ -44178,82 +45005,6 @@ static bool test_final_sigma(JSString *p, int sigma_pos) return !lre_is_cased(c1); } -static int to_utf32_buf(JSContext *ctx, JSString *p, uint32_t **pbuf) -{ - uint32_t *b; - int i, j, n; - - j = -1; - n = p->len; - b = js_malloc(ctx, max_int(1, n) * sizeof(*b)); - if (b) - for (i = j = 0; i < n;) - b[j++] = string_getc(p, &i); - *pbuf = b; - return j; -} - -static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int i, n, an, bn, cmp; - uint32_t *as, *bs, *ts; - JSValue a, b, ret; - - ret = JS_EXCEPTION; - as = NULL; - bs = NULL; - - a = JS_ToStringCheckObject(ctx, this_val); - if (JS_IsException(a)) - return JS_EXCEPTION; - - b = JS_ToString(ctx, argv[0]); - if (JS_IsException(b)) - goto exception; - - an = to_utf32_buf(ctx, JS_VALUE_GET_STRING(a), &as); - if (an == -1) - goto exception; - - bn = to_utf32_buf(ctx, JS_VALUE_GET_STRING(b), &bs); - if (bn == -1) - goto exception; - - // TODO(bnoordhuis) skip normalization when input is latin1 - an = unicode_normalize(&ts, as, an, UNICODE_NFC, ctx, - (DynBufReallocFunc *)js_realloc); - if (an == -1) - goto exception; - js_free(ctx, as); - as = ts; - - // TODO(bnoordhuis) skip normalization when input is latin1 - bn = unicode_normalize(&ts, bs, bn, UNICODE_NFC, ctx, - (DynBufReallocFunc *)js_realloc); - if (bn == -1) - goto exception; - js_free(ctx, bs); - bs = ts; - - n = min_int(an, bn); - for (i = 0; i < n; i++) - if (as[i] != bs[i]) - break; - if (i < n) - cmp = compare_u32(as[i], bs[i]); - else - cmp = compare_u32(an, bn); - ret = js_int32(cmp); - -exception: - JS_FreeValue(ctx, a); - JS_FreeValue(ctx, b); - js_free(ctx, as); - js_free(ctx, bs); - return ret; -} - static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int to_lower) { @@ -44292,18 +45043,35 @@ static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +#ifdef CONFIG_ALL_UNICODE + /* return (-1, NULL) if exception, otherwise (len, buf) */ -static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValue val1) +static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValueConst val1) { JSValue val; - int len; + JSString *p; + uint32_t *buf; + int i, j, len; val = JS_ToString(ctx, val1); if (JS_IsException(val)) return -1; - len = to_utf32_buf(ctx, JS_VALUE_GET_STRING(val), pbuf); + p = JS_VALUE_GET_STRING(val); + len = p->len; + /* UTF32 buffer length is len minus the number of correct surrogates pairs */ + buf = js_malloc(ctx, sizeof(buf[0]) * max_int(len, 1)); + if (!buf) { + JS_FreeValue(ctx, val); + goto fail; + } + for(i = j = 0; i < len;) + buf[j++] = string_getc(p, &i); JS_FreeValue(ctx, val); - return len; + *pbuf = buf; + return j; + fail: + *pbuf = NULL; + return -1; } static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len) @@ -44322,24 +45090,38 @@ static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len) return JS_EXCEPTION; } +static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf, + JSValueConst val, + UnicodeNormalizationEnum n_type) +{ + int buf_len, out_len; + uint32_t *buf, *out_buf; + + buf_len = JS_ToUTF32String(ctx, &buf, val); + if (buf_len < 0) + return -1; + out_len = unicode_normalize(&out_buf, buf, buf_len, n_type, + ctx->rt, (DynBufReallocFunc *)js_realloc_rt); + js_free(ctx, buf); + if (out_len < 0) + return -1; + *pout_buf = out_buf; + return out_len; +} + static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *form, *p; size_t form_len; - int is_compat, buf_len, out_len; + int is_compat, out_len; UnicodeNormalizationEnum n_type; JSValue val; - uint32_t *buf, *out_buf; + uint32_t *out_buf; val = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(val)) return val; - buf = NULL; // appease bogus -Wmaybe-uninitialized warning - buf_len = JS_ToUTF32String(ctx, &buf, val); - JS_FreeValue(ctx, val); - if (buf_len < 0) - return JS_EXCEPTION; if (argc == 0 || JS_IsUndefined(argv[0])) { n_type = UNICODE_NFC; @@ -44351,9 +45133,9 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, if (p[0] != 'N' || p[1] != 'F') goto bad_form; p += 2; - is_compat = false; + is_compat = FALSE; if (*p == 'K') { - is_compat = true; + is_compat = TRUE; p++; } if (*p == 'C' || *p == 'D') { @@ -44365,15 +45147,14 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, form); JS_ThrowRangeError(ctx, "bad normalization form"); fail1: - js_free(ctx, buf); + JS_FreeValue(ctx, val); return JS_EXCEPTION; } JS_FreeCString(ctx, form); } - out_len = unicode_normalize(&out_buf, buf, buf_len, n_type, - ctx->rt, (DynBufReallocFunc *)js_realloc_rt); - js_free(ctx, buf); + out_len = js_string_normalize1(ctx, &out_buf, val, n_type); + JS_FreeValue(ctx, val); if (out_len < 0) return JS_EXCEPTION; val = JS_NewUTF32String(ctx, out_buf, out_len); @@ -44381,6 +45162,82 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, return val; } +/* return < 0, 0 or > 0 */ +static int js_UTF32_compare(const uint32_t *buf1, int buf1_len, + const uint32_t *buf2, int buf2_len) +{ + int i, len, c, res; + len = min_int(buf1_len, buf2_len); + for(i = 0; i < len; i++) { + /* Note: range is limited so a subtraction is valid */ + c = buf1[i] - buf2[i]; + if (c != 0) + return c; + } + if (buf1_len == buf2_len) + res = 0; + else if (buf1_len < buf2_len) + res = -1; + else + res = 1; + return res; +} + +static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue a, b; + int cmp, a_len, b_len; + uint32_t *a_buf, *b_buf; + + a = JS_ToStringCheckObject(ctx, this_val); + if (JS_IsException(a)) + return JS_EXCEPTION; + b = JS_ToString(ctx, argv[0]); + if (JS_IsException(b)) { + JS_FreeValue(ctx, a); + return JS_EXCEPTION; + } + a_len = js_string_normalize1(ctx, &a_buf, a, UNICODE_NFC); + JS_FreeValue(ctx, a); + if (a_len < 0) { + JS_FreeValue(ctx, b); + return JS_EXCEPTION; + } + + b_len = js_string_normalize1(ctx, &b_buf, b, UNICODE_NFC); + JS_FreeValue(ctx, b); + if (b_len < 0) { + js_free(ctx, a_buf); + return JS_EXCEPTION; + } + cmp = js_UTF32_compare(a_buf, a_len, b_buf, b_len); + js_free(ctx, a_buf); + js_free(ctx, b_buf); + return JS_NewInt32(ctx, cmp); +} +#else /* CONFIG_ALL_UNICODE */ +static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue a, b; + int cmp; + + a = JS_ToStringCheckObject(ctx, this_val); + if (JS_IsException(a)) + return JS_EXCEPTION; + b = JS_ToString(ctx, argv[0]); + if (JS_IsException(b)) { + JS_FreeValue(ctx, a); + return JS_EXCEPTION; + } + cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b)); + JS_FreeValue(ctx, a); + JS_FreeValue(ctx, b); + return JS_NewInt32(ctx, cmp); +} +#endif /* !CONFIG_ALL_UNICODE */ + /* also used for String.prototype.valueOf */ static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -44388,11 +45245,52 @@ static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val, return js_thisStringValue(ctx, this_val); } +#if 0 +static JSValue js_string___toStringCheckObject(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_ToStringCheckObject(ctx, argv[0]); +} + +static JSValue js_string___toString(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_ToString(ctx, argv[0]); +} + +static JSValue js_string___advanceStringIndex(JSContext *ctx, JSValueConst + this_val, + int argc, JSValueConst *argv) +{ + JSValue str; + int idx; + BOOL is_unicode; + JSString *p; + + str = JS_ToString(ctx, argv[0]); + if (JS_IsException(str)) + return str; + if (JS_ToInt32Sat(ctx, &idx, argv[1])) { + JS_FreeValue(ctx, str); + return JS_EXCEPTION; + } + is_unicode = JS_ToBool(ctx, argv[2]); + p = JS_VALUE_GET_STRING(str); + if (!is_unicode || (unsigned)idx >= p->len || !p->is_wide_char) { + idx++; + } else { + string_getc(p, &idx); + } + JS_FreeValue(ctx, str); + return JS_NewInt32(ctx, idx); +} +#endif + /* String Iterator */ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic) + BOOL *pdone, int magic) { JSArrayIteratorData *it; uint32_t idx, c, start; @@ -44400,7 +45298,7 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, it = JS_GetOpaque2(ctx, this_val, JS_CLASS_STRING_ITERATOR); if (!it) { - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } if (JS_IsUndefined(it->obj)) @@ -44411,18 +45309,18 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, it->obj); it->obj = JS_UNDEFINED; done: - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } start = idx; c = string_getc(p, (int *)&idx); it->idx = idx; - *pdone = false; + *pdone = FALSE; if (c <= 0xffff) { return js_new_string_char(ctx, c); } else { - return js_new_string16_len(ctx, str16(p) + start, 2); + return js_new_string16_len(ctx, p->u.str16 + start, 2); } } @@ -44447,7 +45345,7 @@ static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSValue str; - JSString *p; + const JSString *p; StringBuffer b_s, *b = &b_s; static struct { const char *tag, *attr; } const defs[] = { { "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL }, @@ -44501,13 +45399,18 @@ static const JSCFunctionListEntry js_string_funcs[] = { JS_CFUNC_DEF("fromCharCode", 1, js_string_fromCharCode ), JS_CFUNC_DEF("fromCodePoint", 1, js_string_fromCodePoint ), JS_CFUNC_DEF("raw", 1, js_string_raw ), + //JS_CFUNC_DEF("__toString", 1, js_string___toString ), + //JS_CFUNC_DEF("__isSpace", 1, js_string___isSpace ), + //JS_CFUNC_DEF("__toStringCheckObject", 1, js_string___toStringCheckObject ), + //JS_CFUNC_DEF("__advanceStringIndex", 3, js_string___advanceStringIndex ), + //JS_CFUNC_DEF("__GetSubstitution", 6, js_string___GetSubstitution ), }; static const JSCFunctionListEntry js_string_proto_funcs[] = { JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ), - JS_CFUNC_DEF("at", 1, js_string_at ), + JS_CFUNC_MAGIC_DEF("at", 1, js_string_charAt, 1 ), JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ), - JS_CFUNC_DEF("charAt", 1, js_string_charAt ), + JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ), JS_CFUNC_DEF("concat", 1, js_string_concat ), JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ), JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ), @@ -44536,8 +45439,6 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = { JS_ALIAS_DEF("trimLeft", "trimStart" ), JS_CFUNC_DEF("toString", 0, js_string_toString ), JS_CFUNC_DEF("valueOf", 0, js_string_toString ), - JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ), - JS_CFUNC_DEF("normalize", 0, js_string_normalize ), JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ), JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ), JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ), @@ -44564,6 +45465,18 @@ static const JSCFunctionListEntry js_string_iterator_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "String Iterator", JS_PROP_CONFIGURABLE ), }; +static const JSCFunctionListEntry js_string_proto_normalize[] = { +#ifdef CONFIG_ALL_UNICODE + JS_CFUNC_DEF("normalize", 0, js_string_normalize ), +#endif + JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ), +}; + +int JS_AddIntrinsicStringNormalize(JSContext *ctx) +{ + return JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize, + countof(js_string_proto_normalize)); +} /* Math */ @@ -44598,13 +45511,13 @@ static double js_fmax(double a, double b) static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { - bool is_max = magic; + BOOL is_max = magic; double r, a; int i; uint32_t tag; if (unlikely(argc == 0)) { - return js_float64(is_max ? NEG_INF : INF); + return __JS_NewFloat64(ctx, is_max ? NEG_INF : INF); } tag = JS_VALUE_GET_TAG(argv[0]); @@ -44623,7 +45536,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, r1 = min_int(r1, a1); } - return js_int32(r1); + return JS_NewInt32(ctx, r1); } else { if (JS_ToFloat64(ctx, &r, argv[0])) return JS_EXCEPTION; @@ -44644,7 +45557,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, } i++; } - return js_number(r); + return JS_NewFloat64(ctx, r); } } @@ -44707,7 +45620,7 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, } } } - return js_float64(r); + return JS_NewFloat64(ctx, r); } static double js_math_f16round(double a) @@ -44732,7 +45645,7 @@ static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; c = a * b; memcpy(&d, &c, sizeof(d)); - return js_int32(d); + return JS_NewInt32(ctx, d); } static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, @@ -44746,51 +45659,63 @@ static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, r = 32; else r = clz32(a); - return js_int32(r); + return JS_NewInt32(ctx, r); } -/* we add one extra limb to avoid having to test for overflows during the sum */ -#define SUM_PRECISE_ACC_LEN 34 - typedef enum { - SUM_PRECISE_STATE_MINUS_ZERO, SUM_PRECISE_STATE_FINITE, SUM_PRECISE_STATE_INFINITY, SUM_PRECISE_STATE_MINUS_INFINITY, /* must be after SUM_PRECISE_STATE_INFINITY */ SUM_PRECISE_STATE_NAN, /* must be after SUM_PRECISE_STATE_MINUS_INFINITY */ } SumPreciseStateEnum; +#define SP_LIMB_BITS 56 +#define SP_RND_BITS (SP_LIMB_BITS - 53) +/* we add one extra limb to avoid having to test for overflows during the sum */ +#define SUM_PRECISE_ACC_LEN 39 + +#define SUM_PRECISE_COUNTER_INIT 250 + typedef struct { - uint64_t acc[SUM_PRECISE_ACC_LEN]; - int n_limbs; /* acc is not necessarily normalized */ SumPreciseStateEnum state; + uint32_t counter; + int n_limbs; /* 'acc' contains n_limbs and is not necessarily + acc[n_limb - 1] may be 0. 0 indicates minus zero + result when state = SUM_PRECISE_STATE_FINITE */ + int64_t acc[SUM_PRECISE_ACC_LEN]; } SumPreciseState; static void sum_precise_init(SumPreciseState *s) { - s->state = SUM_PRECISE_STATE_MINUS_ZERO; - s->acc[0] = 0; - s->n_limbs = 1; + memset(s->acc, 0, sizeof(s->acc)); + s->state = SUM_PRECISE_STATE_FINITE; + s->counter = SUM_PRECISE_COUNTER_INIT; + s->n_limbs = 0; } -#define ADDC64(res, carry_out, op1, op2, carry_in) \ -do { \ - uint64_t __v, __a, __k, __k1; \ - __v = (op1); \ - __a = __v + (op2); \ - __k1 = __a < __v; \ - __k = (carry_in); \ - __a = __a + __k; \ - carry_out = (__a < __k) | __k1; \ - res = __a; \ -} while (0) +static void sum_precise_renorm(SumPreciseState *s) +{ + int64_t v, carry; + int i; + + carry = 0; + for(i = 0; i < s->n_limbs; i++) { + v = s->acc[i] + carry; + s->acc[i] = v & (((uint64_t)1 << SP_LIMB_BITS) - 1); + carry = v >> SP_LIMB_BITS; + } + /* we add a failsafe but it should be never reached in a + reasonnable amount of time */ + if (carry != 0 && s->n_limbs < SUM_PRECISE_ACC_LEN) + s->acc[s->n_limbs++] = carry; +} static void sum_precise_add(SumPreciseState *s, double d) { - uint64_t a, m, a0, carry, acc_sign, a_sign; - int sgn, e, p, n, i; - unsigned shift; - + uint64_t a, m, a0, a1; + int sgn, e, p; + unsigned int shift; + a = float64_as_uint64(d); sgn = a >> 63; e = (a >> 52) & ((1 << 11) - 1); @@ -44812,8 +45737,8 @@ static void sum_precise_add(SumPreciseState *s, double d) } else if (e == 0) { if (likely(m == 0)) { /* zero */ - if (s->state == SUM_PRECISE_STATE_MINUS_ZERO && !sgn) - s->state = SUM_PRECISE_STATE_FINITE; + if (s->n_limbs == 0 && !sgn) + s->n_limbs = 1; } else { /* subnormal */ p = 0; @@ -44821,69 +45746,41 @@ static void sum_precise_add(SumPreciseState *s, double d) goto add; } } else { + /* Note: we sum even if state != SUM_PRECISE_STATE_FINITE to + avoid tests */ m |= (uint64_t)1 << 52; shift = e - 1; - p = shift / 64; - /* 'p' is the position of a0 in acc */ - shift %= 64; + /* 'p' is the position of a0 in acc. The division is normally + implementation as a multiplication by the compiler. */ + p = shift / SP_LIMB_BITS; + shift %= SP_LIMB_BITS; add: - if (s->state >= SUM_PRECISE_STATE_INFINITY) - return; - s->state = SUM_PRECISE_STATE_FINITE; - n = s->n_limbs; - - acc_sign = (int64_t)s->acc[n - 1] >> 63; - - /* sign extend acc */ - for(i = n; i <= p; i++) - s->acc[i] = acc_sign; - - carry = sgn; - a_sign = -sgn; - a0 = m << shift; - ADDC64(s->acc[p], carry, s->acc[p], a0 ^ a_sign, carry); - if (shift >= 12) { - p++; - if (p >= n) - s->acc[p] = acc_sign; - a0 = m >> (64 - shift); - ADDC64(s->acc[p], carry, s->acc[p], a0 ^ a_sign, carry); - } - p++; - if (p >= n) { - n = p; + a0 = (m << shift) & (((uint64_t)1 << SP_LIMB_BITS) - 1); + a1 = m >> (SP_LIMB_BITS - shift); + if (!sgn) { + s->acc[p] += a0; + s->acc[p + 1] += a1; } else { - /* carry */ - for(i = p; i < n; i++) { - /* if 'a' positive: stop condition: carry = 0. - if 'a' negative: stop condition: carry = 1. */ - if (carry == sgn) - goto done; - ADDC64(s->acc[i], carry, s->acc[i], a_sign, carry); - } + s->acc[p] -= a0; + s->acc[p + 1] -= a1; } + s->n_limbs = max_int(s->n_limbs, p + 2); - /* extend the accumulator if needed */ - a0 = carry + acc_sign + a_sign; - /* -1 <= a0 <= 1 (if both acc and a are negative, carry is set) */ - if (a0 != ((int64_t)s->acc[n - 1] >> 63)) { - s->acc[n++] = a0; + if (unlikely(--s->counter == 0)) { + s->counter = SUM_PRECISE_COUNTER_INIT; + sum_precise_renorm(s); } - done: - s->n_limbs = n; } } static double sum_precise_get_result(SumPreciseState *s) { - int n, shift, e, p, is_neg, i; - uint64_t m, addend, carry; - + int n, shift, e, p, is_neg; + uint64_t m, addend; + if (s->state != SUM_PRECISE_STATE_FINITE) { switch(s->state) { default: - case SUM_PRECISE_STATE_MINUS_ZERO: - return -0.0; case SUM_PRECISE_STATE_INFINITY: return INFINITY; case SUM_PRECISE_STATE_MINUS_INFINITY: @@ -44893,30 +45790,53 @@ static double sum_precise_get_result(SumPreciseState *s) } } + sum_precise_renorm(s); + /* extract the sign and absolute value */ - n = s->n_limbs; - is_neg = s->acc[n - 1] >> 63; - if (is_neg) { - /* acc = -acc */ - carry = 1; - for(i = 0; i < n; i++) { - ADDC64(s->acc[i], carry, ~s->acc[i], 0, carry); - } +#if 0 + { + int i; + printf("len=%d:", s->n_limbs); + for(i = s->n_limbs - 1; i >= 0; i--) + printf(" %014lx", s->acc[i]); + printf("\n"); } +#endif + n = s->n_limbs; + /* minus zero result */ + if (n == 0) + return -0.0; + /* normalize */ while (n > 0 && s->acc[n - 1] == 0) n--; /* zero result. The spec tells it is always positive in the finite case */ if (n == 0) return 0.0; + is_neg = (s->acc[n - 1] < 0); + if (is_neg) { + uint64_t v, carry; + int i; + /* negate */ + /* XXX: do it only when needed */ + carry = 1; + for(i = 0; i < n - 1; i++) { + v = (((uint64_t)1 << SP_LIMB_BITS) - 1) - s->acc[i] + carry; + carry = v >> SP_LIMB_BITS; + s->acc[i] = v & (((uint64_t)1 << SP_LIMB_BITS) - 1); + } + s->acc[n - 1] = -s->acc[n - 1] + carry - 1; + while (n > 1 && s->acc[n - 1] == 0) + n--; + } /* subnormal case */ if (n == 1 && s->acc[0] < ((uint64_t)1 << 52)) - return uint64_as_float64(((uint64_t)is_neg << 63) | s->acc[0]); + return uint64_as_float64(((uint64_t)is_neg << 63) | s->acc[0]); /* normal case */ - e = n * 64; + e = n * SP_LIMB_BITS; p = n - 1; m = s->acc[p]; - shift = clz64(m); + shift = clz64(m) - (64 - SP_LIMB_BITS); e = e - shift - 52; if (shift != 0) { m <<= shift; @@ -44924,12 +45844,12 @@ static double sum_precise_get_result(SumPreciseState *s) int shift1; uint64_t nz; p--; - shift1 = 64 - shift; + shift1 = SP_LIMB_BITS - shift; nz = s->acc[p] & (((uint64_t)1 << shift1) - 1); m = m | (s->acc[p] >> shift1) | (nz != 0); } } - if ((m & ((1 << 10) - 1)) == 0) { + if ((m & ((1 << SP_RND_BITS) - 1)) == (1 << (SP_RND_BITS - 1))) { /* see if the LSB part is non zero for the final rounding */ while (p > 0) { p--; @@ -44940,10 +45860,10 @@ static double sum_precise_get_result(SumPreciseState *s) } } /* rounding to nearest with ties to even */ - addend = (1 << 10) - 1 + ((m >> 11) & 1); - m = (m + addend) >> 11; + addend = (1 << (SP_RND_BITS - 1)) - 1 + ((m >> SP_RND_BITS) & 1); + m = (m + addend) >> SP_RND_BITS; /* handle overflow in the rounding */ - if (m == 0) + if (m == ((uint64_t)1 << 53)) e++; if (unlikely(e >= 2047)) { /* infinity */ @@ -44963,7 +45883,7 @@ static JSValue js_math_sumPrecise(JSContext *ctx, JSValueConst this_val, double d; SumPreciseState s_s, *s = &s_s; - iter = JS_GetIterator(ctx, argv[0], /*is_async*/false); + iter = JS_GetIterator(ctx, argv[0], FALSE); if (JS_IsException(iter)) return JS_EXCEPTION; ret = JS_EXCEPTION; @@ -44985,12 +45905,12 @@ static JSValue js_math_sumPrecise(JSContext *ctx, JSValueConst this_val, } else { JS_FreeValue(ctx, item); JS_ThrowTypeError(ctx, "not a number"); - JS_IteratorClose(ctx, iter, /*is_exception_pending*/true); + JS_IteratorClose(ctx, iter, TRUE); goto fail; } sum_precise_add(s, d); } - ret = js_float64(sum_precise_get_result(s)); + ret = __JS_NewFloat64(ctx, sum_precise_get_result(s)); fail: JS_FreeValue(ctx, iter); JS_FreeValue(ctx, next); @@ -45011,7 +45931,9 @@ static uint64_t xorshift64star(uint64_t *pstate) static void js_random_init(JSContext *ctx) { - ctx->random_state = js__gettimeofday_us(); + struct timeval tv; + gettimeofday(&tv, NULL); + ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; /* the state must be non zero */ if (ctx->random_state == 0) ctx->random_state = 1; @@ -45026,7 +45948,7 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val, v = xorshift64star(&ctx->random_state); /* 1.0 <= u.d < 2 */ u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12); - return js_float64(u.d - 1.0); + return __JS_NewFloat64(ctx, u.d - 1.0); } /* use local wrappers for math functions to @@ -45075,7 +45997,7 @@ static const JSCFunctionListEntry js_math_funcs[] = { JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, js_math_cos ), JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, js_math_exp ), JS_CFUNC_SPECIAL_DEF("log", 1, f_f, js_math_log ), - JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_math_pow ), + JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_pow ), JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, js_math_sin ), JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, js_math_tan ), /* ES6 */ @@ -45118,19 +46040,10 @@ static const JSCFunctionListEntry js_math_obj[] = { /* OS dependent. d = argv[0] is in ms from 1970. Return the difference between UTC time and local time 'd' in minutes */ -static int getTimezoneOffset(int64_t time) { -#if defined(_WIN32) - DWORD r; - TIME_ZONE_INFORMATION t; - r = GetTimeZoneInformation(&t); - if (r == TIME_ZONE_ID_INVALID) - return 0; - if (r == TIME_ZONE_ID_DAYLIGHT) - return (int)(t.Bias + t.DaylightBias); - return (int)t.Bias; -#else +static int getTimezoneOffset(int64_t time) +{ time_t ti; - struct tm tm; + int res; time /= 1000; /* convert to seconds */ if (sizeof(time_t) == 4) { @@ -45154,24 +46067,80 @@ static int getTimezoneOffset(int64_t time) { } } ti = time; - localtime_r(&ti, &tm); -#ifdef NO_TM_GMTOFF - struct tm gmt; - gmtime_r(&ti, &gmt); +#if defined(_WIN32) + { + struct tm *tm; + time_t gm_ti, loc_ti; - /* disable DST adjustment on the local tm struct */ - tm.tm_isdst = 0; + tm = gmtime(&ti); + if (!tm) + return 0; + gm_ti = mktime(tm); + + tm = localtime(&ti); + if (!tm) + return 0; + loc_ti = mktime(tm); - return (int)difftime(mktime(&gmt), mktime(&tm)) / 60; + res = (gm_ti - loc_ti) / 60; + } #else - return -tm.tm_gmtoff / 60; -#endif /* NO_TM_GMTOFF */ + { + struct tm tm; + localtime_r(&ti, &tm); + res = -tm.tm_gmtoff / 60; + } #endif + return res; +} + +#if 0 +static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + double dd; + + if (JS_ToFloat64(ctx, &dd, argv[0])) + return JS_EXCEPTION; + if (isnan(dd)) + return __JS_NewFloat64(ctx, dd); + else + return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd)); +} + +static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor, + JSValueConst def_proto) +{ + JSValue proto; + proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype); + if (JS_IsException(proto)) + return proto; + if (!JS_IsObject(proto)) { + JS_FreeValue(ctx, proto); + proto = JS_DupValue(ctx, def_proto); + } + return proto; } +/* create a new date object */ +static JSValue js___date_create(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue obj, proto; + proto = js_get_prototype_from_ctor(ctx, argv[0], argv[1]); + if (JS_IsException(proto)) + return proto; + obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_DATE); + JS_FreeValue(ctx, proto); + if (!JS_IsException(obj)) + JS_SetObjectData(ctx, obj, JS_DupValue(ctx, argv[2])); + return obj; +} +#endif + /* RegExp */ -static void js_regexp_finalizer(JSRuntime *rt, JSValueConst val) +static void js_regexp_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSRegExp *re = &p->u.regexp; @@ -45229,18 +46198,20 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, if ((re_flags & mask) != 0) { bad_flags: JS_FreeCString(ctx, str); - return JS_ThrowSyntaxError(ctx, "invalid regular expression flags"); + goto bad_flags1; } re_flags |= mask; } JS_FreeCString(ctx, str); } - if (re_flags & LRE_FLAG_UNICODE) - if (re_flags & LRE_FLAG_UNICODE_SETS) - return JS_ThrowSyntaxError(ctx, "invalid regular expression flags"); - - str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE)); + /* 'u' and 'v' cannot be both set */ + if ((re_flags & LRE_FLAG_UNICODE_SETS) && (re_flags & LRE_FLAG_UNICODE)) { + bad_flags1: + return JS_ThrowSyntaxError(ctx, "invalid regular expression flags"); + } + + str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS))); if (!str) return JS_EXCEPTION; re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg, @@ -45251,7 +46222,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, return JS_EXCEPTION; } - ret = js_new_string8_len(ctx, (char *)re_bytecode_buf, re_bytecode_len); + ret = js_new_string8_len(ctx, (const char *)re_bytecode_buf, re_bytecode_len); js_free(ctx, re_bytecode_buf); return ret; } @@ -45282,13 +46253,12 @@ static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, re = &p->u.regexp; re->pattern = JS_VALUE_GET_STRING(pattern); re->bytecode = JS_VALUE_GET_STRING(bc); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, js_int32(0), + JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0), JS_PROP_WRITABLE); return obj; } -static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, - bool throw_error) +static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_error) { if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); @@ -45301,19 +46271,19 @@ static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, return NULL; } -/* return < 0 if exception or true/false */ +/* return < 0 if exception or TRUE/FALSE */ static int js_is_regexp(JSContext *ctx, JSValueConst obj) { JSValue m; if (!JS_IsObject(obj)) - return false; + return FALSE; m = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_match); if (JS_IsException(m)) return -1; if (!JS_IsUndefined(m)) return JS_ToBoolFree(ctx, m); - return js_get_regexp(ctx, obj, false) != NULL; + return js_get_regexp(ctx, obj, FALSE) != NULL; } static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, @@ -45334,21 +46304,21 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, new_target = JS_GetActiveFunction(ctx); if (pat_is_regexp && JS_IsUndefined(flags1)) { JSValue ctor; - bool res; + BOOL res; ctor = JS_GetProperty(ctx, pat, JS_ATOM_constructor); if (JS_IsException(ctor)) return ctor; res = js_same_value(ctx, ctor, new_target); JS_FreeValue(ctx, ctor); if (res) - return js_dup(pat); + return JS_DupValue(ctx, pat); } } - re = js_get_regexp(ctx, pat, false); + re = js_get_regexp(ctx, pat, FALSE); if (re) { - pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re->pattern)); + pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern)); if (JS_IsUndefined(flags1)) { - bc = js_dup(JS_MKPTR(JS_TAG_STRING, re->bytecode)); + bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode)); goto no_compilation; } else { flags = JS_ToString(ctx, flags1); @@ -45366,14 +46336,14 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, if (JS_IsException(flags)) goto fail; } else { - flags = js_dup(flags1); + flags = JS_DupValue(ctx, flags1); } } else { - pattern = js_dup(pat); - flags = js_dup(flags1); + pattern = JS_DupValue(ctx, pat); + flags = JS_DupValue(ctx, flags1); } if (JS_IsUndefined(pattern)) { - pattern = js_empty_string(ctx->rt); + pattern = JS_AtomToString(ctx, JS_ATOM_empty_string); } else { val = pattern; pattern = JS_ToString(ctx, val); @@ -45401,21 +46371,21 @@ static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val, JSValueConst pattern1, flags1; JSValue bc, pattern; - re = js_get_regexp(ctx, this_val, true); + re = js_get_regexp(ctx, this_val, TRUE); if (!re) return JS_EXCEPTION; pattern1 = argv[0]; flags1 = argv[1]; - re1 = js_get_regexp(ctx, pattern1, false); + re1 = js_get_regexp(ctx, pattern1, FALSE); if (re1) { if (!JS_IsUndefined(flags1)) return JS_ThrowTypeError(ctx, "flags must be undefined"); - pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re1->pattern)); - bc = js_dup(JS_MKPTR(JS_TAG_STRING, re1->bytecode)); + pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->pattern)); + bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->bytecode)); } else { bc = JS_UNDEFINED; if (JS_IsUndefined(pattern1)) - pattern = js_empty_string(ctx->rt); + pattern = JS_AtomToString(ctx, JS_ATOM_empty_string); else pattern = JS_ToString(ctx, pattern1); if (JS_IsException(pattern)) @@ -45429,15 +46399,36 @@ static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val, re->pattern = JS_VALUE_GET_STRING(pattern); re->bytecode = JS_VALUE_GET_STRING(bc); if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - js_int32(0)) < 0) + JS_NewInt32(ctx, 0)) < 0) return JS_EXCEPTION; - return js_dup(this_val); + return JS_DupValue(ctx, this_val); fail: JS_FreeValue(ctx, pattern); JS_FreeValue(ctx, bc); return JS_EXCEPTION; } +#if 0 +static JSValue js_regexp_get___source(JSContext *ctx, JSValueConst this_val) +{ + JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); + if (!re) + return JS_EXCEPTION; + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern)); +} + +static JSValue js_regexp_get___flags(JSContext *ctx, JSValueConst this_val) +{ + JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); + int flags; + + if (!re) + return JS_EXCEPTION; + flags = lre_get_flags(re->bytecode->u.str8); + return JS_NewInt32(ctx, flags); +} +#endif + static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) { JSRegExp *re; @@ -45451,7 +46442,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP])) goto empty_regex; - re = js_get_regexp(ctx, this_val, true); + re = js_get_regexp(ctx, this_val, TRUE); if (!re) return JS_EXCEPTION; @@ -45512,7 +46503,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - re = js_get_regexp(ctx, this_val, false); + re = js_get_regexp(ctx, this_val, FALSE); if (!re) { if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP])) return JS_UNDEFINED; @@ -45520,61 +46511,39 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP); } - flags = lre_get_flags(str8(re->bytecode)); - return js_bool(flags & mask); + flags = lre_get_flags(re->bytecode->u.str8); + return JS_NewBool(ctx, flags & mask); } +#define RE_FLAG_COUNT 8 + static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val) { - char str[8], *p = str; - int res; - + char str[RE_FLAG_COUNT], *p = str; + int res, i; + static const int flag_atom[RE_FLAG_COUNT] = { + JS_ATOM_hasIndices, + JS_ATOM_global, + JS_ATOM_ignoreCase, + JS_ATOM_multiline, + JS_ATOM_dotAll, + JS_ATOM_unicode, + JS_ATOM_unicodeSets, + JS_ATOM_sticky, + }; + static const char flag_char[RE_FLAG_COUNT] = { 'd', 'g', 'i', 'm', 's', 'u', 'v', 'y' }; + if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "hasIndices")); - if (res < 0) - goto exception; - if (res) - *p++ = 'd'; - res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global)); - if (res < 0) - goto exception; - if (res) - *p++ = 'g'; - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "ignoreCase")); - if (res < 0) - goto exception; - if (res) - *p++ = 'i'; - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "multiline")); - if (res < 0) - goto exception; - if (res) - *p++ = 'm'; - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "dotAll")); - if (res < 0) - goto exception; - if (res) - *p++ = 's'; - res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_unicode)); - if (res < 0) - goto exception; - if (res) - *p++ = 'u'; - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "unicodeSets")); - if (res < 0) - goto exception; - if (res) - *p++ = 'v'; - res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "sticky")); - if (res < 0) - goto exception; - if (res) - *p++ = 'y'; - if (p == str) - return js_empty_string(ctx->rt); - return js_new_string8_len(ctx, str, p - str); + for(i = 0; i < RE_FLAG_COUNT; i++) { + res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, flag_atom[i])); + if (res < 0) + goto exception; + if (res) + *p++ = flag_char[i]; + } + return JS_NewStringLen(ctx, str, p - str); exception: return JS_EXCEPTION; @@ -45605,7 +46574,7 @@ static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -bool lre_check_stack_overflow(void *opaque, size_t alloca_size) +int lre_check_stack_overflow(void *opaque, size_t alloca_size) { JSContext *ctx = opaque; return js_check_stack_overflow(ctx->rt, alloca_size); @@ -45615,7 +46584,7 @@ int lre_check_timeout(void *opaque) { JSContext *ctx = opaque; JSRuntime *rt = ctx->rt; - return (rt->interrupt_handler && + return (rt->interrupt_handler && rt->interrupt_handler(rt, rt->interrupt_opaque)); } @@ -45629,6 +46598,7 @@ void *lre_realloc(void *opaque, void *ptr, size_t size) static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + JSValue str; StringBuffer b_s, *b = &b_s; JSString *p; uint32_t c, i; @@ -45636,10 +46606,13 @@ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, if (!JS_IsString(argv[0])) return JS_ThrowTypeError(ctx, "not a string"); - p = JS_VALUE_GET_STRING(argv[0]); + str = JS_ToString(ctx, argv[0]); /* must call it to linearlize ropes */ + if (JS_IsException(str)) + return JS_EXCEPTION; + p = JS_VALUE_GET_STRING(str); string_buffer_init2(ctx, b, 0, p->is_wide_char); for (i = 0; i < p->len; i++) { - c = p->is_wide_char ? (uint32_t)str16(p)[i] : (uint32_t)str8(p)[i]; + c = string_get(p, i); if (c < 33) { if (c >= 9 && c <= 13) { string_buffer_putc8(b, '\\'); @@ -45663,20 +46636,21 @@ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, hex2: snprintf(s, sizeof(s), "\\x%02x", c); string_buffer_puts8(b, s); - } else if (is_surrogate(c) || lre_is_white_space(c) || c == 0xFEFF) { + } else if (is_surrogate(c) || lre_is_space(c)) { snprintf(s, sizeof(s), "\\u%04x", c); string_buffer_puts8(b, s); } else { string_buffer_putc16(b, c); } } + JS_FreeValue(ctx, str); return string_buffer_end(b); } static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSRegExp *re = js_get_regexp(ctx, this_val, true); + JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); JSString *str; JSValue t, ret, str_val, obj, val, groups; JSValue indices, indices_groups; @@ -45704,7 +46678,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val)) goto fail; - re_bytecode = str8(re->bytecode); + re_bytecode = re->bytecode->u.str8; re_flags = lre_get_flags(re_bytecode); if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) { last_index = 0; @@ -45717,7 +46691,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } shift = str->is_wide_char; - str_buf = str8(str); + str_buf = str->u.str8; if (last_index > str->len) { rc = 2; } else { @@ -45729,7 +46703,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, if (rc >= 0) { if (rc == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - js_int32(0)) < 0) + JS_NewInt32(ctx, 0)) < 0) goto fail; } } else { @@ -45744,7 +46718,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, int prop_flags; if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - js_int32((capture[1] - str_buf) >> shift)) < 0) + JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0) goto fail; } obj = JS_NewArray(ctx); @@ -45773,6 +46747,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, uint8_t **match = &capture[2 * i]; int start = -1; int end = -1; + JSValue val; if (group_name_ptr && i > 0) { if (*group_name_ptr) name = group_name_ptr; @@ -45785,26 +46760,26 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } if (!JS_IsUndefined(indices)) { - JSValue val = JS_UNDEFINED; + val = JS_UNDEFINED; if (start != -1) { val = JS_NewArray(ctx); if (JS_IsException(val)) goto fail; if (JS_DefinePropertyValueUint32(ctx, val, 0, - js_int32(start), + JS_NewInt32(ctx, start), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; } if (JS_DefinePropertyValueUint32(ctx, val, 1, - js_int32(end), + JS_NewInt32(ctx, end), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; } } if (name && !JS_IsUndefined(indices_groups)) { - val = js_dup(val); + val = JS_DupValue(ctx, val); if (JS_DefinePropertyValueStr(ctx, indices_groups, name, val, prop_flags) < 0) { JS_FreeValue(ctx, val); @@ -45817,7 +46792,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } } - JSValue val = JS_UNDEFINED; + val = JS_UNDEFINED; if (start != -1) { val = js_sub_string(ctx, str, start, end); if (JS_IsException(val)) @@ -45826,7 +46801,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, if (name) { if (JS_DefinePropertyValueStr(ctx, groups, name, - js_dup(val), + JS_DupValue(ctx, val), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; @@ -45837,13 +46812,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } - t = groups, groups = JS_UNDEFINED; - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups, - t, prop_flags) < 0) { - goto fail; - } - - t = js_int32((capture[0] - str_buf) >> shift); + t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift); if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0) goto fail; @@ -45851,6 +46820,12 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0) goto fail; + t = groups, groups = JS_UNDEFINED; + if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups, + t, prop_flags) < 0) { + goto fail; + } + if (!JS_IsUndefined(indices)) { t = indices_groups, indices_groups = JS_UNDEFINED; if (JS_DefinePropertyValue(ctx, indices, JS_ATOM_groups, @@ -45877,9 +46852,9 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } /* delete portions of a string that match a given regex */ -static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue arg) +static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg) { - JSRegExp *re = js_get_regexp(ctx, this_val, true); + JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); JSString *str; JSValue str_val, val; uint8_t *re_bytecode; @@ -45900,7 +46875,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar if (JS_IsException(str_val)) goto fail; str = JS_VALUE_GET_STRING(str_val); - re_bytecode = str8(re->bytecode); + re_bytecode = re->bytecode->u.str8; re_flags = lre_get_flags(re_bytecode); if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) { last_index = 0; @@ -45916,7 +46891,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar goto fail; } shift = str->is_wide_char; - str_buf = str8(str); + str_buf = str->u.str8; next_src_pos = 0; for (;;) { if (last_index > str->len) @@ -45928,7 +46903,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar if (ret >= 0) { if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - js_int32(0)) < 0) + JS_NewInt32(ctx, 0)) < 0) goto fail; } } else { @@ -45951,7 +46926,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar next_src_pos = end; if (!(re_flags & LRE_FLAG_GLOBAL)) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - js_int32(end)) < 0) + JS_NewInt32(ctx, end)) < 0) goto fail; break; } @@ -45997,18 +46972,31 @@ static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s) return js_regexp_exec(ctx, r, 1, &s); } +#if 0 +static JSValue js_regexp___RegExpExec(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_RegExpExec(ctx, argv[0], argv[1]); +} +static JSValue js_regexp___RegExpDelete(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_RegExpDelete(ctx, argv[0], argv[1]); +} +#endif + static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue val; - bool ret; + BOOL ret; val = JS_RegExpExec(ctx, this_val, argv[0]); if (JS_IsException(val)) return JS_EXCEPTION; ret = !JS_IsNull(val); JS_FreeValue(ctx, val); - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, @@ -46039,16 +47027,14 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(flags); - // TODO(bnoordhuis) query 'u' flag the same way? global = (-1 != string_indexof_char(p, 'g', 0)); if (!global) { A = JS_RegExpExec(ctx, rx, S); } else { - fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode)); - if (fullUnicode < 0) - goto exception; + fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 || + string_indexof_char(p, 'v', 0) >= 0); - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) goto exception; A = JS_NewArray(ctx); if (JS_IsException(A)) @@ -46065,7 +47051,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, if (JS_IsException(matchStr)) goto exception; isEmpty = JS_IsEmptyString(matchStr); - if (JS_SetPropertyInt64(ctx, A, n++, matchStr) < 0) + if (JS_DefinePropertyValueInt64(ctx, A, n++, matchStr, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; if (isEmpty) { int64_t thisIndex, nextIndex; @@ -46074,7 +47060,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(S); nextIndex = string_advance_index(p, thisIndex, fullUnicode); - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0) goto exception; } } @@ -46099,13 +47085,12 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, typedef struct JSRegExpStringIteratorData { JSValue iterating_regexp; JSValue iterated_string; - bool global; - bool unicode; - int done; + BOOL global; + BOOL unicode; + BOOL done; } JSRegExpStringIteratorData; -static void js_regexp_string_iterator_finalizer(JSRuntime *rt, - JSValueConst val) +static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data; @@ -46130,10 +47115,10 @@ static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, static JSValue js_regexp_string_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic) + BOOL *pdone, int magic) { JSRegExpStringIteratorData *it; - JSValue R, S; + JSValueConst R, S; JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED; JSString *sp; @@ -46141,7 +47126,7 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx, if (!it) goto exception; if (it->done) { - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } R = it->iterating_regexp; @@ -46150,8 +47135,8 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx, if (JS_IsException(match)) goto exception; if (JS_IsNull(match)) { - it->done = true; - *pdone = true; + it->done = TRUE; + *pdone = TRUE; return JS_UNDEFINED; } else if (it->global) { matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, match, 0)); @@ -46164,19 +47149,20 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx, goto exception; sp = JS_VALUE_GET_STRING(S); nextIndex = string_advance_index(sp, thisIndex, it->unicode); - if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) + if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex, + JS_NewInt64(ctx, nextIndex)) < 0) goto exception; } JS_FreeValue(ctx, matchStr); } else { - it->done = true; + it->done = TRUE; } - *pdone = false; + *pdone = FALSE; return match; exception: JS_FreeValue(ctx, match); JS_FreeValue(ctx, matchStr); - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } @@ -46216,7 +47202,8 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, if (JS_ToLengthFree(ctx, &lastIndex, JS_GetProperty(ctx, R, JS_ATOM_lastIndex))) goto exception; - if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, js_int64(lastIndex)) < 0) + if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, + JS_NewInt64(ctx, lastIndex)) < 0) goto exception; iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR); @@ -46229,9 +47216,10 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, it->iterated_string = S; strp = JS_VALUE_GET_STRING(flags); it->global = string_indexof_char(strp, 'g', 0) >= 0; - it->unicode = string_indexof_char(strp, 'u', 0) >= 0; - it->done = false; - JS_SetOpaqueInternal(iter, it); + it->unicode = (string_indexof_char(strp, 'u', 0) >= 0 || + string_indexof_char(strp, 'v', 0) >= 0); + it->done = FALSE; + JS_SetOpaque(iter, it); JS_FreeValue(ctx, C); JS_FreeValue(ctx, flags); @@ -46376,14 +47364,12 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(flags); - // TODO(bnoordhuis) query 'u' flag the same way? fullUnicode = 0; is_global = (-1 != string_indexof_char(p, 'g', 0)); if (is_global) { - fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode)); - if (fullUnicode < 0) - goto exception; - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) + fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 || + string_indexof_char(p, 'v', 0) >= 0); + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) goto exception; } @@ -46413,13 +47399,13 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, if (JS_ToLengthFree(ctx, &thisIndex, JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0) goto exception; nextIndex = string_advance_index(sp, thisIndex, fullUnicode); - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0) goto exception; } } nextSourcePosition = 0; for(j = 0; j < results->len; j++) { - JSValue result; + JSValueConst result; result = results->arr[j]; if (js_get_length32(ctx, &nCaptures, result) < 0) goto exception; @@ -46439,7 +47425,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, tab = JS_NewArray(ctx); if (JS_IsException(tab)) goto exception; - if (JS_DefinePropertyValueInt64(ctx, tab, 0, js_dup(matched), + if (JS_DefinePropertyValueInt64(ctx, tab, 0, JS_DupValue(ctx, matched), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; for(n = 1; n < nCaptures; n++) { @@ -46461,12 +47447,12 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, if (JS_IsException(namedCaptures)) goto exception; if (functionalReplace) { - if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_int32(position), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_NewInt32(ctx, position), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; - if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(str), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, str), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; if (!JS_IsUndefined(namedCaptures)) { - if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } args[0] = JS_UNDEFINED; @@ -46484,7 +47470,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, } args[0] = matched; args[1] = str; - args[2] = js_int32(position); + args[2] = JS_NewInt32(ctx, position); args[3] = tab; args[4] = namedCaptures1; args[5] = rep_val; @@ -46540,8 +47526,8 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val, if (JS_IsException(previousLastIndex)) goto exception; - if (!js_same_value(ctx, previousLastIndex, js_int32(0))) { - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) { + if (!js_same_value(ctx, previousLastIndex, JS_NewInt32(ctx, 0))) { + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) { goto exception; } } @@ -46563,7 +47549,7 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, currentLastIndex); if (JS_IsNull(result)) { - return js_int32(-1); + return JS_NewInt32(ctx, -1); } else { index = JS_GetProperty(ctx, result, JS_ATOM_index); JS_FreeValue(ctx, result); @@ -46608,7 +47594,8 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, if (JS_IsException(flags)) goto exception; strp = JS_VALUE_GET_STRING(flags); - unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0; + unicodeMatching = (string_indexof_char(strp, 'u', 0) >= 0 || + string_indexof_char(strp, 'v', 0) >= 0); if (string_indexof_char(strp, 'y', 0) < 0) { flags = JS_ConcatString3(ctx, "", flags, "y"); if (JS_IsException(flags)) @@ -46643,7 +47630,7 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, goto done; } while (q < size) { - if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, js_int32(q)) < 0) + if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0) goto exception; JS_FreeValue(ctx, z); z = JS_RegExpExec(ctx, splitter, str); @@ -46674,11 +47661,6 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, sub = JS_GetPropertyInt64(ctx, z, i); if (JS_IsException(sub)) goto exception; - if (!JS_IsUndefined(sub)) { - sub = JS_ToStringFree(ctx, sub); - if (JS_IsException(sub)) - goto exception; - } if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; if (lengthA == lim) @@ -46712,6 +47694,8 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_regexp_funcs[] = { JS_CFUNC_DEF("escape", 1, js_regexp_escape ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), + //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ), + //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ), }; static const JSCFunctionListEntry js_regexp_proto_funcs[] = { @@ -46734,6 +47718,8 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = { JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ), JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ), JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ), + //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ), + //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ), }; static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = { @@ -46746,29 +47732,42 @@ void JS_AddIntrinsicRegExpCompiler(JSContext *ctx) ctx->compile_regexp = js_compile_regexp; } -void JS_AddIntrinsicRegExp(JSContext *ctx) +int JS_AddIntrinsicRegExp(JSContext *ctx) { JSValue obj; JS_AddIntrinsicRegExpCompiler(ctx); - ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP], js_regexp_proto_funcs, - countof(js_regexp_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2, - ctx->class_proto[JS_CLASS_REGEXP]); - ctx->regexp_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs)); - + obj = JS_NewCConstructor(ctx, JS_CLASS_REGEXP, "RegExp", + js_regexp_constructor, 2, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_regexp_funcs, countof(js_regexp_funcs), + js_regexp_proto_funcs, countof(js_regexp_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + ctx->regexp_ctor = obj; + ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR], - js_regexp_string_iterator_proto_funcs, - countof(js_regexp_string_iterator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_regexp_string_iterator_proto_funcs, + countof(js_regexp_string_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR])) + return -1; + return 0; } /* JSON */ +static int json_parse_expect(JSParseState *s, int tok) +{ + if (s->token.val != tok) { + /* XXX: dump token correctly in all cases */ + return js_parse_error(s, "expecting '%c'", tok); + } + return json_next_token(s); +} + static JSValue json_parse_value(JSParseState *s) { JSContext *ctx = s->ctx; @@ -46792,17 +47791,15 @@ static JSValue json_parse_value(JSParseState *s) prop_name = JS_ValueToAtom(ctx, s->token.u.str.str); if (prop_name == JS_ATOM_NULL) goto fail; + } else if (s->ext_json && s->token.val == TOK_IDENT) { + prop_name = JS_DupAtom(ctx, s->token.u.ident.atom); } else { - json_parse_error(s, s->token.ptr, "Expected property name or '}'"); + js_parse_error(s, "expecting property name"); goto fail; } if (json_next_token(s)) goto fail1; - if (s->token.val != ':') { - json_parse_error(s, s->token.ptr, "Expected ':' after property name"); - goto fail1; - } - if (json_next_token(s)) + if (json_parse_expect(s, ':')) goto fail1; prop_val = json_parse_value(s); if (JS_IsException(prop_val)) { @@ -46816,17 +47813,15 @@ static JSValue json_parse_value(JSParseState *s) if (ret < 0) goto fail; - if (s->token.val == '}') + if (s->token.val != ',') break; - if (s->token.val != ',') { - json_parse_error(s, s->token.ptr, "Expected ',' or '}' after property value"); - goto fail; - } if (json_next_token(s)) goto fail; + if (s->ext_json && s->token.val == '}') + break; } } - if (json_next_token(s)) + if (json_parse_expect(s, '}')) goto fail; } break; @@ -46841,29 +47836,29 @@ static JSValue json_parse_value(JSParseState *s) if (JS_IsException(val)) goto fail; if (s->token.val != ']') { - for(idx = 0;; idx++) { + idx = 0; + for(;;) { el = json_parse_value(s); if (JS_IsException(el)) goto fail; ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E); if (ret < 0) goto fail; - if (s->token.val == ']') + if (s->token.val != ',') break; - if (s->token.val != ',') { - json_parse_error(s, s->token.ptr, "Expected ',' or ']' after array element"); - goto fail; - } if (json_next_token(s)) goto fail; + idx++; + if (s->ext_json && s->token.val == ']') + break; } } - if (json_next_token(s)) + if (json_parse_expect(s, ']')) goto fail; } break; case TOK_STRING: - val = js_dup(s->token.u.str.str); + val = JS_DupValue(ctx, s->token.u.str.str); if (json_next_token(s)) goto fail; break; @@ -46875,9 +47870,15 @@ static JSValue json_parse_value(JSParseState *s) case TOK_IDENT: if (s->token.u.ident.atom == JS_ATOM_false || s->token.u.ident.atom == JS_ATOM_true) { - val = js_bool(s->token.u.ident.atom == JS_ATOM_true); + val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true); } else if (s->token.u.ident.atom == JS_ATOM_null) { val = JS_NULL; + } else if (s->token.u.ident.atom == JS_ATOM_NaN && s->ext_json) { + /* Note: json5 identifier handling is ambiguous e.g. is + '{ NaN: 1 }' a valid JSON5 production ? */ + val = JS_NewFloat64(s->ctx, NAN); + } else if (s->token.u.ident.atom == JS_ATOM_Infinity && s->ext_json) { + val = JS_NewFloat64(s->ctx, INFINITY); } else { goto def_token; } @@ -46900,13 +47901,14 @@ static JSValue json_parse_value(JSParseState *s) return JS_EXCEPTION; } -/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ -JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename) +JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename, int flags) { JSParseState s1, *s = &s1; JSValue val = JS_UNDEFINED; - js_parse_init(ctx, s, buf, buf_len, filename, 1); + js_parse_init(ctx, s, buf, buf_len, filename); + s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0); if (json_next_token(s)) goto fail; val = json_parse_value(s); @@ -46923,6 +47925,12 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char return JS_EXCEPTION; } +JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename) +{ + return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); +} + static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, JSAtom name, JSValueConst reviver) { @@ -46941,7 +47949,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, if (JS_IsException(val)) return val; if (JS_IsObject(val)) { - is_array = js_is_array(ctx, val); + is_array = JS_IsArray(ctx, val); if (is_array < 0) goto fail; if (is_array) { @@ -46975,7 +47983,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, goto fail; } } - js_free_prop_enum(ctx, atoms, len); + JS_FreePropertyEnum(ctx, atoms, len); atoms = NULL; name_val = JS_AtomToValue(ctx, name); if (JS_IsException(name_val)) @@ -46987,7 +47995,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, JS_FreeValue(ctx, val); return res; fail: - js_free_prop_enum(ctx, atoms, len); + JS_FreePropertyEnum(ctx, atoms, len); JS_FreeValue(ctx, val); return JS_EXCEPTION; } @@ -47035,33 +48043,96 @@ typedef struct JSONStringifyContext { StringBuffer *b; } JSONStringifyContext; -static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) { - JSValue r = JS_ToQuotedString(ctx, val); +static int JS_ToQuotedString(JSContext *ctx, StringBuffer *b, JSValueConst val1) +{ + JSValue val; + JSString *p; + int i; + uint32_t c; + char buf[16]; + + val = JS_ToStringCheckObject(ctx, val1); + if (JS_IsException(val)) + return -1; + p = JS_VALUE_GET_STRING(val); + + if (string_buffer_putc8(b, '\"')) + goto fail; + for(i = 0; i < p->len; ) { + c = string_getc(p, &i); + switch(c) { + case '\t': + c = 't'; + goto quote; + case '\r': + c = 'r'; + goto quote; + case '\n': + c = 'n'; + goto quote; + case '\b': + c = 'b'; + goto quote; + case '\f': + c = 'f'; + goto quote; + case '\"': + case '\\': + quote: + if (string_buffer_putc8(b, '\\')) + goto fail; + if (string_buffer_putc8(b, c)) + goto fail; + break; + default: + if (c < 32 || is_surrogate(c)) { + snprintf(buf, sizeof(buf), "\\u%04x", c); + if (string_buffer_puts8(b, buf)) + goto fail; + } else { + if (string_buffer_putc(b, c)) + goto fail; + } + break; + } + } + if (string_buffer_putc8(b, '\"')) + goto fail; JS_FreeValue(ctx, val); - return r; + return 0; + fail: + JS_FreeValue(ctx, val); + return -1; +} + +static int JS_ToQuotedStringFree(JSContext *ctx, StringBuffer *b, JSValue val) { + int ret = JS_ToQuotedString(ctx, b, val); + JS_FreeValue(ctx, val); + return ret; } static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, - JSValueConst holder, JSValue val, - JSValueConst key) + JSValueConst holder, JSValue val, JSValueConst key) { JSValue v; JSValueConst args[2]; - if (JS_IsObject(val) || JS_IsBigInt(val)) { - JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON); - if (JS_IsException(f)) - goto exception; - if (JS_IsFunction(ctx, f)) { - v = JS_CallFree(ctx, f, val, 1, &key); - JS_FreeValue(ctx, val); - val = v; - if (JS_IsException(val)) - goto exception; - } else { - JS_FreeValue(ctx, f); - } - } + /* check for object.toJSON method */ + /* ECMA specifies this is done only for Object and BigInt */ + if (JS_IsObject(val) || JS_IsBigInt(ctx, val)) { + JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON); + if (JS_IsException(f)) + goto exception; + if (JS_IsFunction(ctx, f)) { + v = JS_CallFree(ctx, f, val, 1, &key); + JS_FreeValue(ctx, val); + val = v; + if (JS_IsException(val)) + goto exception; + } else { + JS_FreeValue(ctx, f); + } + } if (!JS_IsUndefined(jsc->replacer_func)) { args[0] = key; @@ -47078,6 +48149,7 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsFunction(ctx, val)) break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: case JS_TAG_INT: case JS_TAG_FLOAT64: case JS_TAG_BOOL: @@ -47105,7 +48177,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, JSObject *p; int64_t i, len; int cl, ret; - bool has_content; + BOOL has_content; indent1 = JS_UNDEFINED; sep = JS_UNDEFINED; @@ -47131,35 +48203,37 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsException(val)) goto exception; goto concat_primitive; - } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT) { - set_value(ctx, &val, js_dup(p->u.object_data)); + } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT) + { + /* This will thow the same error as for the primitive object */ + set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data)); goto concat_primitive; } - v = js_array_includes(ctx, jsc->stack, 1, vc(&val)); + v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val); if (JS_IsException(v)) goto exception; if (JS_ToBoolFree(ctx, v)) { JS_ThrowTypeError(ctx, "circular reference"); goto exception; } - indent1 = JS_ConcatString(ctx, js_dup(indent), js_dup(jsc->gap)); + indent1 = JS_ConcatString(ctx, JS_DupValue(ctx, indent), JS_DupValue(ctx, jsc->gap)); if (JS_IsException(indent1)) goto exception; if (!JS_IsEmptyString(jsc->gap)) { - sep = JS_ConcatString3(ctx, "\n", js_dup(indent1), ""); + sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), ""); if (JS_IsException(sep)) goto exception; sep1 = js_new_string8(ctx, " "); if (JS_IsException(sep1)) goto exception; } else { - sep = js_dup(jsc->empty); - sep1 = js_dup(jsc->empty); + sep = JS_DupValue(ctx, jsc->empty); + sep1 = JS_DupValue(ctx, jsc->empty); } - v = js_array_push(ctx, jsc->stack, 1, vc(&val), 0); + v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0); if (check_exception_free(ctx, v)) goto exception; - ret = js_is_array(ctx, val); + ret = JS_IsArray(ctx, val); if (ret < 0) goto exception; if (ret) { @@ -47174,7 +48248,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsException(v)) goto exception; /* XXX: could do this string conversion only when needed */ - prop = JS_ToStringFree(ctx, js_int64(i)); + prop = JS_ToStringFree(ctx, JS_NewInt64(ctx, i)); if (JS_IsException(prop)) goto exception; v = js_json_check(ctx, jsc, val, v, prop); @@ -47194,22 +48268,21 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, string_buffer_putc8(jsc->b, ']'); } else { if (!JS_IsUndefined(jsc->property_list)) - tab = js_dup(jsc->property_list); + tab = JS_DupValue(ctx, jsc->property_list); else - tab = js_object_keys(ctx, JS_UNDEFINED, 1, vc(&val), - JS_ITERATOR_KIND_KEY); + tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY); if (JS_IsException(tab)) goto exception; if (js_get_length64(ctx, &len, tab)) goto exception; string_buffer_putc8(jsc->b, '{'); - has_content = false; + has_content = FALSE; for(i = 0; i < len; i++) { JS_FreeValue(ctx, prop); prop = JS_GetPropertyInt64(ctx, tab, i); if (JS_IsException(prop)) goto exception; - v = JS_GetPropertyValue(ctx, val, js_dup(prop)); + v = JS_GetPropertyValue(ctx, val, JS_DupValue(ctx, prop)); if (JS_IsException(v)) goto exception; v = js_json_check(ctx, jsc, val, v, prop); @@ -47218,21 +48291,19 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (!JS_IsUndefined(v)) { if (has_content) string_buffer_putc8(jsc->b, ','); - prop = JS_ToQuotedStringFree(ctx, prop); - if (JS_IsException(prop)) { + string_buffer_concat_value(jsc->b, sep); + if (JS_ToQuotedString(ctx, jsc->b, prop)) { JS_FreeValue(ctx, v); goto exception; } - string_buffer_concat_value(jsc->b, sep); - string_buffer_concat_value(jsc->b, prop); string_buffer_putc8(jsc->b, ':'); string_buffer_concat_value(jsc->b, sep1); if (js_json_to_str(ctx, jsc, val, v, indent1)) goto exception; - has_content = true; + has_content = TRUE; } } - if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) { + if (has_content && !JS_IsEmptyString(jsc->gap)) { string_buffer_putc8(jsc->b, '\n'); string_buffer_concat_value(jsc->b, indent); } @@ -47251,10 +48322,8 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, concat_primitive: switch (JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_STRING: - val = JS_ToQuotedStringFree(ctx, val); - if (JS_IsException(val)) - goto exception; - goto concat_value; + case JS_TAG_STRING_ROPE: + return JS_ToQuotedStringFree(ctx, jsc->b, val); case JS_TAG_FLOAT64: if (!isfinite(JS_VALUE_GET_FLOAT64(val))) { val = JS_NULL; @@ -47267,7 +48336,8 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, return string_buffer_concat_value_free(jsc->b, val); case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: - JS_ThrowTypeError(ctx, "BigInt are forbidden in JSON.stringify"); + /* reject big numbers: use toJSON method to override */ + JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt"); goto exception; default: JS_FreeValue(ctx, val); @@ -47298,7 +48368,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, jsc->property_list = JS_UNDEFINED; jsc->gap = JS_UNDEFINED; jsc->b = &b_s; - jsc->empty = js_empty_string(ctx->rt); + jsc->empty = JS_AtomToString(ctx, JS_ATOM_empty_string); ret = JS_UNDEFINED; wrapper = JS_UNDEFINED; @@ -47309,7 +48379,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, if (JS_IsFunction(ctx, replacer)) { jsc->replacer_func = replacer; } else { - res = js_is_array(ctx, replacer); + res = JS_IsArray(ctx, replacer); if (res < 0) goto exception; if (res) { @@ -47344,7 +48414,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, continue; } present = js_array_includes(ctx, jsc->property_list, - 1, vc(&v)); + 1, (JSValueConst *)&v); if (JS_IsException(present)) { JS_FreeValue(ctx, v); goto exception; @@ -47357,7 +48427,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, } } } - space = js_dup(space0); + space = JS_DupValue(ctx, space0); if (JS_IsObject(space)) { JSObject *p = JS_VALUE_GET_OBJ(space); if (p->class_id == JS_CLASS_NUMBER) { @@ -47374,12 +48444,12 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, int n; if (JS_ToInt32Clamp(ctx, &n, space, 0, 10, 0)) goto exception; - jsc->gap = JS_NewStringLen(ctx, " ", n); + jsc->gap = js_new_string8_len(ctx, " ", n); } else if (JS_IsString(space)) { JSString *p = JS_VALUE_GET_STRING(space); jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10)); } else { - jsc->gap = js_dup(jsc->empty); + jsc->gap = JS_DupValue(ctx, jsc->empty); } JS_FreeValue(ctx, space); if (JS_IsException(jsc->gap)) @@ -47388,9 +48458,9 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, if (JS_IsException(wrapper)) goto exception; if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string, - js_dup(obj), JS_PROP_C_W_E) < 0) + JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0) goto exception; - val = js_dup(obj); + val = JS_DupValue(ctx, obj); val = js_json_check(ctx, jsc, wrapper, val, jsc->empty); if (JS_IsException(val)) @@ -47435,10 +48505,10 @@ static const JSCFunctionListEntry js_json_obj[] = { JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicJSON(JSContext *ctx) +int JS_AddIntrinsicJSON(JSContext *ctx) { /* add JSON as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); } /* Reflect */ @@ -47468,7 +48538,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val, tab = build_arg_list(ctx, &len, array_arg); if (!tab) return JS_EXCEPTION; - ret = JS_CallConstructor2(ctx, func, new_target, len, vc(tab)); + ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab); free_arg_list(ctx, tab, len); return ret; } @@ -47491,7 +48561,7 @@ static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, @@ -47512,7 +48582,7 @@ static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; - ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, false); + ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, FALSE); JS_FreeAtom(ctx, atom); return ret; } @@ -47536,7 +48606,7 @@ static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, @@ -47558,23 +48628,24 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; - ret = JS_SetPropertyInternal2(ctx, obj, atom, js_dup(val), receiver, 0); + ret = JS_SetPropertyInternal(ctx, obj, atom, + JS_DupValue(ctx, val), receiver, 0); JS_FreeAtom(ctx, atom); if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { int ret; - ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], false); + ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE); if (ret < 0) return JS_EXCEPTION; else - return js_bool(ret); + return JS_NewBool(ctx, ret); } static JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val, @@ -47610,7 +48681,7 @@ static const JSCFunctionListEntry js_reflect_obj[] = { /* Proxy */ -static void js_proxy_finalizer(JSRuntime *rt, JSValueConst val) +static void js_proxy_finalizer(JSRuntime *rt, JSValue val) { JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY); if (s) { @@ -47661,7 +48732,7 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, return s; } -static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) +static JSValue js_proxy_get_prototype(JSContext *ctx, JSValueConst obj) { JSProxyData *s; JSValue method, ret, proto1; @@ -47672,7 +48743,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) return JS_EXCEPTION; if (JS_IsUndefined(method)) return JS_GetPrototype(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, vc(&s->target)); + ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); if (JS_IsException(ret)) return ret; if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL && @@ -47691,7 +48762,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) JS_FreeValue(ctx, ret); return JS_EXCEPTION; } - if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) { + if (!js_same_value(ctx, proto1, ret)) { JS_FreeValue(ctx, proto1); fail: JS_FreeValue(ctx, ret); @@ -47702,34 +48773,28 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) return ret; } -static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, - JSValueConst proto_val, bool throw_flag) +static int js_proxy_set_prototype(JSContext *ctx, JSValueConst obj, + JSValueConst proto_val) { JSProxyData *s; JSValue method, ret, proto1; JSValueConst args[2]; - bool res; + BOOL res; int res2; s = get_proxy_method(ctx, &method, obj, JS_ATOM_setPrototypeOf); if (!s) return -1; if (JS_IsUndefined(method)) - return JS_SetPrototypeInternal(ctx, s->target, proto_val, throw_flag); + return JS_SetPrototypeInternal(ctx, s->target, proto_val, FALSE); args[0] = s->target; args[1] = proto_val; ret = JS_CallFree(ctx, method, s->handler, 2, args); if (JS_IsException(ret)) return -1; res = JS_ToBoolFree(ctx, ret); - if (!res) { - if (throw_flag) { - JS_ThrowTypeError(ctx, "proxy: bad prototype"); - return -1; - } else { - return false; - } - } + if (!res) + return FALSE; res2 = JS_IsExtensible(ctx, s->target); if (res2 < 0) return -1; @@ -47737,21 +48802,21 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, proto1 = JS_GetPrototype(ctx, s->target); if (JS_IsException(proto1)) return -1; - if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) { + if (!js_same_value(ctx, proto_val, proto1)) { JS_FreeValue(ctx, proto1); JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); return -1; } JS_FreeValue(ctx, proto1); } - return true; + return TRUE; } -static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj) +static int js_proxy_is_extensible(JSContext *ctx, JSValueConst obj) { JSProxyData *s; JSValue method, ret; - bool res; + BOOL res; int res2; s = get_proxy_method(ctx, &method, obj, JS_ATOM_isExtensible); @@ -47759,7 +48824,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj) return -1; if (JS_IsUndefined(method)) return JS_IsExtensible(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, vc(&s->target)); + ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); if (JS_IsException(ret)) return -1; res = JS_ToBoolFree(ctx, ret); @@ -47773,11 +48838,11 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj) return res; } -static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj) +static int js_proxy_prevent_extensions(JSContext *ctx, JSValueConst obj) { JSProxyData *s; JSValue method, ret; - bool res; + BOOL res; int res2; s = get_proxy_method(ctx, &method, obj, JS_ATOM_preventExtensions); @@ -47785,7 +48850,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj) return -1; if (JS_IsUndefined(method)) return JS_PreventExtensions(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, vc(&s->target)); + ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); if (JS_IsException(ret)) return -1; res = JS_ToBoolFree(ctx, ret); @@ -47805,10 +48870,10 @@ static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) { JSProxyData *s; JSValue method, ret1, atom_val; - int res; + int ret, res; JSObject *p; JSValueConst args[2]; - bool ret, res2; + BOOL res2; s = get_proxy_method(ctx, &method, obj, JS_ATOM_has); if (!s) @@ -47859,7 +48924,7 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, return JS_EXCEPTION; /* Note: recursion is possible thru the prototype of s->target */ if (JS_IsUndefined(method)) - return JS_GetPropertyInternal(ctx, s->target, atom, receiver, false); + return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE); atom_val = JS_AtomToValue(ctx, atom); if (JS_IsException(atom_val)) { JS_FreeValue(ctx, method); @@ -47900,16 +48965,16 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, { JSProxyData *s; JSValue method, ret1, atom_val; - bool ret; - int res; + int ret, res; JSValueConst args[4]; s = get_proxy_method(ctx, &method, obj, JS_ATOM_set); if (!s) return -1; if (JS_IsUndefined(method)) { - return JS_SetPropertyInternal2(ctx, s->target, atom, - js_dup(value), receiver, flags); + return JS_SetPropertyInternal(ctx, s->target, atom, + JS_DupValue(ctx, value), receiver, + flags); } atom_val = JS_AtomToValue(ctx, atom); if (JS_IsException(atom_val)) { @@ -47962,30 +49027,30 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val, if (JS_IsException(ret)) return ret; if (flags & JS_PROP_HAS_GET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(getter), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, getter), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_SET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(setter), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_VALUE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(val), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_WRITABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - js_bool(flags & JS_PROP_WRITABLE), + JS_NewBool(ctx, flags & JS_PROP_WRITABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_ENUMERABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - js_bool(flags & JS_PROP_ENUMERABLE), + JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_CONFIGURABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - js_bool(flags & JS_PROP_CONFIGURABLE), + JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE), JS_PROP_C_W_E); } return ret; @@ -48035,7 +49100,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible) goto fail; } - ret = false; + ret = FALSE; } else { int flags1, extensible_target; extensible_target = JS_IsExtensible(ctx, s->target); @@ -48048,6 +49113,14 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc if (res < 0) return -1; + /* convert the result_desc.flags to property flags */ + if (result_desc.flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { + result_desc.flags |= JS_PROP_GETSET; + } else { + result_desc.flags |= JS_PROP_NORMAL; + } + result_desc.flags &= (JS_PROP_C_W_E | JS_PROP_TMASK); + if (target_desc_ret) { /* convert result_desc.flags to defineProperty flags */ flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; @@ -48078,7 +49151,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc return -1; } } - ret = true; + ret = TRUE; if (pdesc) { *pdesc = result_desc; } else { @@ -48090,16 +49163,16 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst val, - JSValueConst getter, - JSValueConst setter, int flags) + JSValueConst getter, JSValueConst setter, + int flags) { JSProxyData *s; JSValue method, ret1, prop_val, desc_val; - int res; + int res, ret; JSObject *p; JSValueConst args[3]; JSPropertyDescriptor desc; - bool ret, setting_not_configurable; + BOOL setting_not_configurable; s = get_proxy_method(ctx, &method, obj, JS_ATOM_defineProperty); if (!s) @@ -48146,13 +49219,11 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, if (!p->extensible || setting_not_configurable) goto fail; } else { - if (!check_define_prop_flags(desc.flags, flags) || - ((desc.flags & JS_PROP_CONFIGURABLE) && setting_not_configurable)) { + if (!check_define_prop_flags(desc.flags, flags)) goto fail1; - } - if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { - if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == - JS_PROP_GETSET) { + /* do the missing check from check_define_prop_flags() */ + if (!(desc.flags & JS_PROP_CONFIGURABLE)) { + if ((desc.flags & JS_PROP_TMASK) == JS_PROP_GETSET) { if ((flags & JS_PROP_HAS_GET) && !js_same_value(ctx, getter, desc.getter)) { goto fail1; @@ -48161,27 +49232,26 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, !js_same_value(ctx, setter, desc.setter)) { goto fail1; } - } - } else if (flags & JS_PROP_HAS_VALUE) { - if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == - JS_PROP_WRITABLE && !(flags & JS_PROP_WRITABLE)) { - /* missing-proxy-check feature */ - goto fail1; - } else if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 && - !js_same_value(ctx, val, desc.value)) { - goto fail1; + } else if (!(desc.flags & JS_PROP_WRITABLE)) { + if ((flags & JS_PROP_HAS_VALUE) && + !js_same_value(ctx, val, desc.value)) { + goto fail1; + } } } - if (flags & JS_PROP_HAS_WRITABLE) { - if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | - JS_PROP_WRITABLE)) == JS_PROP_WRITABLE) { - /* proxy-missing-checks */ - fail1: - js_free_desc(ctx, &desc); - fail: - JS_ThrowTypeError(ctx, "proxy: inconsistent defineProperty"); - return -1; - } + + /* additional checks */ + if ((desc.flags & JS_PROP_CONFIGURABLE) && setting_not_configurable) + goto fail1; + + if ((desc.flags & JS_PROP_TMASK) != JS_PROP_GETSET && + (desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == JS_PROP_WRITABLE && + (flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { + fail1: + js_free_desc(ctx, &desc); + fail: + JS_ThrowTypeError(ctx, "proxy: inconsistent defineProperty"); + return -1; } js_free_desc(ctx, &desc); } @@ -48193,8 +49263,7 @@ static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, { JSProxyData *s; JSValue method, ret, atom_val; - int res2, is_extensible; - bool res; + int res, res2, is_extensible; JSValueConst args[2]; s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty); @@ -48272,7 +49341,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, JS_VALUE_GET_OBJ(s->target), JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK); } - prop_array = JS_CallFree(ctx, method, s->handler, 1, vc(&s->target)); + prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); if (JS_IsException(prop_array)) return -1; tab = NULL; @@ -48300,7 +49369,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, if (atom == JS_ATOM_NULL) goto fail; tab[i].atom = atom; - tab[i].is_enumerable = false; /* XXX: redundant? */ + tab[i].is_enumerable = FALSE; /* XXX: redundant? */ } /* check duplicate properties (XXX: inefficient, could store the @@ -48343,7 +49412,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, } /* mark the property as found */ if (!is_extensible) - tab[idx].is_enumerable = true; + tab[idx].is_enumerable = TRUE; } } } @@ -48357,14 +49426,14 @@ static int js_proxy_get_own_property_names(JSContext *ctx, } } - js_free_prop_enum(ctx, tab2, len2); + JS_FreePropertyEnum(ctx, tab2, len2); JS_FreeValue(ctx, prop_array); *ptab = tab; *plen = len; return 0; fail: - js_free_prop_enum(ctx, tab2, len2); - js_free_prop_enum(ctx, tab, len); + JS_FreePropertyEnum(ctx, tab2, len2); + JS_FreePropertyEnum(ctx, tab, len); JS_FreeValue(ctx, prop_array); return -1; } @@ -48419,7 +49488,7 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, return JS_EXCEPTION; if (!s->is_func) { JS_FreeValue(ctx, method); - return JS_ThrowTypeErrorNotAFunction(ctx); + return JS_ThrowTypeError(ctx, "not a function"); } if (JS_IsUndefined(method)) return JS_Call(ctx, s->target, this_obj, argc, argv); @@ -48438,22 +49507,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, return ret; } -static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) -{ - JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); - if (!s) - return false; - - if (js_check_stack_overflow(ctx->rt, 0)) { - JS_ThrowStackOverflow(ctx); - return -1; - } +/* `js_resolve_proxy`: resolve the proxy chain + `*pval` is updated with to ultimate proxy target + `throw_exception` controls whether exceptions are thown or not + - return -1 in case of error + - otherwise return 0 + */ +static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) { + int depth = 0; + JSObject *p; + JSProxyData *s; - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - return -1; + while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) { + p = JS_VALUE_GET_OBJ(*pval); + if (p->class_id != JS_CLASS_PROXY) + break; + if (depth++ > 1000) { + if (throw_exception) + JS_ThrowStackOverflow(ctx); + return -1; + } + s = p->u.opaque; + if (s->is_revoked) { + if (throw_exception) + JS_ThrowTypeErrorRevokedProxy(ctx); + return -1; + } + *pval = s->target; } - return js_is_array(ctx, s->target); + return 0; } static const JSClassExoticMethods js_proxy_exotic_methods = { @@ -48464,6 +49546,10 @@ static const JSClassExoticMethods js_proxy_exotic_methods = { .has_property = js_proxy_has, .get_property = js_proxy_get, .set_property = js_proxy_set, + .get_prototype = js_proxy_get_prototype, + .set_prototype = js_proxy_set_prototype, + .is_extensible = js_proxy_is_extensible, + .prevent_extensions = js_proxy_prevent_extensions, }; static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, @@ -48487,25 +49573,25 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - s->target = js_dup(target); - s->handler = js_dup(handler); + s->target = JS_DupValue(ctx, target); + s->handler = JS_DupValue(ctx, handler); s->is_func = JS_IsFunction(ctx, target); - s->is_revoked = false; - JS_SetOpaqueInternal(obj, s); + s->is_revoked = FALSE; + JS_SetOpaque(obj, s); JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target)); return obj; } static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + JSValue *func_data) { JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY); if (s) { /* We do not free the handler and target in case they are referenced as constants in the C call stack */ - s->is_revoked = true; - JS_FreeValue(ctx, unsafe_unconst(func_data[0])); + s->is_revoked = TRUE; + JS_FreeValue(ctx, func_data[0]); func_data[0] = JS_NULL; } return JS_UNDEFINED; @@ -48549,59 +49635,36 @@ static const JSClassShortDef js_proxy_class_def[] = { { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */ }; -void JS_AddIntrinsicProxy(JSContext *ctx) +int JS_AddIntrinsicProxy(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) { - init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, - countof(js_proxy_class_def)); + if (init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, + countof(js_proxy_class_def))) + return -1; rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods; rt->class_array[JS_CLASS_PROXY].call = js_proxy_call; } - obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2, - JS_CFUNC_constructor, 0); - JS_SetConstructorBit(ctx, obj1, true); - JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, - countof(js_proxy_funcs)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", - obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); -} - -bool JS_IsProxy(JSValueConst val) -{ - if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { - JSObject *p = JS_VALUE_GET_OBJ(val); - return p->class_id == JS_CLASS_PROXY; - } - return false; -} - -static JSValue js_get_proxy_field(JSContext *ctx, JSValueConst proxy, - int offset) -{ - if (JS_VALUE_GET_TAG(proxy) == JS_TAG_OBJECT) { - JSObject *p = JS_VALUE_GET_OBJ(proxy); - if (p->class_id == JS_CLASS_PROXY) { - JSProxyData *s = JS_GetOpaque(proxy, JS_CLASS_PROXY); - if (s->is_revoked) - return JS_ThrowTypeErrorRevokedProxy(ctx); - return js_dup(*(JSValue *)((char *)s + offset)); - } - } - return JS_ThrowTypeError(ctx, "not a proxy"); -} - -JSValue JS_GetProxyTarget(JSContext *ctx, JSValueConst proxy) -{ - return js_get_proxy_field(ctx, proxy, offsetof(JSProxyData, target)); -} - -JSValue JS_GetProxyHandler(JSContext *ctx, JSValueConst proxy) -{ - return js_get_proxy_field(ctx, proxy, offsetof(JSProxyData, handler)); + /* additional fields: name, length */ + obj1 = JS_NewCFunction3(ctx, js_proxy_constructor, "Proxy", 2, + JS_CFUNC_constructor, 0, + ctx->function_proto, countof(js_proxy_funcs) + 2); + if (JS_IsException(obj1)) + return -1; + JS_SetConstructorBit(ctx, obj1, TRUE); + if (JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, + countof(js_proxy_funcs))) + goto fail; + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", + obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + return 0; + fail: + JS_FreeValue(ctx, obj1); + return -1; } /* Symbol */ @@ -48622,19 +49685,19 @@ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, return JS_EXCEPTION; p = JS_VALUE_GET_STRING(str); } - return JS_NewSymbolInternal(ctx, p, JS_ATOM_TYPE_SYMBOL); + return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL); } static JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL) - return js_dup(this_val); + return JS_DupValue(ctx, this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); if (p->class_id == JS_CLASS_SYMBOL) { if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_SYMBOL) - return js_dup(p->u.object_data); + return JS_DupValue(ctx, p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a symbol"); @@ -48648,7 +49711,7 @@ static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val, if (JS_IsException(val)) return val; /* XXX: use JS_ToStringInternal() with a flags */ - ret = js_string_constructor(ctx, JS_UNDEFINED, 1, vc(&val)); + ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val); JS_FreeValue(ctx, val); return ret; } @@ -48694,7 +49757,7 @@ static JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val, str = JS_ToString(ctx, argv[0]); if (JS_IsException(str)) return JS_EXCEPTION; - return JS_NewSymbolInternal(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL); + return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL); } static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, @@ -48707,16 +49770,102 @@ static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_PTR(argv[0]); if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL) return JS_UNDEFINED; - return js_dup(JS_MKPTR(JS_TAG_STRING, p)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); } static const JSCFunctionListEntry js_symbol_funcs[] = { JS_CFUNC_DEF("for", 1, js_symbol_for ), JS_CFUNC_DEF("keyFor", 1, js_symbol_keyFor ), + JS_PROP_ATOM_DEF("toPrimitive", JS_ATOM_Symbol_toPrimitive, 0), + JS_PROP_ATOM_DEF("iterator", JS_ATOM_Symbol_iterator, 0), + JS_PROP_ATOM_DEF("match", JS_ATOM_Symbol_match, 0), + JS_PROP_ATOM_DEF("matchAll", JS_ATOM_Symbol_matchAll, 0), + JS_PROP_ATOM_DEF("replace", JS_ATOM_Symbol_replace, 0), + JS_PROP_ATOM_DEF("search", JS_ATOM_Symbol_search, 0), + JS_PROP_ATOM_DEF("split", JS_ATOM_Symbol_split, 0), + JS_PROP_ATOM_DEF("toStringTag", JS_ATOM_Symbol_toStringTag, 0), + JS_PROP_ATOM_DEF("isConcatSpreadable", JS_ATOM_Symbol_isConcatSpreadable, 0), + JS_PROP_ATOM_DEF("hasInstance", JS_ATOM_Symbol_hasInstance, 0), + JS_PROP_ATOM_DEF("species", JS_ATOM_Symbol_species, 0), + JS_PROP_ATOM_DEF("unscopables", JS_ATOM_Symbol_unscopables, 0), + JS_PROP_ATOM_DEF("asyncIterator", JS_ATOM_Symbol_asyncIterator, 0), }; /* Set/Map/WeakSet/WeakMap */ +static BOOL js_weakref_is_target(JSValueConst val) +{ + switch (JS_VALUE_GET_TAG(val)) { + case JS_TAG_OBJECT: + return TRUE; + case JS_TAG_SYMBOL: + { + JSAtomStruct *p = JS_VALUE_GET_PTR(val); + if (p->atom_type == JS_ATOM_TYPE_SYMBOL && + p->hash != JS_ATOM_HASH_PRIVATE) + return TRUE; + } + break; + default: + break; + } + return FALSE; +} + +/* JS_UNDEFINED is considered as a live weakref */ +/* XXX: add a specific JSWeakRef value type ? */ +static BOOL js_weakref_is_live(JSValueConst val) +{ + int *pref_count; + if (JS_IsUndefined(val)) + return TRUE; + pref_count = JS_VALUE_GET_PTR(val); + return (*pref_count != 0); +} + +/* 'val' can be JS_UNDEFINED */ +static void js_weakref_free(JSRuntime *rt, JSValue val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { + JSObject *p = JS_VALUE_GET_OBJ(val); + assert(p->weakref_count >= 1); + p->weakref_count--; + /* 'mark' is tested to avoid freeing the object structure when + it is about to be freed in a cycle or in + free_zero_refcount() */ + if (p->weakref_count == 0 && p->header.ref_count == 0 && + p->header.mark == 0) { + js_free_rt(rt, p); + } + } else if (JS_VALUE_GET_TAG(val) == JS_TAG_SYMBOL) { + JSString *p = JS_VALUE_GET_STRING(val); + assert(p->hash >= 1); + p->hash--; + if (p->hash == 0 && p->header.ref_count == 0) { + /* can remove the dummy structure */ + js_free_rt(rt, p); + } + } +} + +/* val must be an object, a symbol or undefined (see + js_weakref_is_target). */ +static JSValue js_weakref_new(JSContext *ctx, JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { + JSObject *p = JS_VALUE_GET_OBJ(val); + p->weakref_count++; + } else if (JS_VALUE_GET_TAG(val) == JS_TAG_SYMBOL) { + JSString *p = JS_VALUE_GET_STRING(val); + /* XXX: could return an exception if too many references */ + assert(p->hash < JS_ATOM_HASH_MASK - 2); + p->hash++; + } else { + assert(JS_IsUndefined(val)); + } + return JS_VALUE_CONST_CAST(val); +} + #define MAGIC_SET (1 << 0) #define MAGIC_WEAK (1 << 1) @@ -48726,7 +49875,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, JSMapState *s; JSValue obj, adder = JS_UNDEFINED, iter = JS_UNDEFINED, next_method = JS_UNDEFINED; JSValueConst arr; - bool is_set, is_weak; + BOOL is_set, is_weak; is_set = magic & MAGIC_SET; is_weak = ((magic & MAGIC_WEAK) != 0); @@ -48738,12 +49887,16 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, goto fail; init_list_head(&s->records); s->is_weak = is_weak; - JS_SetOpaqueInternal(obj, s); - s->hash_size = 1; - s->hash_table = js_malloc(ctx, sizeof(s->hash_table[0]) * s->hash_size); + if (is_weak) { + s->weakref_header.weakref_type = JS_WEAKREF_TYPE_MAP; + list_add_tail(&s->weakref_header.link, &ctx->rt->weakref_list); + } + JS_SetOpaque(obj, s); + s->hash_bits = 1; + s->hash_size = 1U << s->hash_bits; + s->hash_table = js_mallocz(ctx, sizeof(s->hash_table[0]) * s->hash_size); if (!s->hash_table) goto fail; - init_list_head(&s->hash_table[0]); s->record_count_threshold = 4; arr = JS_UNDEFINED; @@ -48751,7 +49904,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, arr = argv[0]; if (!JS_IsUndefined(arr) && !JS_IsNull(arr)) { JSValue item, ret; - int done; + BOOL done; adder = JS_GetProperty(ctx, obj, is_set ? JS_ATOM_add : JS_ATOM_set); if (JS_IsException(adder)) @@ -48761,7 +49914,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, goto fail; } - iter = JS_GetIterator(ctx, arr, false); + iter = JS_GetIterator(ctx, arr, FALSE); if (JS_IsException(iter)) goto fail; next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); @@ -48775,10 +49928,10 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, if (done) break; if (is_set) { - ret = JS_Call(ctx, adder, obj, 1, vc(&item)); + ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item); if (JS_IsException(ret)) { JS_FreeValue(ctx, item); - goto fail; + goto fail_close; } } else { JSValue key, value; @@ -48803,7 +49956,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, JS_FreeValue(ctx, item); JS_FreeValue(ctx, key); JS_FreeValue(ctx, value); - goto fail; + goto fail_close; } JS_FreeValue(ctx, key); JS_FreeValue(ctx, value); @@ -48816,11 +49969,10 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, JS_FreeValue(ctx, adder); } return obj; + fail_close: + /* close the iterator object, preserving pending exception */ + JS_IteratorClose(ctx, iter, TRUE); fail: - if (JS_IsObject(iter)) { - /* close the iterator object, preserving pending exception */ - JS_IteratorClose(ctx, iter, true); - } JS_FreeValue(ctx, next_method); JS_FreeValue(ctx, iter); JS_FreeValue(ctx, adder); @@ -48832,132 +49984,150 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, static JSValue map_normalize_key(JSContext *ctx, JSValue key) { uint32_t tag = JS_VALUE_GET_TAG(key); - // convert -0.0 to +0.0 - // not a leak; |key| and return value are not heap-allocated - if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) - return js_int32(0); + /* convert -0.0 to +0.0 */ + if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) { + key = JS_NewInt32(ctx, 0); + } return key; } static JSValueConst map_normalize_key_const(JSContext *ctx, JSValueConst key) { - return safe_const(map_normalize_key(ctx, unsafe_unconst(key))); + return JS_VALUE_MAKE_CONST(map_normalize_key(ctx, JS_VALUE_CONST_CAST(key))); +} + +/* hash multipliers, same as the Linux kernel (see Knuth vol 3, + section 6.4, exercise 9) */ +#define HASH_MUL32 0x61C88647 +#define HASH_MUL64 UINT64_C(0x61C8864680B583EB) + +static uint32_t map_hash32(uint32_t a, int hash_bits) +{ + return (a * HASH_MUL32) >> (32 - hash_bits); +} + +static uint32_t map_hash64(uint64_t a, int hash_bits) +{ + return (a * HASH_MUL64) >> (64 - hash_bits); +} + +static uint32_t map_hash_pointer(uintptr_t a, int hash_bits) +{ +#ifdef JS_PTR64 + return map_hash64(a, hash_bits); +#else + return map_hash32(a, hash_bits); +#endif } /* XXX: better hash ? */ -static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) +/* precondition: 1 <= hash_bits <= 32 */ +static uint32_t map_hash_key(JSValueConst key, int hash_bits) { uint32_t tag = JS_VALUE_GET_NORM_TAG(key); uint32_t h; double d; - JSFloat64Union u; - JSBigInt *r; - + JSBigInt *p; + JSBigIntBuf buf; + switch(tag) { case JS_TAG_BOOL: - h = JS_VALUE_GET_INT(key); + h = map_hash32(JS_VALUE_GET_INT(key) ^ JS_TAG_BOOL, hash_bits); break; case JS_TAG_STRING: - h = hash_string(JS_VALUE_GET_STRING(key), 0); + h = map_hash32(hash_string(JS_VALUE_GET_STRING(key), 0) ^ JS_TAG_STRING, hash_bits); + break; + case JS_TAG_STRING_ROPE: + h = map_hash32(hash_string_rope(key, 0) ^ JS_TAG_STRING, hash_bits); break; case JS_TAG_OBJECT: case JS_TAG_SYMBOL: - h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163; + h = map_hash_pointer((uintptr_t)JS_VALUE_GET_PTR(key) ^ tag, hash_bits); break; case JS_TAG_INT: d = JS_VALUE_GET_INT(key); goto hash_float64; - case JS_TAG_SHORT_BIG_INT: - d = JS_VALUE_GET_SHORT_BIG_INT(key); - goto hash_float64; - case JS_TAG_BIG_INT: - r = JS_VALUE_GET_PTR(key); - h = hash_string8((void *)r->tab, r->len * sizeof(*r->tab), 0); - break; case JS_TAG_FLOAT64: d = JS_VALUE_GET_FLOAT64(key); /* normalize the NaN */ if (isnan(d)) - d = NAN; + d = JS_FLOAT64_NAN; hash_float64: - u.d = d; - h = (u.u32[0] ^ u.u32[1]) * 3163; - return h ^= JS_TAG_FLOAT64; + h = map_hash64(float64_as_uint64(d) ^ JS_TAG_FLOAT64, hash_bits); + break; + case JS_TAG_SHORT_BIG_INT: + p = js_bigint_set_short(&buf, key); + goto hash_bigint; + case JS_TAG_BIG_INT: + p = JS_VALUE_GET_PTR(key); + hash_bigint: + { + int i; + h = 1; + for(i = p->len - 1; i >= 0; i--) { + h = h * 263 + p->tab[i]; + } + /* the final step is necessary otherwise h mod n only + depends of p->tab[i] mod n */ + h = map_hash32(h ^ JS_TAG_BIG_INT, hash_bits); + } + break; default: h = 0; break; } - h ^= tag; return h; } static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s, JSValueConst key) { - struct list_head *el; JSMapRecord *mr; uint32_t h; - h = map_hash_key(ctx, key) & (s->hash_size - 1); - list_for_each(el, &s->hash_table[h]) { - mr = list_entry(el, JSMapRecord, hash_link); - if (js_same_value_zero(ctx, mr->key, key)) - return mr; + h = map_hash_key(key, s->hash_bits); + for(mr = s->hash_table[h]; mr != NULL; mr = mr->hash_next) { + if (mr->empty || (s->is_weak && !js_weakref_is_live(mr->key))) { + /* cannot match */ + } else { + if (js_same_value_zero(ctx, mr->key, key)) + return mr; + } } return NULL; } static void map_hash_resize(JSContext *ctx, JSMapState *s) { - uint32_t new_hash_size, i, h; - struct list_head *new_hash_table, *el; - JSMapRecord *mr; + uint32_t new_hash_size, h; + int new_hash_bits; + struct list_head *el; + JSMapRecord *mr, **new_hash_table; /* XXX: no reporting of memory allocation failure */ - if (s->hash_size == 1) - new_hash_size = 4; - else - new_hash_size = s->hash_size * 2; + new_hash_bits = min_int(s->hash_bits + 1, 31); + new_hash_size = 1U << new_hash_bits; new_hash_table = js_realloc(ctx, s->hash_table, sizeof(new_hash_table[0]) * new_hash_size); if (!new_hash_table) return; - for(i = 0; i < new_hash_size; i++) - init_list_head(&new_hash_table[i]); + memset(new_hash_table, 0, sizeof(new_hash_table[0]) * new_hash_size); list_for_each(el, &s->records) { mr = list_entry(el, JSMapRecord, link); - if (!mr->empty) { - h = map_hash_key(ctx, mr->key) & (new_hash_size - 1); - list_add_tail(&mr->hash_link, &new_hash_table[h]); + if (mr->empty || (s->is_weak && !js_weakref_is_live(mr->key))) { + } else { + h = map_hash_key(mr->key, new_hash_bits); + mr->hash_next = new_hash_table[h]; + new_hash_table[h] = mr; } } s->hash_table = new_hash_table; + s->hash_bits = new_hash_bits; s->hash_size = new_hash_size; s->record_count_threshold = new_hash_size * 2; } -static JSWeakRefRecord **get_first_weak_ref(JSValueConst key) -{ - switch (JS_VALUE_GET_TAG(key)) { - case JS_TAG_OBJECT: - { - JSObject *p = JS_VALUE_GET_OBJ(key); - return &p->first_weak_ref; - } - break; - case JS_TAG_SYMBOL: - { - JSAtomStruct *p = JS_VALUE_GET_PTR(key); - return &p->first_weak_ref; - } - break; - default: - abort(); - } - return NULL; // pacify compiler -} - static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s, JSValueConst key) { @@ -48968,23 +50138,15 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s, if (!mr) return NULL; mr->ref_count = 1; - mr->map = s; - mr->empty = false; + mr->empty = FALSE; if (s->is_weak) { - JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr)); - if (!wr) { - js_free(ctx, mr); - return NULL; - } - wr->kind = JS_WEAK_REF_KIND_MAP; - wr->u.map_record = mr; - insert_weakref_record(key, wr); - mr->key = unsafe_unconst(key); + mr->key = js_weakref_new(ctx, key); } else { - mr->key = js_dup(key); + mr->key = JS_DupValue(ctx, key); } - h = map_hash_key(ctx, key) & (s->hash_size - 1); - list_add_tail(&mr->hash_link, &s->hash_table[h]); + h = map_hash_key(key, s->hash_bits); + mr->hash_next = s->hash_table[h]; + s->hash_table[h] = mr; list_add_tail(&mr->link, &s->records); s->record_count++; if (s->record_count >= s->record_count_threshold) { @@ -48993,33 +50155,25 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s, return mr; } -/* Remove the weak reference from the object weak - reference list. we don't use a doubly linked list to - save space, assuming a given object has few weak - references to it */ -static void delete_map_weak_ref(JSRuntime *rt, JSMapRecord *mr) +static JSMapRecord *set_add_record(JSContext *ctx, JSMapState *s, + JSValueConst key) { - JSWeakRefRecord **pwr, *wr; - - pwr = get_first_weak_ref(mr->key); - for(;;) { - wr = *pwr; - assert(wr != NULL); - if (wr->kind == JS_WEAK_REF_KIND_MAP && wr->u.map_record == mr) - break; - pwr = &wr->next_weak_ref; - } - *pwr = wr->next_weak_ref; - js_free_rt(rt, wr); + JSMapRecord *mr; + mr = map_add_record(ctx, s, key); + if (!mr) + return NULL; + mr->value = JS_UNDEFINED; + return mr; } -static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) +/* warning: the record must be removed from the hash table before */ +static void map_delete_record_internal(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) { if (mr->empty) return; - list_del(&mr->hash_link); + if (s->is_weak) { - delete_map_weak_ref(rt, mr); + js_weakref_free(rt, mr->key); } else { JS_FreeValueRT(rt, mr->key); } @@ -49029,7 +50183,7 @@ static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) js_free_rt(rt, mr); } else { /* keep a zombie record for iterators */ - mr->empty = true; + mr->empty = TRUE; mr->key = JS_UNDEFINED; mr->value = JS_UNDEFINED; } @@ -49046,21 +50200,51 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr) } } +static void map_delete_weakrefs(JSRuntime *rt, JSWeakRefHeader *wh) +{ + JSMapState *s = container_of(wh, JSMapState, weakref_header); + struct list_head *el, *el1; + JSMapRecord *mr1, **pmr; + uint32_t h; + + list_for_each_safe(el, el1, &s->records) { + JSMapRecord *mr = list_entry(el, JSMapRecord, link); + if (!js_weakref_is_live(mr->key)) { + + /* even if key is not live it can be hashed as a pointer */ + h = map_hash_key(mr->key, s->hash_bits); + pmr = &s->hash_table[h]; + for(;;) { + mr1 = *pmr; + /* the entry may already be removed from the hash + table if the map was resized */ + if (mr1 == NULL) + goto done; + if (mr1 == mr) + break; + pmr = &mr1->hash_next; + } + /* remove from the hash table */ + *pmr = mr1->hash_next; + done: + map_delete_record_internal(rt, s, mr); + } + } +} + static JSValue js_map_set(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; JSValueConst key, value; - int is_set; if (!s) return JS_EXCEPTION; - is_set = (magic & MAGIC_SET); key = map_normalize_key_const(ctx, argv[0]); - if (s->is_weak && !is_valid_weakref_target(key)) - return JS_ThrowTypeError(ctx, "invalid value used as %s key", is_set ? "WeakSet" : "WeakMap"); - if (is_set) + if (s->is_weak && !js_weakref_is_target(key)) + return JS_ThrowTypeError(ctx, "invalid value used as %s key", (magic & MAGIC_SET) ? "WeakSet" : "WeakMap"); + if (magic & MAGIC_SET) value = JS_UNDEFINED; else value = argv[1]; @@ -49072,8 +50256,8 @@ static JSValue js_map_set(JSContext *ctx, JSValueConst this_val, if (!mr) return JS_EXCEPTION; } - mr->value = js_dup(value); - return js_dup(this_val); + mr->value = JS_DupValue(ctx, value); + return JS_DupValue(ctx, this_val); } static JSValue js_map_get(JSContext *ctx, JSValueConst this_val, @@ -49090,13 +50274,43 @@ static JSValue js_map_get(JSContext *ctx, JSValueConst this_val, if (!mr) return JS_UNDEFINED; else - return js_dup(mr->value); + return JS_DupValue(ctx, mr->value); +} + +/* return JS_TRUE or JS_FALSE */ +static JSValue map_delete_record(JSContext *ctx, JSMapState *s, JSValueConst key) +{ + JSMapRecord *mr, **pmr; + uint32_t h; + + key = map_normalize_key_const(ctx, key); + + h = map_hash_key(key, s->hash_bits); + pmr = &s->hash_table[h]; + for(;;) { + mr = *pmr; + if (mr == NULL) + return JS_FALSE; + if (mr->empty || (s->is_weak && !js_weakref_is_live(mr->key))) { + /* not valid */ + } else { + if (js_same_value_zero(ctx, mr->key, key)) + break; + } + pmr = &mr->hash_next; + } + + /* remove from the hash table */ + *pmr = mr->hash_next; + + map_delete_record_internal(ctx->rt, s, mr); + return JS_TRUE; } static JSValue js_map_getOrInsert(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { - bool computed = magic & 1; + BOOL computed = magic & 1; JSClassID class_id = magic >> 1; JSMapState *s = JS_GetOpaque2(ctx, this_val, class_id); JSMapRecord *mr; @@ -49105,10 +50319,10 @@ static JSValue js_map_getOrInsert(JSContext *ctx, JSValueConst this_val, if (!s) return JS_EXCEPTION; - if (computed && check_function(ctx, argv[1])) - return JS_EXCEPTION; + if (computed && !JS_IsFunction(ctx, argv[1])) + return JS_ThrowTypeError(ctx, "not a function"); key = map_normalize_key_const(ctx, argv[0]); - if (s->is_weak && !is_valid_weakref_target(key)) + if (s->is_weak && !js_weakref_is_target(key)) return JS_ThrowTypeError(ctx, "invalid value used as WeakMap key"); mr = map_find_record(ctx, s, key); if (!mr) { @@ -49116,11 +50330,9 @@ static JSValue js_map_getOrInsert(JSContext *ctx, JSValueConst this_val, value = JS_Call(ctx, argv[1], JS_UNDEFINED, 1, &key); if (JS_IsException(value)) return JS_EXCEPTION; - mr = map_find_record(ctx, s, key); - if (mr) - map_delete_record(ctx->rt, s, mr); + map_delete_record(ctx, s, key); } else { - value = js_dup(argv[1]); + value = JS_DupValue(ctx, argv[1]); } mr = map_add_record(ctx, s, key); if (!mr) { @@ -49129,7 +50341,7 @@ static JSValue js_map_getOrInsert(JSContext *ctx, JSValueConst this_val, } mr->value = value; } - return js_dup(mr->value); + return JS_DupValue(ctx, mr->value); } static JSValue js_map_has(JSContext *ctx, JSValueConst this_val, @@ -49143,24 +50355,16 @@ static JSValue js_map_has(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; key = map_normalize_key_const(ctx, argv[0]); mr = map_find_record(ctx, s, key); - return js_bool(mr != NULL); + return JS_NewBool(ctx, mr != NULL); } static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); - JSMapRecord *mr; - JSValueConst key; - if (!s) return JS_EXCEPTION; - key = map_normalize_key_const(ctx, argv[0]); - mr = map_find_record(ctx, s, key); - if (!mr) - return JS_FALSE; - map_delete_record(ctx->rt, s, mr); - return JS_TRUE; + return map_delete_record(ctx, s, argv[0]); } static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val, @@ -49172,9 +50376,13 @@ static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val, if (!s) return JS_EXCEPTION; + + /* remove from the hash table */ + memset(s->hash_table, 0, sizeof(s->hash_table[0]) * s->hash_size); + list_for_each_safe(el, el1, &s->records) { mr = list_entry(el, JSMapRecord, link); - map_delete_record(ctx->rt, s, mr); + map_delete_record_internal(ctx->rt, s, mr); } return JS_UNDEFINED; } @@ -49184,7 +50392,7 @@ static JSValue js_map_get_size(JSContext *ctx, JSValueConst this_val, int magic) JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); if (!s) return JS_EXCEPTION; - return js_uint32(s->record_count); + return JS_NewUint32(ctx, s->record_count); } static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, @@ -49213,13 +50421,13 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, if (!mr->empty) { mr->ref_count++; /* must duplicate in case the record is deleted */ - args[1] = js_dup(mr->key); + args[1] = JS_DupValue(ctx, mr->key); if (magic) args[0] = args[1]; else - args[0] = js_dup(mr->value); - args[2] = unsafe_unconst(this_val); - ret = JS_Call(ctx, func, this_arg, 3, vc(args)); + args[0] = JS_DupValue(ctx, mr->value); + args[2] = JS_VALUE_CONST_CAST(this_val); + ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args); JS_FreeValue(ctx, args[0]); if (!magic) JS_FreeValue(ctx, args[1]); @@ -49235,24 +50443,26 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int is_map) { - JSValue res, iter, next, groups, k, v, prop; JSValueConst cb, args[2]; + JSValue res, iter, next, groups, key, v, prop; + JSAtom key_atom = JS_ATOM_NULL; int64_t idx; - int done; + BOOL done; // "is function?" check must be observed before argv[0] is accessed cb = argv[1]; if (check_function(ctx, cb)) return JS_EXCEPTION; - iter = JS_GetIterator(ctx, argv[0], /*is_async*/false); + iter = JS_GetIterator(ctx, argv[0], /*is_async*/FALSE); if (JS_IsException(iter)) return JS_EXCEPTION; - k = JS_UNDEFINED; + key = JS_UNDEFINED; + key_atom = JS_ATOM_NULL; v = JS_UNDEFINED; prop = JS_UNDEFINED; groups = JS_UNDEFINED; @@ -49261,11 +50471,19 @@ static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, if (JS_IsException(next)) goto exception; - groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0); + if (is_map) { + groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0); + } else { + groups = JS_NewObjectProto(ctx, JS_NULL); + } if (JS_IsException(groups)) goto exception; for (idx = 0; ; idx++) { + if (idx >= MAX_SAFE_INTEGER) { + JS_ThrowTypeError(ctx, "too many elements"); + goto iterator_close_exception; + } v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(v)) goto exception; @@ -49273,12 +50491,21 @@ static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, break; // v is JS_UNDEFINED args[0] = v; - args[1] = js_int64(idx); - k = JS_Call(ctx, cb, ctx->global_obj, 2, args); - if (JS_IsException(k)) - goto exception; + args[1] = JS_NewInt64(ctx, idx); + key = JS_Call(ctx, cb, ctx->global_obj, 2, args); + if (JS_IsException(key)) + goto iterator_close_exception; - prop = js_map_get(ctx, groups, 1, vc(&k), 0); + if (is_map) { + prop = js_map_get(ctx, groups, 1, (JSValueConst *)&key, 0); + } else { + key_atom = JS_ValueToAtom(ctx, key); + JS_FreeValue(ctx, key); + key = JS_UNDEFINED; + if (key_atom == JS_ATOM_NULL) + goto iterator_close_exception; + prop = JS_GetProperty(ctx, groups, key_atom); + } if (JS_IsException(prop)) goto exception; @@ -49286,24 +50513,33 @@ static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, prop = JS_NewArray(ctx); if (JS_IsException(prop)) goto exception; - args[0] = k; - args[1] = prop; - res = js_map_set(ctx, groups, 2, args, 0); - if (JS_IsException(res)) - goto exception; - JS_FreeValue(ctx, res); + if (is_map) { + args[0] = key; + args[1] = prop; + res = js_map_set(ctx, groups, 2, args, 0); + if (JS_IsException(res)) + goto exception; + JS_FreeValue(ctx, res); + } else { + prop = JS_DupValue(ctx, prop); + if (JS_DefinePropertyValue(ctx, groups, key_atom, prop, + JS_PROP_C_W_E) < 0) { + goto exception; + } + } } - - res = js_array_push(ctx, prop, 1, vc(&v), /*unshift*/0); + res = js_array_push(ctx, prop, 1, (JSValueConst *)&v, /*unshift*/0); if (JS_IsException(res)) goto exception; // res is an int64 JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, k); + JS_FreeValue(ctx, key); + JS_FreeAtom(ctx, key_atom); JS_FreeValue(ctx, v); prop = JS_UNDEFINED; - k = JS_UNDEFINED; + key = JS_UNDEFINED; + key_atom = JS_ATOM_NULL; v = JS_UNDEFINED; } @@ -49311,9 +50547,12 @@ static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, next); return groups; -exception: + iterator_close_exception: + JS_IteratorClose(ctx, iter, TRUE); + exception: + JS_FreeAtom(ctx, key_atom); JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, k); + JS_FreeValue(ctx, key); JS_FreeValue(ctx, v); JS_FreeValue(ctx, groups); JS_FreeValue(ctx, iter); @@ -49321,7 +50560,7 @@ static JSValue js_map_groupBy(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static void js_map_finalizer(JSRuntime *rt, JSValueConst val) +static void js_map_finalizer(JSRuntime *rt, JSValue val) { JSObject *p; JSMapState *s; @@ -49337,7 +50576,7 @@ static void js_map_finalizer(JSRuntime *rt, JSValueConst val) mr = list_entry(el, JSMapRecord, link); if (!mr->empty) { if (s->is_weak) - delete_map_weak_ref(rt, mr); + js_weakref_free(rt, mr->key); else JS_FreeValueRT(rt, mr->key); JS_FreeValueRT(rt, mr->value); @@ -49345,12 +50584,14 @@ static void js_map_finalizer(JSRuntime *rt, JSValueConst val) js_free_rt(rt, mr); } js_free_rt(rt, s->hash_table); + if (s->is_weak) { + list_del(&s->weakref_header.link); + } js_free_rt(rt, s); } } -static void js_map_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) +static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSMapState *s; @@ -49359,10 +50600,10 @@ static void js_map_mark(JSRuntime *rt, JSValueConst val, s = p->u.map_state; if (s) { - assert(!s->is_weak); list_for_each(el, &s->records) { mr = list_entry(el, JSMapRecord, link); - JS_MarkValue(rt, mr->key, mark_func); + if (!s->is_weak) + JS_MarkValue(rt, mr->key, mark_func); JS_MarkValue(rt, mr->value, mark_func); } } @@ -49376,7 +50617,7 @@ typedef struct JSMapIteratorData { JSMapRecord *cur_record; } JSMapIteratorData; -static void js_map_iterator_finalizer(JSRuntime *rt, JSValueConst val) +static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val) { JSObject *p; JSMapIteratorData *it; @@ -49427,10 +50668,10 @@ static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, enum_obj); goto fail; } - it->obj = js_dup(this_val); + it->obj = JS_DupValue(ctx, this_val); it->kind = kind; it->cur_record = NULL; - JS_SetOpaqueInternal(enum_obj, it); + JS_SetOpaque(enum_obj, it); return enum_obj; fail: return JS_EXCEPTION; @@ -49438,7 +50679,7 @@ static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val, static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int *pdone, int magic) + BOOL *pdone, int magic) { JSMapIteratorData *it; JSMapState *s; @@ -49447,7 +50688,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, it = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP_ITERATOR + magic); if (!it) { - *pdone = false; + *pdone = FALSE; return JS_EXCEPTION; } if (JS_IsUndefined(it->obj)) @@ -49469,7 +50710,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, it->obj = JS_UNDEFINED; done: /* end of enumeration */ - *pdone = true; + *pdone = TRUE; return JS_UNDEFINED; } mr = list_entry(el, JSMapRecord, link); @@ -49482,10 +50723,10 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, /* lock the record so that it won't be freed */ mr->ref_count++; it->cur_record = mr; - *pdone = false; + *pdone = FALSE; if (it->kind == JS_ITERATOR_KIND_KEY) { - return js_dup(mr->key); + return JS_DupValue(ctx, mr->key); } else { JSValueConst args[2]; args[0] = mr->key; @@ -49494,218 +50735,175 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, else args[1] = mr->value; if (it->kind == JS_ITERATOR_KIND_VALUE) { - return js_dup(args[1]); + return JS_DupValue(ctx, args[1]); } else { return js_create_array(ctx, 2, args); } } } -static JSValue js_map_read(BCReaderState *s, int magic) -{ - JSContext *ctx = s->ctx; - JSValue obj, rv, argv[2]; - uint32_t i, prop_count; - - argv[0] = JS_UNDEFINED; - argv[1] = JS_UNDEFINED; - obj = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, magic); - if (JS_IsException(obj)) - return JS_EXCEPTION; - if (BC_add_object_ref(s, obj)) - goto fail; - if (bc_get_leb128(s, &prop_count)) - goto fail; - for(i = 0; i < prop_count; i++) { - argv[0] = JS_ReadObjectRec(s); - if (JS_IsException(argv[0])) - goto fail; - if (!(magic & MAGIC_SET)) { - argv[1] = JS_ReadObjectRec(s); - if (JS_IsException(argv[1])) - goto fail; - } - rv = js_map_set(ctx, obj, countof(argv), vc(argv), magic); - if (JS_IsException(rv)) - goto fail; - JS_FreeValue(ctx, rv); - JS_FreeValue(ctx, argv[0]); - JS_FreeValue(ctx, argv[1]); - argv[0] = JS_UNDEFINED; - argv[1] = JS_UNDEFINED; - } - return obj; - fail: - JS_FreeValue(ctx, obj); - JS_FreeValue(ctx, argv[0]); - JS_FreeValue(ctx, argv[1]); - return JS_EXCEPTION; -} - -static int js_map_write(BCWriterState *s, struct JSMapState *map_state, - int magic) -{ - struct list_head *el; - JSMapRecord *mr; - - bc_put_leb128(s, map_state ? map_state->record_count : 0); - if (map_state) { - list_for_each(el, &map_state->records) { - mr = list_entry(el, JSMapRecord, link); - if (JS_WriteObjectRec(s, mr->key)) - return -1; - // mr->value is always JS_UNDEFINED for sets - if (!(magic & MAGIC_SET)) - if (JS_WriteObjectRec(s, mr->value)) - return -1; - } - } - - return 0; -} - -static JSValue JS_ReadMap(BCReaderState *s) -{ - return js_map_read(s, 0); -} - -static JSValue JS_ReadSet(BCReaderState *s) -{ - return js_map_read(s, MAGIC_SET); -} - -static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state) -{ - return js_map_write(s, map_state, 0); -} - -static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state) +static int get_set_record(JSContext *ctx, JSValueConst obj, + int64_t *psize, JSValue *phas, JSValue *pkeys) { - return js_map_write(s, map_state, MAGIC_SET); -} - -static int js_setlike_get_props(JSContext *ctx, JSValueConst setlike, - uint64_t *psize, JSValue *phas, JSValue *pkeys) -{ - JSValue has, keys, v; JSMapState *s; - uint64_t size; - double d; - - keys = JS_UNDEFINED; - has = JS_UNDEFINED; - s = JS_GetOpaque(setlike, JS_CLASS_SET); + int64_t size; + JSValue has = JS_UNDEFINED, keys = JS_UNDEFINED; + + s = JS_GetOpaque(obj, JS_CLASS_SET); if (s) { size = s->record_count; } else { - v = JS_GetProperty(ctx, setlike, JS_ATOM_size); + JSValue v; + double d; + + v = JS_GetProperty(ctx, obj, JS_ATOM_size); if (JS_IsException(v)) - return -1; - if (JS_IsUndefined(v)) { - JS_ThrowTypeError(ctx, ".size is undefined"); - return -1; - } + goto exception; if (JS_ToFloat64Free(ctx, &d, v) < 0) - return -1; - if (d < 0) { - JS_ThrowRangeError(ctx, ".size is not a legal size"); - return -1; - } + goto exception; if (isnan(d)) { - JS_ThrowTypeError(ctx, ".size is not a legal size"); - return -1; + JS_ThrowTypeError(ctx, ".size is not a number"); + goto exception; } - if (isinf(d) || d > (double)MAX_SAFE_INTEGER) { - size = UINT64_MAX; - } else { - size = (uint64_t)d; // cast for expository reasons + if (d < INT64_MIN) + size = INT64_MIN; + else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */ + size = INT64_MAX; + else + size = (int64_t)d; + if (size < 0) { + JS_ThrowRangeError(ctx, ".size must be positive"); + goto exception; } } - has = JS_GetProperty(ctx, setlike, JS_ATOM_has); + + has = JS_GetProperty(ctx, obj, JS_ATOM_has); if (JS_IsException(has)) - return -1; + goto exception; + if (JS_IsUndefined(has)) { + JS_ThrowTypeError(ctx, ".has is undefined"); + goto exception; + } if (!JS_IsFunction(ctx, has)) { JS_ThrowTypeError(ctx, ".has is not a function"); - goto fail; + goto exception; } - keys = JS_GetProperty(ctx, setlike, JS_ATOM_keys); + + keys = JS_GetProperty(ctx, obj, JS_ATOM_keys); if (JS_IsException(keys)) - goto fail; + goto exception; + if (JS_IsUndefined(keys)) { + JS_ThrowTypeError(ctx, ".keys is undefined"); + goto exception; + } if (!JS_IsFunction(ctx, keys)) { JS_ThrowTypeError(ctx, ".keys is not a function"); - goto fail; + goto exception; } *psize = size; *phas = has; *pkeys = keys; return 0; -fail: + + exception: JS_FreeValue(ctx, has); JS_FreeValue(ctx, keys); + *psize = 0; + *phas = JS_UNDEFINED; + *pkeys = JS_UNDEFINED; return -1; } +/* copy 'this_val' in a new set without side effects */ +static JSValue js_copy_set(JSContext *ctx, JSValueConst this_val) +{ + JSValue newset; + JSMapState *s, *t; + struct list_head *el; + JSMapRecord *mr; + + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + + newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); + if (JS_IsException(newset)) + return JS_EXCEPTION; + t = JS_GetOpaque(newset, JS_CLASS_SET); + + // can't clone this_val using js_map_constructor(), + // test262 mandates we don't call the .add method + list_for_each(el, &s->records) { + mr = list_entry(el, JSMapRecord, link); + if (mr->empty) + continue; + if (!set_add_record(ctx, t, mr->key)) + goto exception; + } + return newset; + exception: + JS_FreeValue(ctx, newset); + return JS_EXCEPTION; +} + static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, next, rv, rval; - JSValueConst setlike; + JSValue item, iter, keys, has, next, rv, rval; int done; - bool found; + BOOL found; JSMapState *s; - uint64_t size; + int64_t size; int ok; - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); - if (!s) - return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) - return JS_EXCEPTION; iter = JS_UNDEFINED; next = JS_UNDEFINED; rval = JS_EXCEPTION; - if (s->record_count > size) { - iter = JS_Call(ctx, keys, setlike, 0, NULL); + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) + goto exception; + if (s->record_count <= size) { + iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); if (JS_IsException(iter)) goto exception; - next = JS_GetProperty(ctx, iter, JS_ATOM_next); - if (JS_IsException(next)) - goto exception; - found = false; - for (;;) { - item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); + found = FALSE; + do { + item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - item = map_normalize_key(ctx, item); - found = (NULL != map_find_record(ctx, s, item)); + rv = JS_Call(ctx, has, argv[0], 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); - if (!found) - continue; - if (JS_IteratorClose(ctx, iter, /*is_exception_pending*/false) < 0) + ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION + if (ok < 0) goto exception; - break; - } + found = (ok > 0); + } while (!found); } else { - iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; - found = false; - do { - item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET); + next = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next)) + goto exception; + found = FALSE; + for(;;) { + item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - rv = JS_Call(ctx, has, setlike, 1, vc(&item)); + item = map_normalize_key(ctx, item); + found = (NULL != map_find_record(ctx, s, item)); JS_FreeValue(ctx, item); - ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION - if (ok < 0) - goto exception; - found = (ok > 0); - } while (!found); + if (found) { + JS_IteratorClose(ctx, iter, FALSE); + break; + } + } } rval = !found ? JS_TRUE : JS_FALSE; exception: @@ -49719,36 +50917,34 @@ static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValueConst this_val, static JSValue js_set_isSubsetOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, next, rv, rval; - JSValueConst setlike; - bool found; + JSValue item, iter, keys, has, next, rv, rval; + BOOL found; JSMapState *s; - uint64_t size; + int64_t size; int done, ok; - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); - if (!s) - return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) - return JS_EXCEPTION; iter = JS_UNDEFINED; next = JS_UNDEFINED; rval = JS_EXCEPTION; - found = false; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) + goto exception; + found = FALSE; if (s->record_count > size) goto fini; iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); if (JS_IsException(iter)) goto exception; - found = true; + found = TRUE; do { item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - rv = JS_Call(ctx, has, setlike, 1, vc(&item)); + rv = JS_Call(ctx, has, argv[0], 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION if (ok < 0) @@ -49768,33 +50964,31 @@ static JSValue js_set_isSubsetOf(JSContext *ctx, JSValueConst this_val, static JSValue js_set_isSupersetOf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, next, rval; - JSValueConst setlike; + JSValue item, iter, keys, has, next, rval; int done; - bool found; + BOOL found; JSMapState *s; - uint64_t size; + int64_t size; - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); - if (!s) - return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) - return JS_EXCEPTION; iter = JS_UNDEFINED; next = JS_UNDEFINED; rval = JS_EXCEPTION; - found = false; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) + goto exception; + found = FALSE; if (s->record_count < size) goto fini; - iter = JS_Call(ctx, keys, setlike, 0, NULL); + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; next = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next)) goto exception; - found = true; - for (;;) { + found = TRUE; + for(;;) { item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(item)) goto exception; @@ -49803,11 +50997,10 @@ static JSValue js_set_isSupersetOf(JSContext *ctx, JSValueConst this_val, item = map_normalize_key(ctx, item); found = (NULL != map_find_record(ctx, s, item)); JS_FreeValue(ctx, item); - if (found) - continue; - if (JS_IteratorClose(ctx, iter, /*is_exception_pending*/false) < 0) - goto exception; - break; + if (!found) { + JS_IteratorClose(ctx, iter, FALSE); + break; + } } fini: rval = found ? JS_TRUE : JS_FALSE; @@ -49822,24 +51015,22 @@ static JSValue js_set_isSupersetOf(JSContext *ctx, JSValueConst this_val, static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, newset, next, rv; - JSValueConst setlike; + JSValue newset, item, iter, keys, has, next, rv; JSMapState *s, *t; JSMapRecord *mr; - uint64_t size; + int64_t size; int done, ok; - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); - if (!s) - return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) - return JS_EXCEPTION; iter = JS_UNDEFINED; next = JS_UNDEFINED; newset = JS_UNDEFINED; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) + goto exception; if (s->record_count > size) { - iter = JS_Call(ctx, keys, setlike, 0, NULL); + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; next = JS_GetProperty(ctx, iter, JS_ATOM_next); @@ -49860,11 +51051,11 @@ static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, item); } else if (map_find_record(ctx, t, item)) { JS_FreeValue(ctx, item); // no duplicates - } else if ((mr = map_add_record(ctx, t, item))) { - mr->value = JS_UNDEFINED; } else { + mr = set_add_record(ctx, t, item); JS_FreeValue(ctx, item); - goto exception; + if (!mr) + goto exception; } } } else { @@ -49881,17 +51072,17 @@ static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, goto exception; if (done) // item is JS_UNDEFINED break; - rv = JS_Call(ctx, has, setlike, 1, vc(&item)); + rv = JS_Call(ctx, has, argv[0], 1, (JSValueConst *)&item); ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION if (ok > 0) { item = map_normalize_key(ctx, item); if (map_find_record(ctx, t, item)) { JS_FreeValue(ctx, item); // no duplicates - } else if ((mr = map_add_record(ctx, t, item))) { - mr->value = JS_UNDEFINED; } else { + mr = set_add_record(ctx, t, item); JS_FreeValue(ctx, item); - goto exception; + if (!mr) + goto exception; } } else { JS_FreeValue(ctx, item); @@ -49915,77 +51106,62 @@ static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, static JSValue js_set_difference(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, newset, next, rv; - JSValueConst setlike; + JSValue newset, item, iter, keys, has, next, rv; JSMapState *s, *t; - JSMapRecord *mr; - uint64_t size; + int64_t size; int done; int ok; - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); - if (!s) - return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) - return JS_EXCEPTION; iter = JS_UNDEFINED; next = JS_UNDEFINED; newset = JS_UNDEFINED; - if (s->record_count > size) { - iter = JS_Call(ctx, keys, setlike, 0, NULL); + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) + goto exception; + + newset = js_copy_set(ctx, this_val); + if (JS_IsException(newset)) + goto exception; + t = JS_GetOpaque(newset, JS_CLASS_SET); + + if (s->record_count <= size) { + iter = js_create_map_iterator(ctx, newset, 0, NULL, MAGIC_SET); if (JS_IsException(iter)) goto exception; - next = JS_GetProperty(ctx, iter, JS_ATOM_next); - if (JS_IsException(next)) - goto exception; - newset = js_map_constructor(ctx, JS_UNDEFINED, 1, &this_val, MAGIC_SET); - if (JS_IsException(newset)) - goto exception; - t = JS_GetOpaque(newset, JS_CLASS_SET); for (;;) { - item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); + item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - item = map_normalize_key(ctx, item); - mr = map_find_record(ctx, t, item); - if (mr) - map_delete_record(ctx->rt, t, mr); + rv = JS_Call(ctx, has, argv[0], 1, (JSValueConst *)&item); + ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION + if (ok < 0) { + JS_FreeValue(ctx, item); + goto exception; + } + if (ok) { + map_delete_record(ctx, t, item); + } JS_FreeValue(ctx, item); } } else { - iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; - newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); - if (JS_IsException(newset)) + next = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next)) goto exception; - t = JS_GetOpaque(newset, JS_CLASS_SET); for (;;) { - item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET); + item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - rv = JS_Call(ctx, has, setlike, 1, vc(&item)); - ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION - if (ok == 0) { - item = map_normalize_key(ctx, item); - if (map_find_record(ctx, t, item)) { - JS_FreeValue(ctx, item); // no duplicates - } else if ((mr = map_add_record(ctx, t, item))) { - mr->value = JS_UNDEFINED; - } else { - JS_FreeValue(ctx, item); - goto exception; - } - } else { - JS_FreeValue(ctx, item); - if (ok < 0) - goto exception; - } + map_delete_record(ctx, t, item); + JS_FreeValue(ctx, item); } } goto fini; @@ -50003,45 +51179,32 @@ static JSValue js_set_difference(JSContext *ctx, JSValueConst this_val, static JSValue js_set_symmetricDifference(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, newset, next; - JSValueConst setlike; - struct list_head *el; + JSValue newset, item, iter, next, has, keys; JSMapState *s, *t; JSMapRecord *mr; - uint64_t size; + int64_t size; int done; - bool present; + BOOL present; s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); if (!s) return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) return JS_EXCEPTION; JS_FreeValue(ctx, has); - iter = JS_UNDEFINED; + next = JS_UNDEFINED; - newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); - if (JS_IsException(newset)) - goto exception; - t = JS_GetOpaque(newset, JS_CLASS_SET); - // can't clone this_val using js_map_constructor(), - // test262 mandates we don't call the .add method - list_for_each(el, &s->records) { - mr = list_entry(el, JSMapRecord, link); - if (mr->empty) - continue; - mr = map_add_record(ctx, t, js_dup(mr->key)); - if (!mr) - goto exception; - mr->value = JS_UNDEFINED; - } - iter = JS_Call(ctx, keys, setlike, 0, NULL); + newset = JS_UNDEFINED; + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; next = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next)) goto exception; + newset = js_copy_set(ctx, this_val); + if (JS_IsException(newset)) + goto exception; + t = JS_GetOpaque(newset, JS_CLASS_SET); for (;;) { item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(item)) @@ -50060,18 +51223,15 @@ static JSValue js_set_symmetricDifference(JSContext *ctx, JSValueConst this_val, present = (NULL != map_find_record(ctx, s, item)); mr = map_find_record(ctx, t, item); if (present) { - if (mr) - map_delete_record(ctx->rt, t, mr); + map_delete_record(ctx, t, item); JS_FreeValue(ctx, item); } else if (mr) { JS_FreeValue(ctx, item); } else { - mr = map_add_record(ctx, t, item); - if (!mr) { - JS_FreeValue(ctx, item); + mr = set_add_record(ctx, t, item); + JS_FreeValue(ctx, item); + if (!mr) goto exception; - } - mr->value = JS_UNDEFINED; } } goto fini; @@ -50079,59 +51239,47 @@ static JSValue js_set_symmetricDifference(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, newset); newset = JS_EXCEPTION; fini: - JS_FreeValue(ctx, keys); JS_FreeValue(ctx, next); JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, keys); return newset; } static JSValue js_set_union(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue has, item, iter, keys, newset, next, rv; - JSValueConst setlike; - struct list_head *el; - JSMapState *s, *t; - JSMapRecord *mr; - uint64_t size; + JSValue newset, item, iter, next, has, keys, rv; + JSMapState *s; + int64_t size; int done; - iter = JS_UNDEFINED; s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); if (!s) return JS_EXCEPTION; - setlike = argv[0]; - if (js_setlike_get_props(ctx, setlike, &size, &has, &keys) < 0) + if (get_set_record(ctx, argv[0], &size, &has, &keys) < 0) return JS_EXCEPTION; JS_FreeValue(ctx, has); - iter = JS_UNDEFINED; + next = JS_UNDEFINED; - newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); - if (JS_IsException(newset)) - goto exception; - t = JS_GetOpaque(newset, JS_CLASS_SET); - list_for_each(el, &s->records) { - mr = list_entry(el, JSMapRecord, link); - if (mr->empty) - continue; - mr = map_add_record(ctx, t, js_dup(mr->key)); - if (!mr) - goto exception; - mr->value = JS_UNDEFINED; - } - iter = JS_Call(ctx, keys, setlike, 0, NULL); + newset = JS_UNDEFINED; + iter = JS_Call(ctx, keys, argv[0], 0, NULL); if (JS_IsException(iter)) goto exception; next = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next)) goto exception; + + newset = js_copy_set(ctx, this_val); + if (JS_IsException(newset)) + goto exception; + for (;;) { item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); if (JS_IsException(item)) goto exception; if (done) // item is JS_UNDEFINED break; - rv = js_map_set(ctx, newset, 1, vc(&item), MAGIC_SET); + rv = js_map_set(ctx, newset, 1, (JSValueConst *)&item, MAGIC_SET); JS_FreeValue(ctx, item); if (JS_IsException(rv)) goto exception; @@ -50142,18 +51290,14 @@ static JSValue js_set_union(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, newset); newset = JS_EXCEPTION; fini: - JS_FreeValue(ctx, keys); JS_FreeValue(ctx, next); JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, keys); return newset; } static const JSCFunctionListEntry js_map_funcs[] = { - JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ), - JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), -}; - -static const JSCFunctionListEntry js_set_funcs[] = { + JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 1 ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), }; @@ -50161,9 +51305,9 @@ static const JSCFunctionListEntry js_map_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, 0 ), JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, 0 ), JS_CFUNC_MAGIC_DEF("getOrInsert", 2, js_map_getOrInsert, - JS_CLASS_MAP<<1 | /*computed*/false ), + (JS_CLASS_MAP << 1) | /*computed*/FALSE ), JS_CFUNC_MAGIC_DEF("getOrInsertComputed", 2, js_map_getOrInsert, - JS_CLASS_MAP<<1 | /*computed*/true ), + (JS_CLASS_MAP << 1) | /*computed*/TRUE ), JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, 0 ), JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, 0 ), JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, 0 ), @@ -50211,9 +51355,9 @@ static const JSCFunctionListEntry js_weak_map_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, MAGIC_WEAK ), JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, MAGIC_WEAK ), JS_CFUNC_MAGIC_DEF("getOrInsert", 2, js_map_getOrInsert, - JS_CLASS_WEAKMAP<<1 | /*computed*/false ), + (JS_CLASS_WEAKMAP << 1) | /*computed*/FALSE ), JS_CFUNC_MAGIC_DEF("getOrInsertComputed", 2, js_map_getOrInsert, - JS_CLASS_WEAKMAP<<1 | /*computed*/true ), + (JS_CLASS_WEAKMAP << 1) | /*computed*/TRUE ), JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_WEAK ), JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_WEAK ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakMap", JS_PROP_CONFIGURABLE ), @@ -50244,37 +51388,37 @@ static const uint8_t js_map_proto_funcs_count[6] = { countof(js_set_iterator_proto_funcs), }; -void JS_AddIntrinsicMapSet(JSContext *ctx) +int JS_AddIntrinsicMapSet(JSContext *ctx) { int i; JSValue obj1; char buf[ATOM_GET_STR_BUF_SIZE]; for(i = 0; i < 4; i++) { + JSCFunctionType ft; const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Map + i); - int class_id = JS_CLASS_MAP + i; - ctx->class_proto[class_id] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[class_id], - js_map_proto_funcs_ptr[i], - js_map_proto_funcs_count[i]); - obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0, - JS_CFUNC_constructor_magic, i); - if (class_id == JS_CLASS_MAP) - JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs, countof(js_map_funcs)); - else if (class_id == JS_CLASS_SET) - JS_SetPropertyFunctionList(ctx, obj1, js_set_funcs, countof(js_set_funcs)); - - JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[class_id]); + ft.constructor_magic = js_map_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_MAP + i, name, + ft.generic, 0, JS_CFUNC_constructor_magic, i, + JS_UNDEFINED, + js_map_funcs, i < 2 ? countof(js_map_funcs) : 0, + js_map_proto_funcs_ptr[i], js_map_proto_funcs_count[i], + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); } for(i = 0; i < 2; i++) { ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i], - js_map_proto_funcs_ptr[i + 4], - js_map_proto_funcs_count[i + 4]); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_map_proto_funcs_ptr[i + 4], + js_map_proto_funcs_count[i + 4]); + if (JS_IsException(ctx->class_proto[JS_CLASS_MAP_ITERATOR + i])) + return -1; } + return 0; } /* Generator */ @@ -50295,13 +51439,13 @@ typedef struct JSPromiseData { JSPromiseStateEnum promise_state; /* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */ struct list_head promise_reactions[2]; - bool is_handled; /* Note: only useful to debug */ + BOOL is_handled; /* Note: only useful to debug */ JSValue promise_result; } JSPromiseData; typedef struct JSPromiseFunctionDataResolved { int ref_count; - bool already_resolved; + BOOL already_resolved; } JSPromiseFunctionDataResolved; typedef struct JSPromiseFunctionData { @@ -50315,7 +51459,7 @@ typedef struct JSPromiseReactionData { JSValue handler; } JSPromiseReactionData; -JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValueConst promise) +JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); if (!s) @@ -50323,19 +51467,12 @@ JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValueConst promise) return s->promise_state; } -JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise) +JSValue JS_PromiseResult(JSContext *ctx, JSValue promise) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); if (!s) return JS_UNDEFINED; - return js_dup(s->promise_result); -} - -bool JS_IsPromise(JSValueConst val) -{ - if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) - return false; - return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_PROMISE; + return JS_DupValue(ctx, s->promise_result); } static int js_create_resolving_functions(JSContext *ctx, JSValue *args, @@ -50350,52 +51487,40 @@ static void promise_reaction_data_free(JSRuntime *rt, js_free_rt(rt, rd); } -#ifdef ENABLE_DUMPS // JS_DUMP_PROMISE -#define promise_trace(ctx, ...) \ - do { \ - if (check_dump_flag(ctx->rt, JS_DUMP_PROMISE)) \ - printf(__VA_ARGS__); \ - } while (0) -#else -#define promise_trace(...) -#endif - static JSValue promise_reaction_job(JSContext *ctx, int argc, JSValueConst *argv) { - JSValueConst handler, func; + JSValueConst handler, arg, func; JSValue res, res2; - JSValueConst arg; - bool is_reject; + BOOL is_reject; assert(argc == 5); handler = argv[2]; is_reject = JS_ToBool(ctx, argv[3]); arg = argv[4]; - - promise_trace(ctx, "promise_reaction_job: is_reject=%d\n", is_reject); +#ifdef DUMP_PROMISE + printf("promise_reaction_job: is_reject=%d\n", is_reject); +#endif if (JS_IsUndefined(handler)) { if (is_reject) { - res = JS_Throw(ctx, js_dup(arg)); + res = JS_Throw(ctx, JS_DupValue(ctx, arg)); } else { - res = js_dup(arg); + res = JS_DupValue(ctx, arg); } } else { res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg); } is_reject = JS_IsException(res); - if (is_reject) { - if (unlikely(JS_IsUncatchableError(ctx, ctx->rt->current_exception))) - return JS_EXCEPTION; + if (is_reject) res = JS_GetException(ctx); - } func = argv[is_reject]; /* as an extension, we support undefined as value to avoid creating a dummy promise in the 'await' implementation of async functions */ if (!JS_IsUndefined(func)) { - res2 = JS_Call(ctx, func, JS_UNDEFINED, 1, vc(&res)); + res2 = JS_Call(ctx, func, JS_UNDEFINED, + 1, (JSValueConst *)&res); } else { res2 = JS_UNDEFINED; } @@ -50404,12 +51529,6 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc, return res2; } -void JS_SetPromiseHook(JSRuntime *rt, JSPromiseHook promise_hook, void *opaque) -{ - rt->promise_hook = promise_hook; - rt->promise_hook_opaque = opaque; -} - void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque) @@ -50419,7 +51538,7 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, } static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, - JSValueConst value, bool is_reject) + JSValueConst value, BOOL is_reject) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); struct list_head *el, *el1; @@ -50428,24 +51547,17 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, if (!s || s->promise_state != JS_PROMISE_PENDING) return; /* should never happen */ - set_value(ctx, &s->promise_result, js_dup(value)); + set_value(ctx, &s->promise_result, JS_DupValue(ctx, value)); s->promise_state = JS_PROMISE_FULFILLED + is_reject; - - promise_trace(ctx, "fulfill_or_reject_promise: is_reject=%d\n", is_reject); - - if (s->promise_state == JS_PROMISE_FULFILLED) { - JSRuntime *rt = ctx->rt; - if (rt->promise_hook) { - rt->promise_hook(ctx, JS_PROMISE_HOOK_RESOLVE, promise, - JS_UNDEFINED, rt->promise_hook_opaque); - } - } - +#ifdef DUMP_PROMISE + printf("fulfill_or_reject_promise: is_reject=%d\n", is_reject); +#endif if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { JSRuntime *rt = ctx->rt; - if (rt->host_promise_rejection_tracker) - rt->host_promise_rejection_tracker(ctx, promise, value, false, + if (rt->host_promise_rejection_tracker) { + rt->host_promise_rejection_tracker(ctx, promise, value, FALSE, rt->host_promise_rejection_tracker_opaque); + } } list_for_each_safe(el, el1, &s->promise_reactions[is_reject]) { @@ -50453,7 +51565,7 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, args[0] = rd->resolving_funcs[0]; args[1] = rd->resolving_funcs[1]; args[2] = rd->handler; - args[3] = js_bool(is_reject); + args[3] = JS_NewBool(ctx, is_reject); args[4] = value; JS_EnqueueJob(ctx, promise_reaction_job, 5, args); list_del(&rd->link); @@ -50467,34 +51579,31 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, } } +static void reject_promise(JSContext *ctx, JSValueConst promise, + JSValueConst value) +{ + fulfill_or_reject_promise(ctx, promise, value, TRUE); +} + static JSValue js_promise_resolve_thenable_job(JSContext *ctx, int argc, JSValueConst *argv) { JSValueConst promise, thenable, then; JSValue args[2], res; - JSRuntime *rt; - - promise_trace(ctx, "js_promise_resolve_thenable_job\n"); +#ifdef DUMP_PROMISE + printf("js_promise_resolve_thenable_job\n"); +#endif assert(argc == 3); promise = argv[0]; thenable = argv[1]; then = argv[2]; if (js_create_resolving_functions(ctx, args, promise) < 0) return JS_EXCEPTION; - rt = ctx->rt; - if (rt->promise_hook) { - rt->promise_hook(ctx, JS_PROMISE_HOOK_BEFORE, promise, JS_UNDEFINED, - rt->promise_hook_opaque); - } - res = JS_Call(ctx, then, thenable, 2, vc(args)); - if (rt->promise_hook) { - rt->promise_hook(ctx, JS_PROMISE_HOOK_AFTER, promise, JS_UNDEFINED, - rt->promise_hook_opaque); - } + res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args); if (JS_IsException(res)) { JSValue error = JS_GetException(ctx); - res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, vc(&error)); + res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error); JS_FreeValue(ctx, error); } JS_FreeValue(ctx, args[0]); @@ -50524,7 +51633,7 @@ static int js_create_resolving_functions(JSContext *ctx, if (!sr) return -1; sr->ref_count = 1; - sr->already_resolved = false; /* must be shared between the two functions */ + sr->already_resolved = FALSE; /* must be shared between the two functions */ ret = 0; for(i = 0; i < 2; i++) { obj = JS_NewObjectProtoClass(ctx, ctx->function_proto, @@ -50543,8 +51652,8 @@ static int js_create_resolving_functions(JSContext *ctx, } sr->ref_count++; s->presolved = sr; - s->promise = js_dup(promise); - JS_SetOpaqueInternal(obj, s); + s->promise = JS_DupValue(ctx, promise); + JS_SetOpaque(obj, s); js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1); resolving_funcs[i] = obj; } @@ -50552,8 +51661,7 @@ static int js_create_resolving_functions(JSContext *ctx, return ret; } -static void js_promise_resolve_function_finalizer(JSRuntime *rt, - JSValueConst val) +static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val) { JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data; if (s) { @@ -50580,26 +51688,23 @@ static JSValue js_promise_resolve_function_call(JSContext *ctx, { JSObject *p = JS_VALUE_GET_OBJ(func_obj); JSPromiseFunctionData *s; - JSValueConst args[3]; - JSValueConst resolution; + JSValueConst resolution, args[3]; JSValue then; - bool is_reject; + BOOL is_reject; s = p->u.promise_function_data; if (!s || s->presolved->already_resolved) return JS_UNDEFINED; - s->presolved->already_resolved = true; + s->presolved->already_resolved = TRUE; is_reject = p->class_id - JS_CLASS_PROMISE_RESOLVE_FUNCTION; if (argc > 0) resolution = argv[0]; else resolution = JS_UNDEFINED; -#ifdef ENABLE_DUMPS // JS_DUMP_PROMISE - if (check_dump_flag(ctx->rt, JS_DUMP_PROMISE)) { - printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject); - JS_DumpValue(ctx->rt, resolution); - printf("\n"); - } +#ifdef DUMP_PROMISE + printf("js_promise_resolving_function_call: is_reject=%d ", is_reject); + JS_DumpValue(ctx, "resolution", resolution); + printf("\n"); #endif if (is_reject || !JS_IsObject(resolution)) { goto done; @@ -50612,7 +51717,7 @@ static JSValue js_promise_resolve_function_call(JSContext *ctx, JSValue error; fail_reject: error = JS_GetException(ctx); - fulfill_or_reject_promise(ctx, s->promise, error, true); + reject_promise(ctx, s->promise, error); JS_FreeValue(ctx, error); } else if (!JS_IsFunction(ctx, then)) { JS_FreeValue(ctx, then); @@ -50628,7 +51733,7 @@ static JSValue js_promise_resolve_function_call(JSContext *ctx, return JS_UNDEFINED; } -static void js_promise_finalizer(JSRuntime *rt, JSValueConst val) +static void js_promise_finalizer(JSRuntime *rt, JSValue val) { JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE); struct list_head *el, *el1; @@ -50674,7 +51779,6 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, JSValueConst executor; JSValue obj; JSPromiseData *s; - JSRuntime *rt; JSValue args[2], ret; int i; @@ -50688,26 +51792,18 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, if (!s) goto fail; s->promise_state = JS_PROMISE_PENDING; - s->is_handled = false; + s->is_handled = FALSE; for(i = 0; i < 2; i++) init_list_head(&s->promise_reactions[i]); s->promise_result = JS_UNDEFINED; - JS_SetOpaqueInternal(obj, s); + JS_SetOpaque(obj, s); if (js_create_resolving_functions(ctx, args, obj)) goto fail; - rt = ctx->rt; - if (rt->promise_hook) { - JSValueConst parent_promise = JS_UNDEFINED; - if (rt->parent_promise) - parent_promise = rt->parent_promise->value; - rt->promise_hook(ctx, JS_PROMISE_HOOK_INIT, obj, parent_promise, - rt->promise_hook_opaque); - } - ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, vc(args)); + ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, (JSValueConst *)args); if (JS_IsException(ret)) { JSValue ret2, error; error = JS_GetException(ctx); - ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, vc(&error)); + ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error); JS_FreeValue(ctx, error); if (JS_IsException(ret2)) goto fail1; @@ -50728,14 +51824,14 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, static JSValue js_promise_executor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) + int magic, JSValue *func_data) { int i; for(i = 0; i < 2; i++) { if (!JS_IsUndefined(func_data[i])) return JS_ThrowTypeError(ctx, "resolving function already set"); - func_data[i] = js_dup(argv[i]); + func_data[i] = JS_DupValue(ctx, argv[i]); } return JS_UNDEFINED; } @@ -50760,11 +51856,14 @@ static JSValue js_new_promise_capability(JSContext *ctx, executor = js_promise_executor_new(ctx); if (JS_IsException(executor)) - return JS_EXCEPTION; + return executor; + if (JS_IsUndefined(ctor)) { - result_promise = js_promise_constructor(ctx, ctor, 1, vc(&executor)); + result_promise = js_promise_constructor(ctx, ctor, 1, + (JSValueConst *)&executor); } else { - result_promise = JS_CallConstructor(ctx, ctor, 1, vc(&executor)); + result_promise = JS_CallConstructor(ctx, ctor, 1, + (JSValueConst *)&executor); } if (JS_IsException(result_promise)) goto fail; @@ -50774,7 +51873,7 @@ static JSValue js_new_promise_capability(JSContext *ctx, goto fail; } for(i = 0; i < 2; i++) - resolving_funcs[i] = js_dup(s->data[i]); + resolving_funcs[i] = JS_DupValue(ctx, s->data[i]); JS_FreeValue(ctx, executor); return result_promise; fail: @@ -50792,20 +51891,20 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSValue result_promise, resolving_funcs[2], ret; - bool is_reject = magic; + BOOL is_reject = magic; if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); if (!is_reject && JS_GetOpaque(argv[0], JS_CLASS_PROMISE)) { JSValue ctor; - bool is_same; + BOOL is_same; ctor = JS_GetProperty(ctx, argv[0], JS_ATOM_constructor); if (JS_IsException(ctor)) return ctor; is_same = js_same_value(ctx, ctor, this_val); JS_FreeValue(ctx, ctor); if (is_same) - return js_dup(argv[0]); + return JS_DupValue(ctx, argv[0]); } result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); if (JS_IsException(result_promise)) @@ -50821,7 +51920,8 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, return result_promise; } -static JSValue js_promise_withResolvers(JSContext *ctx, JSValueConst this_val, +static JSValue js_promise_withResolvers(JSContext *ctx, + JSValueConst this_val, int argc, JSValueConst *argv) { JSValue result_promise, resolving_funcs[2], obj; @@ -50829,7 +51929,7 @@ static JSValue js_promise_withResolvers(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeErrorNotAnObject(ctx); result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); if (JS_IsException(result_promise)) - return JS_EXCEPTION; + return result_promise; obj = JS_NewObject(ctx); if (JS_IsException(obj)) goto exception; @@ -50860,7 +51960,7 @@ static JSValue js_promise_try(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue result_promise, resolving_funcs[2], ret, ret2; - bool is_reject = 0; + BOOL is_reject = 0; if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -50872,7 +51972,7 @@ static JSValue js_promise_try(JSContext *ctx, JSValueConst this_val, is_reject = 1; ret = JS_GetException(ctx); } - ret2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, vc(&ret)); + ret2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, (JSValueConst *)&ret); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); JS_FreeValue(ctx, ret); @@ -50898,7 +51998,7 @@ static __exception int remainingElementsCount_add(JSContext *ctx, return -1; remainingElementsCount += addend; if (JS_SetPropertyUint32(ctx, resolve_element_env, 0, - js_int32(remainingElementsCount)) < 0) + JS_NewInt32(ctx, remainingElementsCount)) < 0) return -1; return (remainingElementsCount == 0); } @@ -50911,11 +52011,11 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, - JSValueConst *func_data) + JSValue *func_data) { int resolve_type = magic & 3; int is_reject = magic & 4; - bool alreadyCalled = JS_ToBool(ctx, func_data[0]); + BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]); JSValueConst values = func_data[2]; JSValueConst resolve = func_data[3]; JSValueConst resolve_element_env = func_data[4]; @@ -50926,7 +52026,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, return JS_EXCEPTION; if (alreadyCalled) return JS_UNDEFINED; - func_data[0] = JS_TRUE; + func_data[0] = JS_NewBool(ctx, TRUE); if (resolve_type == PROMISE_MAGIC_allSettled) { JSValue str; @@ -50943,14 +52043,14 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, goto fail1; if (JS_DefinePropertyValue(ctx, obj, is_reject ? JS_ATOM_reason : JS_ATOM_value, - js_dup(argv[0]), + JS_DupValue(ctx, argv[0]), JS_PROP_C_W_E) < 0) { fail1: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } } else { - obj = js_dup(argv[0]); + obj = JS_DupValue(ctx, argv[0]); } if (JS_DefinePropertyValueUint32(ctx, values, index, obj, JS_PROP_C_W_E) < 0) @@ -50965,10 +52065,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, error = js_aggregate_error_constructor(ctx, values); if (JS_IsException(error)) return JS_EXCEPTION; - ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, vc(&error)); + ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error); JS_FreeValue(ctx, error); } else { - ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values); + ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values); } if (JS_IsException(ret)) return ret; @@ -50986,7 +52086,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element; JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED; JSValueConst then_args[2], resolve_element_data[5]; - int done, index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); + BOOL done; + int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -50997,12 +52098,13 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, if (JS_IsException(promise_resolve) || check_function(ctx, promise_resolve)) goto fail_reject; - iter = JS_GetIterator(ctx, argv[0], false); + iter = JS_GetIterator(ctx, argv[0], FALSE); if (JS_IsException(iter)) { JSValue error; fail_reject: error = JS_GetException(ctx); - ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&error)); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, + (JSValueConst *)&error); JS_FreeValue(ctx, error); if (JS_IsException(ret)) goto fail; @@ -51019,7 +52121,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto fail_reject; /* remainingElementsCount field */ if (JS_DefinePropertyValueUint32(ctx, resolve_element_env, 0, - js_int32(1), + JS_NewInt32(ctx, 1), JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) goto fail_reject; @@ -51033,15 +52135,15 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, if (done) break; next_promise = JS_Call(ctx, promise_resolve, - this_val, 1, vc(&item)); + this_val, 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: - JS_IteratorClose(ctx, iter, true); + JS_IteratorClose(ctx, iter, TRUE); goto fail_reject; } - resolve_element_data[0] = JS_FALSE; - resolve_element_data[1] = js_int32(index); + resolve_element_data[0] = JS_NewBool(ctx, FALSE); + resolve_element_data[1] = JS_VALUE_MAKE_CONST(JS_NewInt32(ctx, index)); resolve_element_data[2] = values; resolve_element_data[3] = resolving_funcs[is_promise_any]; resolve_element_data[4] = resolve_element_env; @@ -51066,9 +52168,9 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JS_UNDEFINED, JS_PROP_C_W_E) < 0) goto fail_reject1; reject_element = resolve_element; - resolve_element = js_dup(resolving_funcs[0]); + resolve_element = JS_DupValue(ctx, resolving_funcs[0]); } else { - reject_element = js_dup(resolving_funcs[1]); + reject_element = JS_DupValue(ctx, resolving_funcs[1]); } if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) { @@ -51101,7 +52203,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, values = error; } ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED, - 1, vc(&values)); + 1, (JSValueConst *)&values); if (check_exception_free(ctx, ret)) goto fail_reject; } @@ -51127,7 +52229,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, JSValue result_promise, resolving_funcs[2], item, next_promise, ret; JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED; JSValue promise_resolve = JS_UNDEFINED; - int done; + BOOL done; if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -51138,12 +52240,13 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, if (JS_IsException(promise_resolve) || check_function(ctx, promise_resolve)) goto fail_reject; - iter = JS_GetIterator(ctx, argv[0], false); + iter = JS_GetIterator(ctx, argv[0], FALSE); if (JS_IsException(iter)) { JSValue error; fail_reject: error = JS_GetException(ctx); - ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&error)); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, + (JSValueConst *)&error); JS_FreeValue(ctx, error); if (JS_IsException(ret)) goto fail; @@ -51162,15 +52265,15 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, if (done) break; next_promise = JS_Call(ctx, promise_resolve, - this_val, 1, vc(&item)); + this_val, 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: - JS_IteratorClose(ctx, iter, true); + JS_IteratorClose(ctx, iter, TRUE); goto fail_reject; } ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2, - vc(resolving_funcs)); + (JSValueConst *)resolving_funcs); if (check_exception_free(ctx, ret)) goto fail_reject1; } @@ -51209,11 +52312,11 @@ static __exception int perform_promise_then(JSContext *ctx, return -1; } for(j = 0; j < 2; j++) - rd->resolving_funcs[j] = js_dup(cap_resolving_funcs[j]); + rd->resolving_funcs[j] = JS_DupValue(ctx, cap_resolving_funcs[j]); handler = resolve_reject[i]; if (!JS_IsFunction(ctx, handler)) handler = JS_UNDEFINED; - rd->handler = js_dup(handler); + rd->handler = JS_DupValue(ctx, handler); rd_array[i] = rd; } @@ -51224,22 +52327,23 @@ static __exception int perform_promise_then(JSContext *ctx, JSValueConst args[5]; if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { JSRuntime *rt = ctx->rt; - if (rt->host_promise_rejection_tracker) + if (rt->host_promise_rejection_tracker) { rt->host_promise_rejection_tracker(ctx, promise, s->promise_result, - true, rt->host_promise_rejection_tracker_opaque); + TRUE, rt->host_promise_rejection_tracker_opaque); + } } i = s->promise_state - JS_PROMISE_FULFILLED; rd = rd_array[i]; args[0] = rd->resolving_funcs[0]; args[1] = rd->resolving_funcs[1]; args[2] = rd->handler; - args[3] = js_bool(i); + args[3] = JS_NewBool(ctx, i); args[4] = s->promise_result; JS_EnqueueJob(ctx, promise_reaction_job, 5, args); for(i = 0; i < 2; i++) promise_reaction_data_free(ctx->rt, rd_array[i]); } - s->is_handled = true; + s->is_handled = TRUE; return 0; } @@ -51247,10 +52351,7 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue ctor, result_promise, resolving_funcs[2]; - bool have_promise_hook; - JSValueLink link; JSPromiseData *s; - JSRuntime *rt; int i, ret; s = JS_GetOpaque2(ctx, this_val, JS_CLASS_PROMISE); @@ -51260,20 +52361,12 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED); if (JS_IsException(ctor)) return ctor; - rt = ctx->rt; - // always restore, even if js_new_promise_capability callee removes hook - have_promise_hook = (rt->promise_hook != NULL); - if (have_promise_hook) { - link = (JSValueLink){rt->parent_promise, this_val}; - rt->parent_promise = &link; - } result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor); - if (have_promise_hook) - rt->parent_promise = link.next; JS_FreeValue(ctx, ctor); if (JS_IsException(result_promise)) return result_promise; - ret = perform_promise_then(ctx, this_val, argv, vc(resolving_funcs)); + ret = perform_promise_then(ctx, this_val, argv, + (JSValueConst *)resolving_funcs); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); if (ret) { @@ -51294,21 +52387,21 @@ static JSValue js_promise_catch(JSContext *ctx, JSValueConst this_val, static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) + int magic, JSValue *func_data) { - return js_dup(func_data[0]); + return JS_DupValue(ctx, func_data[0]); } static JSValue js_promise_finally_thrower(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) + int magic, JSValue *func_data) { - return JS_Throw(ctx, js_dup(func_data[0])); + return JS_Throw(ctx, JS_DupValue(ctx, func_data[0])); } static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) + int magic, JSValue *func_data) { JSValueConst ctor = func_data[0]; JSValueConst onFinally = func_data[1]; @@ -51317,7 +52410,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL); if (JS_IsException(res)) return res; - promise = js_promise_resolve(ctx, ctor, 1, vc(&res), 0); + promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0); JS_FreeValue(ctx, res); if (JS_IsException(promise)) return promise; @@ -51332,7 +52425,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va JS_FreeValue(ctx, promise); return then_func; } - ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, vc(&then_func)); + ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func); JS_FreeValue(ctx, then_func); return ret; } @@ -51350,8 +52443,8 @@ static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val, if (JS_IsException(ctor)) return ctor; if (!JS_IsFunction(ctx, onFinally)) { - then_funcs[0] = js_dup(onFinally); - then_funcs[1] = js_dup(onFinally); + then_funcs[0] = JS_DupValue(ctx, onFinally); + then_funcs[1] = JS_DupValue(ctx, onFinally); } else { func_data[0] = ctor; func_data[1] = onFinally; @@ -51366,7 +52459,7 @@ static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val, } } JS_FreeValue(ctx, ctor); - ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, vc(then_funcs)); + ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, (JSValueConst *)then_funcs); JS_FreeValue(ctx, then_funcs[0]); JS_FreeValue(ctx, then_funcs[1]); return ret; @@ -51396,25 +52489,6 @@ static const JSCFunctionListEntry js_async_function_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncFunction", JS_PROP_CONFIGURABLE ), }; -static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, - int magic, JSValueConst *func_data) -{ - return js_create_iterator_result(ctx, js_dup(argv[0]), - JS_ToBool(ctx, func_data[0])); -} - -static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx, - bool done) -{ - JSValueConst func_data[1]; - - func_data[0] = js_bool(done); - return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap, - 1, 0, 1, func_data); -} - /* AsyncIteratorPrototype */ static const JSCFunctionListEntry js_async_iterator_proto_funcs[] = { @@ -51428,8 +52502,7 @@ typedef struct JSAsyncFromSyncIteratorData { JSValue next_method; } JSAsyncFromSyncIteratorData; -static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, - JSValueConst val) +static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, JSValue val) { JSAsyncFromSyncIteratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR); @@ -51452,7 +52525,7 @@ static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val, } static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, - JSValue sync_iter) + JSValueConst sync_iter) { JSValue async_iter, next_method; JSAsyncFromSyncIteratorData *s; @@ -51471,12 +52544,47 @@ static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, JS_FreeValue(ctx, next_method); return JS_EXCEPTION; } - s->sync_iter = js_dup(sync_iter); + s->sync_iter = JS_DupValue(ctx, sync_iter); s->next_method = next_method; - JS_SetOpaqueInternal(async_iter, s); + JS_SetOpaque(async_iter, s); return async_iter; } +static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValue *func_data) +{ + return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), + JS_ToBool(ctx, func_data[0])); +} + +static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx, + BOOL done) +{ + JSValueConst func_data[1]; + + func_data[0] = JS_VALUE_MAKE_CONST(JS_NewBool(ctx, done)); + return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap, + 1, 0, 1, func_data); +} + +static JSValue js_async_from_sync_iterator_close_wrap(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValue *func_data) +{ + JS_Throw(ctx, JS_DupValue(ctx, argv[0])); + JS_IteratorClose(ctx, func_data[0], TRUE); + return JS_EXCEPTION; +} + +static JSValue js_async_from_sync_iterator_close_wrap_func_create(JSContext *ctx, JSValueConst sync_iter) +{ + return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_close_wrap, + 1, 0, 1, &sync_iter); +} + static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) @@ -51496,7 +52604,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi } if (magic == GEN_MAGIC_NEXT) { - method = js_dup(s->next_method); + method = JS_DupValue(ctx, s->next_method); } else { method = JS_GetProperty(ctx, s->sync_iter, magic == GEN_MAGIC_RETURN ? JS_ATOM_return : @@ -51505,17 +52613,15 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi goto reject; if (JS_IsUndefined(method) || JS_IsNull(method)) { if (magic == GEN_MAGIC_RETURN) { - err = js_create_iterator_result(ctx, js_dup(argv[0]), true); + err = js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), TRUE); is_reject = 0; - } else if (JS_IteratorClose(ctx, s->sync_iter, false)) { - err = JS_GetException(ctx); - is_reject = 1; + goto done_resolve; } else { - err = JS_MakeError2(ctx, JS_TYPE_ERROR, /*add_backtrace*/true, - "throw is not a method"); - is_reject = 1; + if (JS_IteratorClose(ctx, s->sync_iter, FALSE)) + goto reject; + JS_ThrowTypeError(ctx, "throw is not a method"); + goto reject; } - goto done_resolve; } } value = JS_IteratorNext2(ctx, s->sync_iter, method, @@ -51530,30 +52636,32 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi if (JS_IsException(value)) goto reject; } - - if (JS_IsException(value)) { - JSValue res2; - reject: - err = JS_GetException(ctx); - is_reject = 1; - done_resolve: - res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, - 1, vc(&err)); - JS_FreeValue(ctx, err); - JS_FreeValue(ctx, res2); - JS_FreeValue(ctx, resolving_funcs[0]); - JS_FreeValue(ctx, resolving_funcs[1]); - return promise; - } + + if (JS_IsException(value)) + goto reject; { JSValue value_wrapper_promise, resolve_reject[2]; int res; value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor, - 1, vc(&value), 0); + 1, (JSValueConst *)&value, 0); if (JS_IsException(value_wrapper_promise)) { + JSValue res2; JS_FreeValue(ctx, value); - goto reject; + if (magic != GEN_MAGIC_RETURN && !done) { + JS_IteratorClose(ctx, s->sync_iter, TRUE); + } + reject: + err = JS_GetException(ctx); + is_reject = 1; + done_resolve: + res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, + 1, (JSValueConst *)&err); + JS_FreeValue(ctx, err); + JS_FreeValue(ctx, res2); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + return promise; } resolve_reject[0] = @@ -51562,13 +52670,23 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi JS_FreeValue(ctx, value_wrapper_promise); goto fail; } + if (done || magic == GEN_MAGIC_RETURN) { + resolve_reject[1] = JS_UNDEFINED; + } else { + resolve_reject[1] = + js_async_from_sync_iterator_close_wrap_func_create(ctx, s->sync_iter); + if (JS_IsException(resolve_reject[1])) { + JS_FreeValue(ctx, value_wrapper_promise); + JS_FreeValue(ctx, resolve_reject[0]); + goto fail; + } + } JS_FreeValue(ctx, value); - resolve_reject[1] = JS_UNDEFINED; - res = perform_promise_then(ctx, value_wrapper_promise, - vc(resolve_reject), - vc(resolving_funcs)); + (JSValueConst *)resolve_reject, + (JSValueConst *)resolving_funcs); JS_FreeValue(ctx, resolve_reject[0]); + JS_FreeValue(ctx, resolve_reject[1]); JS_FreeValue(ctx, value_wrapper_promise); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); @@ -51619,14 +52737,16 @@ static JSClassShortDef const js_async_class_def[] = { { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark }, /* JS_CLASS_ASYNC_GENERATOR */ }; -void JS_AddIntrinsicPromise(JSContext *ctx) +int JS_AddIntrinsicPromise(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; + JSCFunctionType ft; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) { - init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, - countof(js_async_class_def)); + if (init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, + countof(js_async_class_def))) + return -1; rt->class_array[JS_CLASS_PROMISE_RESOLVE_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_PROMISE_REJECT_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_ASYNC_FUNCTION].call = js_async_function_call; @@ -51636,77 +52756,67 @@ void JS_AddIntrinsicPromise(JSContext *ctx) } /* Promise */ - ctx->class_proto[JS_CLASS_PROMISE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_PROMISE], - js_promise_proto_funcs, - countof(js_promise_proto_funcs)); - obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1, - JS_CFUNC_constructor, 0); - ctx->promise_ctor = js_dup(obj1); - JS_SetPropertyFunctionList(ctx, obj1, - js_promise_funcs, - countof(js_promise_funcs)); - JS_NewGlobalCConstructor2(ctx, obj1, "Promise", - ctx->class_proto[JS_CLASS_PROMISE]); - - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft; - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_PROMISE, "Promise", + js_promise_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_promise_funcs, countof(js_promise_funcs), + js_promise_proto_funcs, countof(js_promise_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + ctx->promise_ctor = obj1; + /* AsyncFunction */ - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - js_async_function_proto_funcs, - countof(js_async_function_proto_funcs)); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_FUNCTION, "AsyncFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, + ctx->function_ctor, + NULL, 0, + js_async_function_proto_funcs, countof(js_async_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); - + /* AsyncIteratorPrototype */ - ctx->async_iterator_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->async_iterator_proto, - js_async_iterator_proto_funcs, - countof(js_async_iterator_proto_funcs)); + ctx->async_iterator_proto = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + js_async_iterator_proto_funcs, + countof(js_async_iterator_proto_funcs)); + if (JS_IsException(ctx->async_iterator_proto)) + return -1; /* AsyncFromSyncIteratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR], - js_async_from_sync_iterator_proto_funcs, - countof(js_async_from_sync_iterator_proto_funcs)); - + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_from_sync_iterator_proto_funcs, + countof(js_async_from_sync_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR])) + return -1; + /* AsyncGeneratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_GENERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - js_async_generator_proto_funcs, - countof(js_async_generator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_generator_proto_funcs, + countof(js_async_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_GENERATOR])) + return -1; /* AsyncGeneratorFunction */ - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] = - JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncGeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, - JS_FUNC_ASYNC_GENERATOR, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - js_async_generator_function_proto_funcs, - countof(js_async_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_async_generator_function_proto_funcs, countof(js_async_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); + + return JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); } /* URI handling */ @@ -51725,7 +52835,7 @@ static int isURIReserved(int c) { return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL; } -static int JS_PRINTF_FORMAT_ATTR(2, 3) js_throw_URIError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...) +static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext *ctx, const char *fmt, ...) { va_list ap; @@ -51990,7 +53100,6 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ), JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ), JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ), - JS_CFUNC_DEF("queueMicrotask", 1, js_global_queueMicrotask ), JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ), JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ), @@ -51998,10 +53107,11 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_CFUNC_MAGIC_DEF("encodeURIComponent", 1, js_global_encodeURI, 1 ), JS_CFUNC_DEF("escape", 1, js_global_escape ), JS_CFUNC_DEF("unescape", 1, js_global_unescape ), - JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ), - JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc + JS_PROP_DOUBLE_DEF("Infinity", INF, 0 ), + JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ), JS_PROP_UNDEFINED_DEF("undefined", 0 ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), + JS_CFUNC_DEF("eval", 1, js_global_eval ), }; /* Date */ @@ -52012,7 +53122,7 @@ static int64_t math_mod(int64_t a, int64_t b) { return m + (m < 0) * b; } -static int64_t floor_div_int64(int64_t a, int64_t b) { +static int64_t floor_div(int64_t a, int64_t b) { /* integer division rounding toward -Infinity */ int64_t m = a % b; return (a - (m + (m < 0) * b)) / b; @@ -52021,8 +53131,7 @@ static int64_t floor_div_int64(int64_t a, int64_t b) { static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); -static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, - JSValueConst this_val) +static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); @@ -52039,16 +53148,16 @@ static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double JSObject *p = JS_VALUE_GET_OBJ(this_val); if (p->class_id == JS_CLASS_DATE) { JS_FreeValue(ctx, p->u.object_data); - p->u.object_data = js_float64(v); - return js_dup(p->u.object_data); + p->u.object_data = JS_NewFloat64(ctx, v); + return JS_DupValue(ctx, p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a Date object"); } static int64_t days_from_year(int64_t y) { - return 365 * (y - 1970) + floor_div_int64(y - 1969, 4) - - floor_div_int64(y - 1901, 100) + floor_div_int64(y - 1601, 400); + return 365 * (y - 1970) + floor_div(y - 1969, 4) - + floor_div(y - 1901, 100) + floor_div(y - 1601, 400); } static int64_t days_in_year(int64_t y) { @@ -52058,7 +53167,7 @@ static int64_t days_in_year(int64_t y) { /* return the year, update days */ static int64_t year_from_days(int64_t *days) { int64_t y, d1, nd, d = *days; - y = floor_div_int64(d * 10000, 3652425) + 1970; + y = floor_div(d * 10000, 3652425) + 1970; /* the initial approximation is very good, so only a few iterations are necessary */ for(;;) { @@ -52083,8 +53192,7 @@ static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; static char const day_names[] = "SunMonTueWedThuFriSat"; static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, - double fields[minimum_length(9)], - int is_local, int force) + double fields[minimum_length(9)], int is_local, int force) { double dval; int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0; @@ -52094,7 +53202,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, if (isnan(dval)) { if (!force) - return false; /* NaN */ + return FALSE; /* NaN */ d = 0; /* initialize all fields to 0 */ } else { d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */ @@ -52133,7 +53241,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, fields[6] = ms; fields[7] = wd; fields[8] = tz; - return true; + return TRUE; } static double time_clip(double t) { @@ -52202,6 +53310,21 @@ static double set_date_fields(double fields[minimum_length(7)], int is_local) { return time_clip(tv); } +static double set_date_fields_checked(double fields[minimum_length(7)], int is_local) +{ + int i; + double a; + for(i = 0; i < 7; i++) { + a = fields[i]; + if (!isfinite(a)) + return NAN; + fields[i] = trunc(a); + if (i == 0 && fields[0] >= 0 && fields[0] < 100) + fields[0] += 1900; + } + return set_date_fields(fields, is_local); +} + static JSValue get_date_field(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -52220,7 +53343,7 @@ static JSValue get_date_field(JSContext *ctx, JSValueConst this_val, if (magic & 0x100) { // getYear fields[0] -= 1900; } - return js_number(fields[n]); + return JS_NewFloat64(ctx, fields[n]); } static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, @@ -52228,7 +53351,7 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, { // _field(obj, first_field, end_field, args, is_local) double fields[9]; - int res, first_field, end_field, is_local, i, n; + int res, first_field, end_field, is_local, i, n, res1; double d, a; d = NAN; @@ -52239,21 +53362,22 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, res = get_date_fields(ctx, this_val, fields, is_local, first_field == 0); if (res < 0) return JS_EXCEPTION; - + res1 = res; + // Argument coercion is observable and must be done unconditionally. n = min_int(argc, end_field - first_field); for(i = 0; i < n; i++) { if (JS_ToFloat64(ctx, &a, argv[i])) return JS_EXCEPTION; if (!isfinite(a)) - res = false; + res = FALSE; fields[first_field + i] = trunc(a); } - if (!res) - return JS_NAN; + if (!res1) + return JS_NAN; /* thisTimeValue is NaN */ - if (argc > 0) + if (res && argc > 0) d = set_date_fields(fields, is_local); return JS_SetThisTimeValue(ctx, this_val, d); @@ -52370,16 +53494,14 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, break; } } - if (!pos) { - // XXX: should throw exception? - return js_empty_string(ctx->rt); - } - return js_new_string8_len(ctx, buf, pos); + return JS_NewStringLen(ctx, buf, pos); } /* OS dependent: return the UTC time in ms since 1970. */ static int64_t date_now(void) { - return js__gettimeofday_us() / 1000; + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000); } static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, @@ -52388,7 +53510,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, // Date(y, mon, d, h, m, s, ms) JSValue rv; int i, n; - double a, val; + double val; if (JS_IsUndefined(new_target)) { /* invoked as function */ @@ -52410,7 +53532,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, } v = JS_ToPrimitive(ctx, argv[0], HINT_NONE); if (JS_IsString(v)) { - dv = js_Date_parse(ctx, JS_UNDEFINED, 1, vc(&v)); + dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v); JS_FreeValue(ctx, v); if (JS_IsException(dv)) return JS_EXCEPTION; @@ -52426,20 +53548,23 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, if (n > 7) n = 7; for(i = 0; i < n; i++) { - if (JS_ToFloat64(ctx, &a, argv[i])) + if (JS_ToFloat64(ctx, &fields[i], argv[i])) return JS_EXCEPTION; - if (!isfinite(a)) - break; - fields[i] = trunc(a); - if (i == 0 && fields[0] >= 0 && fields[0] < 100) - fields[0] += 1900; } - val = (i == n) ? set_date_fields(fields, 1) : NAN; + val = set_date_fields_checked(fields, 1); } has_val: +#if 0 + JSValueConst args[3]; + args[0] = new_target; + args[1] = ctx->class_proto[JS_CLASS_DATE]; + args[2] = JS_NewFloat64(ctx, val); + rv = js___date_create(ctx, JS_UNDEFINED, 3, args); +#else rv = js_create_from_ctor(ctx, new_target, JS_CLASS_DATE); if (!JS_IsException(rv)) - JS_SetObjectData(ctx, rv, js_float64(val)); + JS_SetObjectData(ctx, rv, JS_NewFloat64(ctx, val)); +#endif if (!JS_IsException(rv) && JS_IsUndefined(new_target)) { /* invoked as a function, return (new Date()).toString(); */ JSValue s; @@ -52456,7 +53581,6 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, // UTC(y, mon, d, h, m, s, ms) double fields[] = { 0, 0, 1, 0, 0, 0, 0 }; int i, n; - double a; n = argc; if (n == 0) @@ -52464,25 +53588,20 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, if (n > 7) n = 7; for(i = 0; i < n; i++) { - if (JS_ToFloat64(ctx, &a, argv[i])) + if (JS_ToFloat64(ctx, &fields[i], argv[i])) return JS_EXCEPTION; - if (!isfinite(a)) - return JS_NAN; - fields[i] = trunc(a); - if (i == 0 && fields[0] >= 0 && fields[0] < 100) - fields[0] += 1900; } - return js_float64(set_date_fields(fields, 0)); + return JS_NewFloat64(ctx, set_date_fields_checked(fields, 0)); } /* Date string parsing */ -static bool string_skip_char(const uint8_t *sp, int *pp, int c) { +static BOOL string_skip_char(const uint8_t *sp, int *pp, int c) { if (sp[*pp] == c) { *pp += 1; - return true; + return TRUE; } else { - return false; + return FALSE; } } @@ -52511,7 +53630,7 @@ static int string_skip_until(const uint8_t *sp, int *pp, const char *stoplist) { } /* parse a numeric field (max_digits = 0 -> no maximum) */ -static bool string_get_digits(const uint8_t *sp, int *pp, int *pval, +static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval, int min_digits, int max_digits) { int v = 0; @@ -52521,20 +53640,20 @@ static bool string_get_digits(const uint8_t *sp, int *pp, int *pval, while ((c = sp[p]) >= '0' && c <= '9') { /* arbitrary limit to 9 digits */ if (v >= 100000000) - return false; + return FALSE; v = v * 10 + c - '0'; p++; if (p - p_start == max_digits) break; } if (p - p_start < min_digits) - return false; + return FALSE; *pval = v; *pp = p; - return true; + return TRUE; } -static bool string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) { +static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) { /* parse optional fractional part as milliseconds and truncate. */ /* spec does not indicate which rounding should be used */ int mul = 100, ms = 0, c, p_start, p = *pp; @@ -52556,20 +53675,24 @@ static bool string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) { *pp = p; } } - return true; + return TRUE; +} + +static uint8_t upper_ascii(uint8_t c) { + return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c; } -static bool string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, bool strict) { +static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) { int tz = 0, sgn, hh, mm, p = *pp; sgn = sp[p++]; if (sgn == '+' || sgn == '-') { int n = p; if (!string_get_digits(sp, &p, &hh, 1, 0)) - return false; + return FALSE; n = p - n; if (strict && n != 2 && n != 4) - return false; + return FALSE; while (n > 4) { n -= 2; hh /= 100; @@ -52579,33 +53702,38 @@ static bool string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, bool stric hh = hh / 100; } else { mm = 0; - if (string_skip_char(sp, &p, ':') /* optional separator */ - && !string_get_digits(sp, &p, &mm, 2, 2)) - return false; + if (string_skip_char(sp, &p, ':')) { + /* optional separator */ + if (!string_get_digits(sp, &p, &mm, 2, 2)) + return FALSE; + } else { + if (strict) + return FALSE; /* [+-]HH is not accepted in strict mode */ + } } if (hh > 23 || mm > 59) - return false; + return FALSE; tz = hh * 60 + mm; if (sgn != '+') tz = -tz; } else if (sgn != 'Z') { - return false; + return FALSE; } *pp = p; *tzp = tz; - return true; + return TRUE; } -static bool string_match(const uint8_t *sp, int *pp, const char *s) { +static BOOL string_match(const uint8_t *sp, int *pp, const char *s) { int p = *pp; while (*s != '\0') { - if (to_upper_ascii(sp[p]) != to_upper_ascii(*s++)) - return false; + if (upper_ascii(sp[p]) != upper_ascii(*s++)) + return FALSE; p++; } *pp = p; - return true; + return TRUE; } static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) { @@ -52613,7 +53741,7 @@ static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) { for (n = 0; n < count; n++) { for (i = 0;; i++) { - if (to_upper_ascii(sp[p + i]) != to_upper_ascii(list[n * 3 + i])) + if (upper_ascii(sp[p + i]) != upper_ascii(list[n * 3 + i])) break; if (i == 2) return n; @@ -52622,75 +53750,75 @@ static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) { return -1; } -static bool string_get_month(const uint8_t *sp, int *pp, int *pval) { +static BOOL string_get_month(const uint8_t *sp, int *pp, int *pval) { int n; n = find_abbrev(sp, *pp, month_names, 12); if (n < 0) - return false; + return FALSE; *pval = n + 1; *pp += 3; - return true; + return TRUE; } /* parse toISOString format */ -static bool js_date_parse_isostring(const uint8_t *sp, int fields[9], bool *is_local) { +static BOOL js_date_parse_isostring(const uint8_t *sp, int fields[9], BOOL *is_local) { int sgn, i, p = 0; /* initialize fields to the beginning of the Epoch */ for (i = 0; i < 9; i++) { fields[i] = (i == 2); } - *is_local = false; + *is_local = FALSE; /* year is either yyyy digits or [+-]yyyyyy */ sgn = sp[p]; if (sgn == '-' || sgn == '+') { p++; if (!string_get_digits(sp, &p, &fields[0], 6, 6)) - return false; + return FALSE; if (sgn == '-') { if (fields[0] == 0) - return false; // reject -000000 + return FALSE; // reject -000000 fields[0] = -fields[0]; } } else { if (!string_get_digits(sp, &p, &fields[0], 4, 4)) - return false; + return FALSE; } if (string_skip_char(sp, &p, '-')) { if (!string_get_digits(sp, &p, &fields[1], 2, 2)) /* month */ - return false; + return FALSE; if (fields[1] < 1) - return false; + return FALSE; fields[1] -= 1; if (string_skip_char(sp, &p, '-')) { if (!string_get_digits(sp, &p, &fields[2], 2, 2)) /* day */ - return false; + return FALSE; if (fields[2] < 1) - return false; + return FALSE; } } if (string_skip_char(sp, &p, 'T')) { - *is_local = true; + *is_local = TRUE; if (!string_get_digits(sp, &p, &fields[3], 2, 2) /* hour */ || !string_skip_char(sp, &p, ':') || !string_get_digits(sp, &p, &fields[4], 2, 2)) { /* minute */ fields[3] = 100; // reject unconditionally - return true; + return TRUE; } if (string_skip_char(sp, &p, ':')) { if (!string_get_digits(sp, &p, &fields[5], 2, 2)) /* second */ - return false; + return FALSE; string_get_milliseconds(sp, &p, &fields[6]); } } /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */ if (sp[p]) { - *is_local = false; - if (!string_get_tzoffset(sp, &p, &fields[8], true)) - return false; + *is_local = FALSE; + if (!string_get_tzoffset(sp, &p, &fields[8], TRUE)) + return FALSE; } /* error if extraneous characters */ return sp[p] == '\0'; @@ -52720,27 +53848,25 @@ static struct { { "EEST", +3 * 60 }, // Eastern European Summer Time }; -static bool string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) { - size_t i; - - for (i = 0; i < countof(js_tzabbr); i++) { +static BOOL string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) { + for (size_t i = 0; i < countof(js_tzabbr); i++) { if (string_match(sp, pp, js_tzabbr[i].name)) { *offset = js_tzabbr[i].offset; - return true; + return TRUE; } } - return false; + return FALSE; } /* parse toString, toUTCString and other formats */ -static bool js_date_parse_otherstring(const uint8_t *sp, +static BOOL js_date_parse_otherstring(const uint8_t *sp, int fields[minimum_length(9)], - bool *is_local) { + BOOL *is_local) { int c, i, val, p = 0, p_start; int num[3]; - bool has_year = false; - bool has_mon = false; - bool has_time = false; + BOOL has_year = FALSE; + BOOL has_mon = FALSE; + BOOL has_time = FALSE; int num_index = 0; /* initialize fields to the beginning of 2001-01-01 */ @@ -52750,23 +53876,23 @@ static bool js_date_parse_otherstring(const uint8_t *sp, for (i = 3; i < 9; i++) { fields[i] = 0; } - *is_local = true; + *is_local = TRUE; while (string_skip_spaces(sp, &p)) { p_start = p; if ((c = sp[p]) == '+' || c == '-') { - if (has_time && string_get_tzoffset(sp, &p, &fields[8], false)) { - *is_local = false; + if (has_time && string_get_tzoffset(sp, &p, &fields[8], FALSE)) { + *is_local = FALSE; } else { p++; if (string_get_digits(sp, &p, &val, 1, 0)) { if (c == '-') { if (val == 0) - return false; + return FALSE; val = -val; } fields[0] = val; - has_year = true; + has_year = TRUE; } } } else @@ -52775,52 +53901,48 @@ static bool js_date_parse_otherstring(const uint8_t *sp, /* time part */ fields[3] = val; if (!string_get_digits(sp, &p, &fields[4], 1, 2)) - return false; + return FALSE; if (string_skip_char(sp, &p, ':')) { if (!string_get_digits(sp, &p, &fields[5], 1, 2)) - return false; + return FALSE; string_get_milliseconds(sp, &p, &fields[6]); - } else - if (sp[p] != '\0' && sp[p] != ' ') - return false; - has_time = true; + } + has_time = TRUE; + if ((sp[p] == '+' || sp[p] == '-') && + string_get_tzoffset(sp, &p, &fields[8], FALSE)) { + *is_local = FALSE; + } } else { - if (p - p_start > 2) { + if (p - p_start > 2 && !has_year) { fields[0] = val; - has_year = true; + has_year = TRUE; } else - if (val < 1 || val > 31) { + if ((val < 1 || val > 31) && !has_year) { fields[0] = val + (val < 100) * 1900 + (val < 50) * 100; - has_year = true; + has_year = TRUE; } else { if (num_index == 3) - return false; + return FALSE; num[num_index++] = val; } } } else if (string_get_month(sp, &p, &fields[1])) { - has_mon = true; + has_mon = TRUE; string_skip_until(sp, &p, "0123456789 -/("); } else if (has_time && string_match(sp, &p, "PM")) { - /* hours greater than 12 will be incremented and - rejected by the range check in js_Date_parse */ - /* 00:00 PM will be silently converted as 12:00 */ - if (fields[3] != 12) + if (fields[3] < 12) fields[3] += 12; continue; } else if (has_time && string_match(sp, &p, "AM")) { - /* 00:00 AM will be silently accepted */ - if (fields[3] > 12) - return false; if (fields[3] == 12) fields[3] -= 12; continue; } else if (string_get_tzabbr(sp, &p, &fields[8])) { - *is_local = false; + *is_local = FALSE; continue; } else if (c == '(') { /* skip parenthesized phrase */ @@ -52833,25 +53955,25 @@ static bool js_date_parse_otherstring(const uint8_t *sp, break; } if (level > 0) - return false; + return FALSE; } else if (c == ')') { - return false; + return FALSE; } else { if (has_year + has_mon + has_time + num_index) - return false; + return FALSE; /* skip a word */ string_skip_until(sp, &p, " -/("); } string_skip_separators(sp, &p); } if (num_index + has_year + has_mon > 3) - return false; + return FALSE; switch (num_index) { case 0: if (!has_year) - return false; + return FALSE; break; case 1: if (has_mon) @@ -52878,12 +54000,12 @@ static bool js_date_parse_otherstring(const uint8_t *sp, fields[2] = num[1]; break; default: - return false; + return FALSE; } if (fields[1] < 1 || fields[2] < 1) - return false; + return FALSE; fields[1] -= 1; - return true; + return TRUE; } static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, @@ -52896,7 +54018,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, int i, c; JSString *sp; uint8_t buf[128]; - bool is_local; + BOOL is_local; rv = JS_NAN; @@ -52916,20 +54038,20 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, if (js_date_parse_isostring(buf, fields, &is_local) || js_date_parse_otherstring(buf, fields, &is_local)) { static int const field_max[6] = { 0, 11, 31, 24, 59, 59 }; - bool valid = true; + BOOL valid = TRUE; /* check field maximum values */ for (i = 1; i < 6; i++) { if (fields[i] > field_max[i]) - valid = false; + valid = FALSE; } /* special case 24:00:00.000 */ if (fields[3] == 24 && (fields[4] | fields[5] | fields[6])) - valid = false; + valid = FALSE; if (valid) { for(i = 0; i < 7; i++) fields1[i] = fields[i]; d = set_date_fields(fields1, is_local) - fields[8] * 60000; - rv = js_float64(d); + rv = JS_NewFloat64(ctx, d); } } JS_FreeValue(ctx, s); @@ -52940,7 +54062,7 @@ static JSValue js_Date_now(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { // now() - return js_int64(date_now()); + return JS_NewInt64(ctx, date_now()); } static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val, @@ -52987,7 +54109,7 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val, return JS_NAN; else /* assuming -8.64e15 <= v <= -8.64e15 */ - return js_int64(getTimezoneOffset((int64_t)trunc(v))); + return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v))); } static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val, @@ -52998,7 +54120,7 @@ static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val, if (JS_ThisTimeValue(ctx, &v, this_val)) return JS_EXCEPTION; - return js_float64(v); + return JS_NewFloat64(ctx, v); } static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val, @@ -53017,22 +54139,18 @@ static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val, { // setYear(y) double y; - JSValue d, ret; + JSValueConst args[1]; if (JS_ThisTimeValue(ctx, &y, this_val) || JS_ToFloat64(ctx, &y, argv[0])) return JS_EXCEPTION; y = +y; - if (isnan(y)) - return JS_SetThisTimeValue(ctx, this_val, y); if (isfinite(y)) { y = trunc(y); if (y >= 0 && y < 100) y += 1900; } - d = js_float64(y); - ret = set_date_field(ctx, this_val, 1, vc(&d), 0x011); - JS_FreeValue(ctx, d); - return ret; + args[0] = JS_NewFloat64(ctx, y); + return set_date_field(ctx, this_val, 1, args, 0x011); } static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val, @@ -53134,37 +54252,33 @@ JSValue JS_NewDate(JSContext *ctx, double epoch_ms) JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_DATE); if (JS_IsException(obj)) return JS_EXCEPTION; - JS_SetObjectData(ctx, obj, js_float64(time_clip(epoch_ms))); + JS_SetObjectData(ctx, obj, __JS_NewFloat64(ctx, time_clip(epoch_ms))); return obj; } -bool JS_IsDate(JSValueConst v) -{ - if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) - return false; - return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE; -} - -void JS_AddIntrinsicDate(JSContext *ctx) +int JS_AddIntrinsicDate(JSContext *ctx) { JSValue obj; /* Date */ - ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATE], js_date_proto_funcs, - countof(js_date_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Date", js_date_constructor, 7, - ctx->class_proto[JS_CLASS_DATE]); - JS_SetPropertyFunctionList(ctx, obj, js_date_funcs, countof(js_date_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATE, "Date", + js_date_constructor, 7, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_date_funcs, countof(js_date_funcs), + js_date_proto_funcs, countof(js_date_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + return 0; } /* eval */ -void JS_AddIntrinsicEval(JSContext *ctx) +int JS_AddIntrinsicEval(JSContext *ctx) { -#ifndef QJS_DISABLE_PARSER ctx->eval_internal = __JS_EvalInternal; -#endif // QJS_DISABLE_PARSER + return 0; } /* BigInt */ @@ -53202,6 +54316,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) } break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: val = JS_StringToBigIntErr(ctx, val); break; case JS_TAG_OBJECT: @@ -53224,19 +54339,19 @@ static JSValue js_bigint_constructor(JSContext *ctx, { if (!JS_IsUndefined(new_target)) return JS_ThrowTypeError(ctx, "not a constructor"); - return JS_ToBigIntCtorFree(ctx, js_dup(argv[0])); + return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0])); } static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val) { - if (JS_IsBigInt(this_val)) - return js_dup(this_val); + if (JS_IsBigInt(ctx, this_val)) + return JS_DupValue(ctx, this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); if (p->class_id == JS_CLASS_BIG_INT) { - if (JS_IsBigInt(p->u.object_data)) - return js_dup(p->u.object_data); + if (JS_IsBigInt(ctx, p->u.object_data)) + return JS_DupValue(ctx, p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a BigInt"); @@ -53279,7 +54394,7 @@ static JSValue js_bigint_asUintN(JSContext *ctx, { uint64_t bits; JSValue res, a; - + if (JS_ToIndex(ctx, &bits, argv[0])) return JS_EXCEPTION; a = JS_ToBigInt(ctx, argv[1]); @@ -53347,320 +54462,330 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicBigInt(JSContext *ctx) +static int JS_AddIntrinsicBigInt(JSContext *ctx) { JSValue obj1; - ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT], - js_bigint_proto_funcs, - countof(js_bigint_proto_funcs)); - obj1 = JS_NewGlobalCConstructor(ctx, "BigInt", js_bigint_constructor, 1, - ctx->class_proto[JS_CLASS_BIG_INT]); - JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs, - countof(js_bigint_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BIG_INT, "BigInt", + js_bigint_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_bigint_funcs, countof(js_bigint_funcs), + js_bigint_proto_funcs, countof(js_bigint_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + return 0; } -static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = { - "EvalError", "RangeError", "ReferenceError", - "SyntaxError", "TypeError", "URIError", - "InternalError", "AggregateError", -}; - /* Minimum amount of objects to be able to compile code and display - error messages. No JSAtom should be allocated by this function. */ -static void JS_AddIntrinsicBasicObjects(JSContext *ctx) + error messages. */ +static int JS_AddIntrinsicBasicObjects(JSContext *ctx) { - JSValue proto; + JSValue obj; + JSCFunctionType ft; int i; - ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL); - ctx->global_obj = JS_NewObject(ctx); - ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL); + /* warning: ordering is tricky */ + ctx->class_proto[JS_CLASS_OBJECT] = + JS_NewObjectProtoClassAlloc(ctx, JS_NULL, JS_CLASS_OBJECT, + countof(js_object_proto_funcs) + 1); + if (JS_IsException(ctx->class_proto[JS_CLASS_OBJECT])) + return -1; + JS_SetImmutablePrototype(ctx, ctx->class_proto[JS_CLASS_OBJECT]); + + /* 2 more properties: caller and arguments */ ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0, JS_CFUNC_generic, 0, - ctx->class_proto[JS_CLASS_OBJECT]); - ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = js_dup(ctx->function_proto); - ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR], - js_error_proto_funcs, - countof(js_error_proto_funcs)); + ctx->class_proto[JS_CLASS_OBJECT], + countof(js_function_proto_funcs) + 3 + 2); + if (JS_IsException(ctx->function_proto)) + return -1; + ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto); + + ctx->global_obj = JS_NewObjectProtoClassAlloc(ctx, ctx->class_proto[JS_CLASS_OBJECT], + JS_CLASS_OBJECT, 64); + if (JS_IsException(ctx->global_obj)) + return -1; + ctx->global_var_obj = JS_NewObjectProtoClassAlloc(ctx, JS_NULL, + JS_CLASS_OBJECT, 16); + if (JS_IsException(ctx->global_var_obj)) + return -1; + + /* Error */ + ft.generic_magic = js_error_constructor; + obj = JS_NewCConstructor(ctx, JS_CLASS_ERROR, "Error", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, -1, + JS_UNDEFINED, + js_error_funcs, countof(js_error_funcs), + js_error_proto_funcs, countof(js_error_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { - proto = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ERROR]); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_name, - JS_NewAtomString(ctx, native_error_name[i]), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_message, - js_empty_string(ctx->rt), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - ctx->native_error_proto[i] = proto; + JSValue func_obj; + const JSCFunctionListEntry *funcs; + int n_args; + char buf[ATOM_GET_STR_BUF_SIZE]; + const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), + JS_ATOM_EvalError + i); + n_args = 1 + (i == JS_AGGREGATE_ERROR); + funcs = js_native_error_proto_funcs + 2 * i; + func_obj = JS_NewCConstructor(ctx, -1, name, + ft.generic, n_args, JS_CFUNC_constructor_or_func_magic, i, + obj, + NULL, 0, + funcs, 2, + 0); + if (JS_IsException(func_obj)) { + JS_FreeValue(ctx, obj); + return -1; + } + ctx->native_error_proto[i] = JS_GetProperty(ctx, func_obj, JS_ATOM_prototype); + JS_FreeValue(ctx, func_obj); + if (JS_IsException(ctx->native_error_proto[i])) { + JS_FreeValue(ctx, obj); + return -1; + } } + JS_FreeValue(ctx, obj); - /* the array prototype is an array */ - ctx->class_proto[JS_CLASS_ARRAY] = - JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_ARRAY); + /* Array */ + obj = JS_NewCConstructor(ctx, JS_CLASS_ARRAY, "Array", + js_array_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_array_funcs, countof(js_array_funcs), + js_array_proto_funcs, countof(js_array_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj)) + return -1; + ctx->array_ctor = obj; ctx->array_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]), JS_PROP_INITIAL_HASH_SIZE, 1); - add_shape_property(ctx, &ctx->array_shape, NULL, - JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); - - /* XXX: could test it on first context creation to ensure that no - new atoms are created in JS_AddIntrinsicBasicObjects(). It is - necessary to avoid useless renumbering of atoms after - JS_EvalBinary() if it is done just after - JS_AddIntrinsicBasicObjects(). */ - // assert(ctx->rt->atom_count == JS_ATOM_END); + if (!ctx->array_shape) + return -1; + if (add_shape_property(ctx, &ctx->array_shape, NULL, + JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH)) + return -1; + ctx->std_array_prototype = TRUE; + + return 0; } -void JS_AddIntrinsicBaseObjects(JSContext *ctx) +int JS_AddIntrinsicBaseObjects(JSContext *ctx) { - int i; - JSValue obj, number_obj; - JSValue obj1; + JSValue obj1, obj2; + JSCFunctionType ft; ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0); - + if (JS_IsException(ctx->throw_type_error)) + return -1; /* add caller and arguments properties to throw a TypeError */ - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); - JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, vc(&ctx->throw_type_error), 1)); + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; + JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1)); /* Object */ - obj = JS_NewGlobalCConstructor(ctx, "Object", js_object_constructor, 1, - ctx->class_proto[JS_CLASS_OBJECT]); - JS_SetPropertyFunctionList(ctx, obj, js_object_funcs, countof(js_object_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_OBJECT], - js_object_proto_funcs, countof(js_object_proto_funcs)); - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_OBJECT, "Object", + js_object_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_object_funcs, countof(js_object_funcs), + js_object_proto_funcs, countof(js_object_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + /* Function */ - JS_SetPropertyFunctionList(ctx, ctx->function_proto, js_function_proto_funcs, countof(js_function_proto_funcs)); - ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor, - "Function", 1, JS_CFUNC_constructor_or_func_magic, - JS_FUNC_NORMAL); - JS_NewGlobalCConstructor2(ctx, js_dup(ctx->function_ctor), "Function", - ctx->function_proto); - - /* Error */ - ctx->error_ctor = JS_NewCFunctionMagic(ctx, js_error_constructor, - "Error", 1, JS_CFUNC_constructor_or_func_magic, -1); - JS_NewGlobalCConstructor2(ctx, js_dup(ctx->error_ctor), - "Error", ctx->class_proto[JS_CLASS_ERROR]); - JS_SetPropertyFunctionList(ctx, ctx->error_ctor, js_error_funcs, countof(js_error_funcs)); - - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft = { .generic_magic = js_error_constructor }; - for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { - JSValue func_obj; - int n_args; - n_args = 1 + (i == JS_AGGREGATE_ERROR); - func_obj = JS_NewCFunction3(ctx, ft.generic, - native_error_name[i], n_args, - JS_CFUNC_constructor_or_func_magic, i, - ctx->error_ctor); - JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i], - ctx->native_error_proto[i]); - } - - /* CallSite */ - _JS_AddIntrinsicCallSite(ctx); + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BYTECODE_FUNCTION, "Function", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_NORMAL, + JS_UNDEFINED, + NULL, 0, + js_function_proto_funcs, countof(js_function_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + ctx->function_ctor = obj1; /* Iterator */ - ctx->class_proto[JS_CLASS_ITERATOR] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - js_iterator_proto_funcs, - countof(js_iterator_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Iterator", js_iterator_constructor, 0, - ctx->class_proto[JS_CLASS_ITERATOR]); + obj2 = JS_NewCConstructor(ctx, JS_CLASS_ITERATOR, "Iterator", + js_iterator_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_iterator_funcs, countof(js_iterator_funcs), + js_iterator_proto_funcs, countof(js_iterator_proto_funcs), + 0); + if (JS_IsException(obj2)) + return -1; // quirk: Iterator.prototype.constructor is an accessor property // TODO(bnoordhuis) mildly inefficient because JS_NewGlobalCConstructor // first creates a .constructor value property that we then replace with // an accessor - ctx->iterator_ctor_getset = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, - 0, 0, 1, vc(&obj)); - JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - JS_ATOM_constructor, JS_UNDEFINED, - ctx->iterator_ctor_getset, ctx->iterator_ctor_getset, - JS_PROP_HAS_GET|JS_PROP_HAS_SET|JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); - ctx->iterator_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, - js_iterator_funcs, - countof(js_iterator_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_CONCAT] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_CONCAT], - js_iterator_concat_proto_funcs, - countof(js_iterator_concat_proto_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_HELPER], - js_iterator_helper_proto_funcs, - countof(js_iterator_helper_proto_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP], - js_iterator_wrap_proto_funcs, - countof(js_iterator_wrap_proto_funcs)); - - /* Array */ - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY], - js_array_proto_funcs, - countof(js_array_proto_funcs)); - - obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY]); - ctx->array_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, js_array_funcs, - countof(js_array_funcs)); - JS_DefineAutoInitProperty(ctx, obj, JS_ATOM_fromAsync, - JS_AUTOINIT_ID_BYTECODE, - (void *)(uintptr_t)JS_BUILTIN_ARRAY_FROMASYNC, - JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); - - /* XXX: create auto_initializer */ - { - /* initialize Array.prototype[Symbol.unscopables] */ - static const char unscopables[] = - "copyWithin" "\0" - "entries" "\0" - "fill" "\0" - "find" "\0" - "findIndex" "\0" - "findLast" "\0" - "findLastIndex" "\0" - "flat" "\0" - "flatMap" "\0" - "includes" "\0" - "keys" "\0" - "toReversed" "\0" - "toSorted" "\0" - "toSpliced" "\0" - "values" "\0"; - const char *p = unscopables; - obj1 = JS_NewObjectProto(ctx, JS_NULL); - for(p = unscopables; *p; p += strlen(p) + 1) { - JS_DefinePropertyValueStr(ctx, obj1, p, JS_TRUE, JS_PROP_C_W_E); - } - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ARRAY], - JS_ATOM_Symbol_unscopables, obj1, - JS_PROP_CONFIGURABLE); + obj1 = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, + 0, 0, 1, (JSValueConst *)&obj2); + if (JS_IsException(obj1)) { + JS_FreeValue(ctx, obj2); + return -1; + } + if (JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + JS_ATOM_constructor, JS_UNDEFINED, + obj1, obj1, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE) < 0) { + JS_FreeValue(ctx, obj2); + JS_FreeValue(ctx, obj1); + return -1; } + JS_FreeValue(ctx, obj1); + ctx->iterator_ctor = obj2; + + ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_helper_proto_funcs, + countof(js_iterator_helper_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_HELPER])) + return -1; + + ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_wrap_proto_funcs, + countof(js_iterator_wrap_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_WRAP])) + return -1; /* needed to initialize arguments[Symbol.iterator] */ ctx->array_proto_values = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values); + if (JS_IsException(ctx->array_proto_values)) + return -1; - ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR], - js_array_iterator_proto_funcs, - countof(js_array_iterator_proto_funcs)); + ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_array_iterator_proto_funcs, + countof(js_array_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ARRAY_ITERATOR])) + return -1; /* parseFloat and parseInteger must be defined before Number because of the Number.parseFloat and Number.parseInteger aliases */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, - countof(js_global_funcs)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, + countof(js_global_funcs))) + return -1; /* Number */ - ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_NUMBER); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], js_int32(0)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER], - js_number_proto_funcs, - countof(js_number_proto_funcs)); - number_obj = JS_NewGlobalCConstructor(ctx, "Number", js_number_constructor, 1, - ctx->class_proto[JS_CLASS_NUMBER]); - JS_SetPropertyFunctionList(ctx, number_obj, js_number_funcs, countof(js_number_funcs)); - + obj1 = JS_NewCConstructor(ctx, JS_CLASS_NUMBER, "Number", + js_number_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_number_funcs, countof(js_number_funcs), + js_number_proto_funcs, countof(js_number_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0))) + return -1; + /* Boolean */ - ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_BOOLEAN); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_FALSE); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs, - countof(js_boolean_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1, - ctx->class_proto[JS_CLASS_BOOLEAN]); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BOOLEAN, "Boolean", + js_boolean_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_boolean_proto_funcs, countof(js_boolean_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE))) + return -1; /* String */ - ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_STRING); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], js_empty_string(ctx->rt)); - obj = JS_NewGlobalCConstructor(ctx, "String", js_string_constructor, 1, - ctx->class_proto[JS_CLASS_STRING]); - JS_SetPropertyFunctionList(ctx, obj, js_string_funcs, - countof(js_string_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs, - countof(js_string_proto_funcs)); - - ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR], - js_string_iterator_proto_funcs, - countof(js_string_iterator_proto_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_STRING, "String", + js_string_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_string_funcs, countof(js_string_funcs), + js_string_proto_funcs, countof(js_string_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], JS_AtomToString(ctx, JS_ATOM_empty_string))) + return -1; + + ctx->class_proto[JS_CLASS_STRING_ITERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_string_iterator_proto_funcs, + countof(js_string_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_STRING_ITERATOR])) + return -1; /* Math: create as autoinit object */ js_random_init(ctx); - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj))) + return -1; /* ES6 Reflect: create as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj))) + return -1; /* ES6 Symbol */ - ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs, - countof(js_symbol_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Symbol", js_symbol_constructor, 0, - ctx->class_proto[JS_CLASS_SYMBOL]); - JS_SetPropertyFunctionList(ctx, obj, js_symbol_funcs, - countof(js_symbol_funcs)); - for(i = JS_ATOM_Symbol_toPrimitive; i < JS_ATOM_END; i++) { - char buf[ATOM_GET_STR_BUF_SIZE]; - const char *str, *p; - str = JS_AtomGetStr(ctx, buf, sizeof(buf), i); - /* skip "Symbol." */ - p = strchr(str, '.'); - if (p) - str = p + 1; - JS_DefinePropertyValueStr(ctx, obj, str, JS_AtomToValue(ctx, i), 0); - } - - /* ES6 Generator */ - ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR], - js_generator_proto_funcs, - countof(js_generator_proto_funcs)); - - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); - obj1 = JS_NewCFunctionMagic(ctx, js_function_constructor, - "GeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - js_generator_function_proto_funcs, - countof(js_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_SYMBOL, "Symbol", + js_symbol_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_symbol_funcs, countof(js_symbol_funcs), + js_symbol_proto_funcs, countof(js_symbol_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); + + /* ES6 Generator */ + ctx->class_proto[JS_CLASS_GENERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_generator_proto_funcs, + countof(js_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_GENERATOR])) + return -1; + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_GENERATOR_FUNCTION, "GeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_generator_function_proto_funcs, + countof(js_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE)) + return -1; + /* global properties */ - ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, - js_dup(ctx->eval_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + ctx->eval_obj = JS_GetProperty(ctx, ctx->global_obj, JS_ATOM_eval); + if (JS_IsException(ctx->eval_obj)) + return -1; + + if (JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, + JS_DupValue(ctx, ctx->global_obj), + JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE) < 0) + return -1; - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, - js_dup(ctx->global_obj), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + /* BigInt */ + if (JS_AddIntrinsicBigInt(ctx)) + return -1; + return 0; } /* Typed Arrays */ @@ -53677,7 +54802,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JSClassID class_id, uint8_t *buf, JSFreeArrayBufferDataFunc *free_func, - void *opaque, bool alloc_flag) + void *opaque, BOOL alloc_flag) { JSRuntime *rt = ctx->rt; JSValue obj; @@ -53733,13 +54858,13 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, abuf->data = buf; } init_list_head(&abuf->array_list); - abuf->detached = false; + abuf->detached = FALSE; abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER); abuf->opaque = opaque; abuf->free_func = free_func; if (alloc_flag && buf) memcpy(abuf->data, buf, len); - JS_SetOpaqueInternal(obj, abuf); + JS_SetOpaque(obj, abuf); return obj; fail: JS_FreeValue(ctx, obj); @@ -53757,9 +54882,9 @@ static JSValue js_array_buffer_constructor2(JSContext *ctx, uint64_t len, uint64_t *max_len, JSClassID class_id) { - return js_array_buffer_constructor3(ctx, new_target, len, max_len, - class_id, NULL, js_array_buffer_free, - NULL, true); + return js_array_buffer_constructor3(ctx, new_target, len, max_len, class_id, + NULL, js_array_buffer_free, NULL, + TRUE); } static JSValue js_array_buffer_constructor1(JSContext *ctx, @@ -53772,16 +54897,12 @@ static JSValue js_array_buffer_constructor1(JSContext *ctx, JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared) + BOOL is_shared) { JSClassID class_id = is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER; return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, class_id, - buf, free_func, opaque, false); -} - -bool JS_IsArrayBuffer(JSValueConst obj) { - return JS_GetClassID(obj) == JS_CLASS_ARRAY_BUFFER; + buf, free_func, opaque, FALSE); } /* create a new ArrayBuffer of length 'len' and copy 'buf' to it */ @@ -53791,19 +54912,19 @@ JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len) JS_CLASS_ARRAY_BUFFER, (uint8_t *)buf, js_array_buffer_free, NULL, - true); + TRUE); } static JSValue js_array_buffer_constructor0(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, JSClassID class_id) -{ + { uint64_t len, max_len, *pmax_len = NULL; JSValue obj, val; int64_t i; - if (JS_ToIndex(ctx, &len, argv[0])) - return JS_EXCEPTION; + if (JS_ToIndex(ctx, &len, argv[0])) + return JS_EXCEPTION; if (argc < 2) goto next; if (!JS_IsObject(argv[1])) @@ -53829,7 +54950,8 @@ static JSValue js_array_buffer_constructor0(JSContext *ctx, JSValueConst new_tar class_id); } -static JSValue js_array_buffer_constructor(JSContext *ctx, JSValueConst new_target, +static JSValue js_array_buffer_constructor(JSContext *ctx, + JSValueConst new_target, int argc, JSValueConst *argv) { return js_array_buffer_constructor0(ctx, new_target, argc, argv, @@ -53845,7 +54967,7 @@ static JSValue js_shared_array_buffer_constructor(JSContext *ctx, } /* also used for SharedArrayBuffer */ -static void js_array_buffer_finalizer(JSRuntime *rt, JSValueConst val) +static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSArrayBuffer *abuf = p->u.array_buffer; @@ -53884,13 +55006,16 @@ static JSValue js_array_buffer_isView(JSContext *ctx, int argc, JSValueConst *argv) { JSObject *p; - + BOOL res; + res = FALSE; if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(argv[0]); - return js_bool(is_typed_array(p->class_id) || - p->class_id == JS_CLASS_DATAVIEW); + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_DATAVIEW) { + res = TRUE; + } } - return JS_FALSE; + return JS_NewBool(ctx, res); } static const JSCFunctionListEntry js_array_buffer_funcs[] = { @@ -53910,14 +55035,14 @@ static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx) // #sec-get-arraybuffer.prototype.detached static JSValue js_array_buffer_get_detached(JSContext *ctx, - JSValueConst this_val) + JSValueConst this_val) { JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); if (!abuf) return JS_EXCEPTION; if (abuf->shared) return JS_ThrowTypeError(ctx, "detached called on SharedArrayBuffer"); - return js_bool(abuf->detached); + return JS_NewBool(ctx, abuf->detached); } static JSValue js_array_buffer_get_byteLength(JSContext *ctx, @@ -53928,7 +55053,7 @@ static JSValue js_array_buffer_get_byteLength(JSContext *ctx, if (!abuf) return JS_EXCEPTION; /* return 0 if detached */ - return js_uint32(abuf->byte_length); + return JS_NewUint32(ctx, abuf->byte_length); } static JSValue js_array_buffer_get_maxByteLength(JSContext *ctx, @@ -53939,8 +55064,8 @@ static JSValue js_array_buffer_get_maxByteLength(JSContext *ctx, if (!abuf) return JS_EXCEPTION; if (array_buffer_is_resizable(abuf)) - return js_uint32(abuf->max_byte_length); - return js_uint32(abuf->byte_length); + return JS_NewUint32(ctx, abuf->max_byte_length); + return JS_NewUint32(ctx, abuf->byte_length); } static JSValue js_array_buffer_get_resizable(JSContext *ctx, @@ -53950,7 +55075,7 @@ static JSValue js_array_buffer_get_resizable(JSContext *ctx, JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id); if (!abuf) return JS_EXCEPTION; - return js_bool(array_buffer_is_resizable(abuf)); + return JS_NewBool(ctx, array_buffer_is_resizable(abuf)); } void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) @@ -53964,7 +55089,7 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) abuf->free_func(ctx->rt, abuf->opaque, abuf->data); abuf->data = NULL; abuf->byte_length = 0; - abuf->detached = true; + abuf->detached = TRUE; list_for_each(el, &abuf->array_list) { JSTypedArray *ta; @@ -54014,19 +55139,19 @@ uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj) return NULL; } -static bool array_buffer_is_resizable(const JSArrayBuffer *abuf) +static BOOL array_buffer_is_resizable(const JSArrayBuffer *abuf) { return abuf->max_byte_length >= 0; } // ES #sec-arraybuffer.prototype.transfer -static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_array_buffer_transfer(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + int transfer_to_fixed_length) { - bool transfer_to_fixed_length = magic & 1; JSArrayBuffer *abuf; - uint64_t new_len, old_len, max_len, *pmax_len; - uint8_t *bs, *new_bs; + uint64_t new_len, *pmax_len, max_len; abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); if (!abuf) @@ -54053,28 +55178,50 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, /* create an empty AB */ if (new_len == 0) { JS_DetachArrayBuffer(ctx, this_val); - return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len, - JS_CLASS_ARRAY_BUFFER); - } - bs = abuf->data; - old_len = abuf->byte_length; - /* if length mismatch, realloc. Otherwise, use the same backing buffer. */ - if (new_len != old_len) { - new_bs = js_realloc(ctx, bs, new_len); - if (!new_bs) - return JS_EXCEPTION; - bs = new_bs; - if (new_len > old_len) - memset(bs + old_len, 0, new_len - old_len); + return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len, JS_CLASS_ARRAY_BUFFER); + } else { + uint64_t old_len; + uint8_t *bs, *new_bs; + JSFreeArrayBufferDataFunc *free_func; + + bs = abuf->data; + old_len = abuf->byte_length; + free_func = abuf->free_func; + + /* if length mismatch, realloc. Otherwise, use the same backing buffer. */ + if (new_len != old_len) { + /* XXX: we are currently limited to 2 GB */ + if (new_len > INT32_MAX) + return JS_ThrowRangeError(ctx, "invalid array buffer length"); + + if (free_func != js_array_buffer_free) { + /* cannot use js_realloc() because the buffer was + allocated with a custom allocator */ + new_bs = js_mallocz(ctx, new_len); + if (!new_bs) + return JS_EXCEPTION; + memcpy(new_bs, bs, min_int(old_len, new_len)); + abuf->free_func(ctx->rt, abuf->opaque, bs); + bs = new_bs; + free_func = js_array_buffer_free; + } else { + new_bs = js_realloc(ctx, bs, new_len); + if (!new_bs) + return JS_EXCEPTION; + bs = new_bs; + if (new_len > old_len) + memset(bs + old_len, 0, new_len - old_len); + } + } + /* neuter the backing buffer */ + abuf->data = NULL; + abuf->byte_length = 0; + abuf->detached = TRUE; + return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len, + JS_CLASS_ARRAY_BUFFER, + bs, free_func, + NULL, FALSE); } - /* neuter the backing buffer */ - abuf->data = NULL; - abuf->byte_length = 0; - abuf->detached = true; - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len, - JS_CLASS_ARRAY_BUFFER, - bs, abuf->free_func, - NULL, false); } static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, @@ -54132,12 +55279,8 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, list_for_each(el, &abuf->array_list) { ta = list_entry(el, JSTypedArray, link); p = ta->obj; - if (p->class_id == JS_CLASS_DATAVIEW) { - if (ta->track_rab && ta->offset < len) - ta->length = len - ta->offset; - + if (p->class_id == JS_CLASS_DATAVIEW) continue; - } p->u.array.count = 0; p->u.array.u.ptr = NULL; size_log2 = typed_array_size_log2(p->class_id); @@ -54189,8 +55332,8 @@ static JSValue js_array_buffer_slice(JSContext *ctx, NULL, class_id); } else { JSValue args[1]; - args[0] = js_int64(new_len); - new_obj = JS_CallConstructor(ctx, ctor, 1, vc(args)); + args[0] = JS_NewInt64(ctx, new_len); + new_obj = JS_CallConstructor(ctx, ctor, 1, (JSValueConst *)args); JS_FreeValue(ctx, ctor); JS_FreeValue(ctx, args[0]); } @@ -54250,45 +55393,68 @@ static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ), }; -static bool is_typed_array(JSClassID class_id) +static JSObject *get_typed_array(JSContext *ctx, JSValueConst this_val) { - return class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY; + JSObject *p; + if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) + goto fail; + p = JS_VALUE_GET_OBJ(this_val); + if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY)) { + fail: + JS_ThrowTypeError(ctx, "not a TypedArray"); + return NULL; + } + return p; } // is the typed array detached or out of bounds relative to its RAB? // |p| must be a typed array, *not* a DataView -static bool typed_array_is_oob(JSObject *p) +static BOOL typed_array_is_oob(JSObject *p) { JSArrayBuffer *abuf; JSTypedArray *ta; int len, size_elem; int64_t end; - assert(is_typed_array(p->class_id)); + assert(p->class_id >= JS_CLASS_UINT8C_ARRAY); + assert(p->class_id <= JS_CLASS_FLOAT64_ARRAY); ta = p->u.typed_array; abuf = ta->buffer->u.array_buffer; if (abuf->detached) - return true; + return TRUE; len = abuf->byte_length; if (ta->offset > len) - return true; + return TRUE; if (ta->track_rab) - return false; + return FALSE; if (len < (int64_t)ta->offset + ta->length) - return true; + return TRUE; size_elem = 1 << typed_array_size_log2(p->class_id); end = (int64_t)ta->offset + (int64_t)p->u.array.count * size_elem; return end > len; } -/* WARNING: 'p' must be a typed array. Works even if the array buffer - is detached */ -static uint32_t typed_array_length(JSObject *p) +// Be *very* careful if you touch the typed array's memory directly: +// the length is only valid until the next call into JS land because +// JS code can detach or resize the backing array buffer. Functions +// like JS_GetProperty and JS_ToIndex call JS code. +// +// Exclusively reading or writing elements with JS_GetProperty, +// JS_GetPropertyInt64, JS_SetProperty, etc. is safe because they +// perform bounds checks, as does js_get_fast_array_element. +static int js_typed_array_get_length_unsafe(JSContext *ctx, JSValueConst obj) { - JSTypedArray *ta = p->u.typed_array; - int size_log2 = typed_array_size_log2(p->class_id); - return ta->length >> size_log2; + JSObject *p; + p = get_typed_array(ctx, obj); + if (!p) + return -1; + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); + return -1; + } + return p->u.array.count; } static int validate_typed_array(JSContext *ctx, JSValueConst this_val) @@ -54304,16 +55470,18 @@ static int validate_typed_array(JSContext *ctx, JSValueConst this_val) return 0; } -static JSValue js_typed_array_get_length(JSContext *ctx, JSValueConst this_val) +static JSValue js_typed_array_get_length(JSContext *ctx, + JSValueConst this_val) { JSObject *p; p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; - return js_int32(p->u.array.count); + return JS_NewInt32(ctx, p->u.array.count); } -static JSValue js_typed_array_get_buffer(JSContext *ctx, JSValueConst this_val) +static JSValue js_typed_array_get_buffer(JSContext *ctx, + JSValueConst this_val) { JSObject *p; JSTypedArray *ta; @@ -54321,28 +55489,30 @@ static JSValue js_typed_array_get_buffer(JSContext *ctx, JSValueConst this_val) if (!p) return JS_EXCEPTION; ta = p->u.typed_array; - return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); } -static JSValue js_typed_array_get_byteLength(JSContext *ctx, JSValueConst this_val) +static JSValue js_typed_array_get_byteLength(JSContext *ctx, + JSValueConst this_val) { - uint32_t size_log2; - JSTypedArray *ta; JSObject *p; + JSTypedArray *ta; + int size_log2; p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; if (typed_array_is_oob(p)) - return js_int32(0); + return JS_NewInt32(ctx, 0); ta = p->u.typed_array; if (!ta->track_rab) - return js_uint32(ta->length); + return JS_NewUint32(ctx, ta->length); size_log2 = typed_array_size_log2(p->class_id); - return js_int64((int64_t)p->u.array.count << size_log2); + return JS_NewInt64(ctx, (int64_t)p->u.array.count << size_log2); } -static JSValue js_typed_array_get_byteOffset(JSContext *ctx, JSValueConst this_val) +static JSValue js_typed_array_get_byteOffset(JSContext *ctx, + JSValueConst this_val) { JSObject *p; JSTypedArray *ta; @@ -54350,9 +55520,9 @@ static JSValue js_typed_array_get_byteOffset(JSContext *ctx, JSValueConst this_v if (!p) return JS_EXCEPTION; if (typed_array_is_oob(p)) - return js_int32(0); + return JS_NewInt32(ctx, 0); ta = p->u.typed_array; - return js_uint32(ta->offset); + return JS_NewUint32(ctx, ta->offset); } JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, @@ -54388,35 +55558,7 @@ JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, if (pbytes_per_element) { *pbytes_per_element = 1 << typed_array_size_log2(p->class_id); } - return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); -} - -/* return NULL if exception. WARNING: any JS call can detach the - buffer and render the returned pointer invalid */ -uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValueConst obj) -{ - JSObject *p; - JSTypedArray *ta; - JSArrayBuffer *abuf; - p = get_typed_array(ctx, obj); - if (!p) - goto fail; - if (typed_array_is_oob(p)) { - JS_ThrowTypeErrorArrayBufferOOB(ctx); - goto fail; - } - if (p->class_id != JS_CLASS_UINT8_ARRAY && p->class_id != JS_CLASS_UINT8C_ARRAY) { - JS_ThrowTypeError(ctx, "not a Uint8Array"); - goto fail; - } - ta = p->u.typed_array; - abuf = ta->buffer->u.array_buffer; - - *psize = ta->length; - return abuf->data + ta->offset; - fail: - *psize = 0; - return NULL; + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); } static JSValue js_typed_array_get_toStringTag(JSContext *ctx, @@ -54426,7 +55568,8 @@ static JSValue js_typed_array_get_toStringTag(JSContext *ctx, if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) return JS_UNDEFINED; p = JS_VALUE_GET_OBJ(this_val); - if (!is_typed_array(p->class_id)) + if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY)) return JS_UNDEFINED; return JS_AtomToString(ctx, ctx->rt->class_array[p->class_id].class_name); } @@ -54459,7 +55602,8 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, if (JS_IsException(src_obj)) goto fail; src_p = JS_VALUE_GET_OBJ(src_obj); - if (is_typed_array(src_p->class_id)) { + if (src_p->class_id >= JS_CLASS_UINT8C_ARRAY && + src_p->class_id <= JS_CLASS_FLOAT64_ARRAY) { JSTypedArray *dest_ta = p->u.typed_array; JSArrayBuffer *dest_abuf = dest_ta->buffer->u.array_buffer; JSTypedArray *src_ta = src_p->u.typed_array; @@ -54500,14 +55644,8 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, val = JS_GetPropertyUint32(ctx, src_obj, i); if (JS_IsException(val)) goto fail; - // Per spec: detaching the TA mid-iteration is allowed and should - // not throw an exception. Because iteration over the source array is - // observable, we cannot bail out early when the TA is first detached. - if (typed_array_is_oob(p)) { - JS_FreeValue(ctx, val); - } else if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0) { + if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0) goto fail; - } } done: JS_FreeValue(ctx, src_obj); @@ -54526,8 +55664,9 @@ static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val, p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_oob(p)) - return JS_ThrowTypeErrorArrayBufferOOB(ctx); + return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); len = p->u.array.count; // note: can change p->u.array.count @@ -54537,37 +55676,10 @@ static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val, if (idx < 0) idx = len + idx; - if (idx < 0 || idx >= p->u.array.count) + len = p->u.array.count; + if (idx < 0 || idx >= len) return JS_UNDEFINED; - - switch (p->class_id) { - case JS_CLASS_INT8_ARRAY: - return js_int32(p->u.array.u.int8_ptr[idx]); - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - return js_int32(p->u.array.u.uint8_ptr[idx]); - case JS_CLASS_INT16_ARRAY: - return js_int32(p->u.array.u.int16_ptr[idx]); - case JS_CLASS_UINT16_ARRAY: - return js_int32(p->u.array.u.uint16_ptr[idx]); - case JS_CLASS_INT32_ARRAY: - return js_int32(p->u.array.u.int32_ptr[idx]); - case JS_CLASS_UINT32_ARRAY: - return js_uint32(p->u.array.u.uint32_ptr[idx]); - case JS_CLASS_FLOAT16_ARRAY: - return js_float64(fromfp16(p->u.array.u.fp16_ptr[idx])); - case JS_CLASS_FLOAT32_ARRAY: - return js_float64(p->u.array.u.float_ptr[idx]); - case JS_CLASS_FLOAT64_ARRAY: - return js_float64(p->u.array.u.double_ptr[idx]); - case JS_CLASS_BIG_INT64_ARRAY: - return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]); - case JS_CLASS_BIG_UINT64_ARRAY: - return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]); - } - - abort(); /* unreachable */ - return JS_UNDEFINED; + return JS_GetPropertyInt64(ctx, this_val, idx); } static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, @@ -54575,37 +55687,35 @@ static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, { JSValue arr, val; JSObject *p; - int64_t idx; - uint32_t len, oldlen, newlen; + int64_t idx, len; p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - oldlen = p->u.array.count; + len = p->u.array.count; if (JS_ToInt64Sat(ctx, &idx, argv[0])) return JS_EXCEPTION; + if (idx < 0) + idx = len + idx; + val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER); if (JS_IsException(val)) return JS_EXCEPTION; - newlen = p->u.array.count; - if (idx < 0) - idx = newlen + idx; - if (idx < 0 || idx >= newlen) { - JS_FreeValue(ctx, val); + if (typed_array_is_oob(p) || idx < 0 || idx >= p->u.array.count) return JS_ThrowRangeError(ctx, "invalid array index"); - } - len = min_uint32(oldlen, newlen); arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, p->class_id, len); if (JS_IsException(arr)) { JS_FreeValue(ctx, val); return JS_EXCEPTION; } - if (idx < len && JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { + if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { JS_FreeValue(ctx, arr); return JS_EXCEPTION; } @@ -54647,7 +55757,7 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, goto fail; if (argc == 1) { /* ensure that it is large enough */ - if (JS_ToLengthFree(ctx, &len, js_dup(argv[0]))) + if (JS_ToLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]))) goto fail; if (new_len < len) { JS_ThrowTypeError(ctx, "TypedArray length is too small"); @@ -54659,6 +55769,15 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, return ret; } +#if 0 +static JSValue js_typed_array___create(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return js_typed_array_create(ctx, argv[0], max_int(argc - 1, 0), argv + 1); +} +#endif + static JSValue js_typed_array___speciesCreate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -54692,18 +55811,16 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, // from(items, mapfn = void 0, this_arg = void 0) JSValueConst items = argv[0], mapfn, this_arg; JSValueConst args[2]; - JSValue stack[2]; JSValue iter, arr, r, v, v2; int64_t k, len; - int done, mapping; + int mapping; - mapping = false; + mapping = FALSE; mapfn = JS_UNDEFINED; this_arg = JS_UNDEFINED; r = JS_UNDEFINED; arr = JS_UNDEFINED; - stack[0] = JS_UNDEFINED; - stack[1] = JS_UNDEFINED; + iter = JS_UNDEFINED; if (argc > 1) { mapfn = argv[1]; @@ -54718,32 +55835,26 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator); if (JS_IsException(iter)) goto exception; - if (!JS_IsUndefined(iter)) { - JS_FreeValue(ctx, iter); - arr = JS_NewArray(ctx); - if (JS_IsException(arr)) - goto exception; - stack[0] = js_dup(items); - if (js_for_of_start(ctx, &stack[1], false)) + if (!JS_IsUndefined(iter) && !JS_IsNull(iter)) { + uint32_t len1; + if (!JS_IsFunction(ctx, iter)) { + JS_ThrowTypeError(ctx, "value is not iterable"); goto exception; - for (k = 0;; k++) { - v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done); - if (JS_IsException(v)) - goto exception_close; - if (done) - break; - if (JS_DefinePropertyValueInt64(ctx, arr, k, v, JS_PROP_C_W_E | JS_PROP_THROW) < 0) - goto exception_close; } + arr = js_array_from_iterator(ctx, &len1, items, iter); + if (JS_IsException(arr)) + goto exception; + len = len1; } else { arr = JS_ToObject(ctx, items); if (JS_IsException(arr)) goto exception; + if (js_get_length64(ctx, &len, arr) < 0) + goto exception; } - if (js_get_length64(ctx, &len, arr) < 0) - goto exception; - v = js_int64(len); - r = js_typed_array_create(ctx, this_val, 1, vc(&v)); + v = JS_NewInt64(ctx, len); + args[0] = v; + r = js_typed_array_create(ctx, this_val, 1, args); JS_FreeValue(ctx, v); if (JS_IsException(r)) goto exception; @@ -54753,7 +55864,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, goto exception; if (mapping) { args[0] = v; - args[1] = js_int32(k); + args[1] = JS_NewInt32(ctx, k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -54764,33 +55875,29 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, goto exception; } goto done; - - exception_close: - if (!JS_IsUndefined(stack[0])) - JS_IteratorClose(ctx, stack[0], true); exception: JS_FreeValue(ctx, r); r = JS_EXCEPTION; done: JS_FreeValue(ctx, arr); - JS_FreeValue(ctx, stack[0]); - JS_FreeValue(ctx, stack[1]); + JS_FreeValue(ctx, iter); return r; } static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue v, obj; + JSValue obj; + JSValueConst args[1]; int i; - v = js_int32(argc); - obj = js_typed_array_create(ctx, this_val, 1, vc(&v)); + args[0] = JS_NewInt32(ctx, argc); + obj = js_typed_array_create(ctx, this_val, 1, args); if (JS_IsException(obj)) return obj; for(i = 0; i < argc; i++) { - if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0) { + if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -54836,7 +55943,7 @@ static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val, p->u.array.u.uint8_ptr + (from << shift), count << shift); } - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, @@ -54855,7 +55962,7 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, if (p->class_id == JS_CLASS_UINT8C_ARRAY) { int32_t v; - if (JS_ToUint8ClampFree(ctx, &v, js_dup(argv[0]))) + if (JS_ToUint8ClampFree(ctx, &v, JS_DupValue(ctx, argv[0]))) return JS_EXCEPTION; v64 = v; } else if (p->class_id <= JS_CLASS_UINT32_ARRAY) { @@ -54863,8 +55970,7 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, if (JS_ToUint32(ctx, &v, argv[0])) return JS_EXCEPTION; v64 = v; - } else - if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) { + } else if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) { if (JS_ToBigInt64(ctx, (int64_t *)&v64, argv[0])) return JS_EXCEPTION; } else { @@ -54929,13 +56035,14 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, default: abort(); } - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int mode) { - JSValueConst func, this_arg, args[3]; + JSValueConst func, this_arg; + JSValueConst args[3]; JSValue val, index_val, res; int len, k, end; int dir; @@ -54963,7 +56070,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, } for(; k != end; k += dir) { - index_val = js_int32(k); + index_val = JS_NewInt32(ctx, k); val = JS_GetPropertyValue(ctx, this_val, index_val); if (JS_IsException(val)) goto exception; @@ -54984,7 +56091,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, val); } if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) - return js_int32(-1); + return JS_NewInt32(ctx, -1); else return JS_UNDEFINED; @@ -55032,28 +56139,17 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } else { k = 0; if (argc > 1) { - if (JS_ToInt32Sat(ctx, &k, argv[1])) + if (JS_ToInt32Clamp(ctx, &k, argv[1], 0, len, len)) goto exception; - if (k < 0) { - k += len; - if (k < 0) - k = 0; - } else if (k > len) { - k = len; - } } stop = len; inc = 1; } - /* if the array was detached, no need to go further (but no - exception is raised) */ - if (typed_array_is_oob(p) || len > p->u.array.count) { - /* "includes" scans all the properties, so "undefined" can match */ - if (special == special_includes) - if (JS_IsUndefined(argv[0])) - if (k < typed_array_length(p)) - res = 0; + /* includes function: 'undefined' can be found if searching out of bounds */ + if (len > p->u.array.count && special == special_includes && + JS_IsUndefined(argv[0]) && k < len) { + res = 0; goto done; } @@ -55061,7 +56157,10 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, len = min_int(len, p->u.array.count); if (len == 0) goto done; - k = min_int(k, len); + if (special == special_lastIndexOf) + k = min_int(k, len - 1); + else + k = min_int(k, len); stop = min_int(stop, len); is_bigint = 0; @@ -55087,7 +56186,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, p1 = js_bigint_set_short(&buf1, argv[0]); else p1 = JS_VALUE_GET_PTR(argv[0]); - + if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) { if (p1->len > sz) goto done; /* does not fit an int64 : cannot be found */ @@ -55284,9 +56383,9 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, done: if (special == special_includes) - return js_bool(res >= 0); + return JS_NewBool(ctx, res >= 0); else - return js_int32(res); + return JS_NewInt32(ctx, res); exception: return JS_EXCEPTION; @@ -55316,7 +56415,7 @@ static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val, goto exception; s = JS_VALUE_GET_STRING(sep); if (s->len == 1 && !s->is_wide_char) - c = str8(s)[0]; + c = s->u.str8[0]; else c = -1; // ToString(sep) can detach or resize the arraybuffer as a side effect @@ -55431,7 +56530,7 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val, abort(); } } - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val, @@ -55452,6 +56551,18 @@ static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val, return ret; } +static void slice_memcpy(uint8_t *dst, const uint8_t *src, size_t len) +{ + if (dst + len <= src || dst >= src + len) { + /* no overlap: can use memcpy */ + memcpy(dst, src, len); + } else { + /* otherwise the spec mandates byte copy */ + while (len-- != 0) + *dst++ = *src++; + } +} + static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -55463,7 +56574,7 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, arr = JS_UNDEFINED; p = get_typed_array(ctx, this_val); if (!p) - return JS_EXCEPTION; + goto exception; if (typed_array_is_oob(p)) return JS_ThrowTypeErrorArrayBufferOOB(ctx); len = p->u.array.count; @@ -55477,8 +56588,10 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, } count = max_int(final - start, 0); + shift = typed_array_size_log2(p->class_id); + args[0] = this_val; - args[1] = js_int32(count); + args[1] = JS_NewInt32(ctx, count); arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(arr)) goto exception; @@ -55488,26 +56601,19 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, || validate_typed_array(ctx, arr)) goto exception; - if (len != p->u.array.count) - goto slow_path; - p1 = get_typed_array(ctx, arr); - if (p1 != NULL && p->class_id == p1->class_id && - typed_array_length(p1) >= count && - typed_array_length(p) >= start + count) { - shift = typed_array_size_log2(p->class_id); - memmove(p1->u.array.u.uint8_ptr, - p->u.array.u.uint8_ptr + (start << shift), - count << shift); + space = max_int(0, p->u.array.count - start); + count = min_int(count, space); + if (p1 != NULL && p->class_id == p1->class_id) { + slice_memcpy(p1->u.array.u.uint8_ptr, + p->u.array.u.uint8_ptr + (start << shift), + count << shift); } else { - slow_path: - space = max_int(0, p->u.array.count - start); - count = min_int(count, space); for (n = 0; n < count; n++) { - val = JS_GetPropertyValue(ctx, this_val, js_int32(start + n)); + val = JS_GetPropertyValue(ctx, this_val, JS_NewInt32(ctx, start + n)); if (JS_IsException(val)) goto exception; - if (JS_SetPropertyValue(ctx, arr, js_int32(n), val, + if (JS_SetPropertyValue(ctx, arr, JS_NewInt32(ctx, n), val, JS_PROP_THROW) < 0) goto exception; } @@ -55523,53 +56629,45 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSArrayBuffer *abuf; - JSTypedArray *ta; JSValueConst args[4]; - JSValue arr, byteOffset, ta_buffer; + JSValue arr, ta_buffer; + JSTypedArray *ta; JSObject *p; int len, start, final, count, shift, offset; - + BOOL is_auto; + p = get_typed_array(ctx, this_val); if (!p) goto exception; len = p->u.array.count; if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) goto exception; + + shift = typed_array_size_log2(p->class_id); + ta = p->u.typed_array; + /* Read byteOffset (ta->offset) even if detached */ + offset = ta->offset + (start << shift); + final = len; - if (!JS_IsUndefined(argv[1])) { + if (JS_IsUndefined(argv[1])) { + is_auto = ta->track_rab; + } else { + is_auto = FALSE; if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len)) goto exception; - } + } count = max_int(final - start, 0); - byteOffset = js_typed_array_get_byteOffset(ctx, this_val); - if (JS_IsException(byteOffset)) - goto exception; - ta = p->u.typed_array; - abuf = ta->buffer->u.array_buffer; - if (ta->offset > abuf->byte_length) - goto range_error; - if (ta->offset == abuf->byte_length && count > 0) { - range_error: - JS_ThrowRangeError(ctx, "invalid offset"); - goto exception; - } - shift = typed_array_size_log2(p->class_id); - offset = JS_VALUE_GET_INT(byteOffset) + (start << shift); - JS_FreeValue(ctx, byteOffset); ta_buffer = js_typed_array_get_buffer(ctx, this_val); if (JS_IsException(ta_buffer)) goto exception; args[0] = this_val; - args[1] = safe_const(ta_buffer); - args[2] = safe_const(js_int32(offset)); - args[3] = safe_const(js_int32(count)); - // result is length-tracking if source TA is and no explicit count is given - if (ta->track_rab && JS_IsUndefined(argv[1])) - args[3] = JS_UNDEFINED; - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 4, args); + args[1] = ta_buffer; + args[2] = JS_NewInt32(ctx, offset); + args[3] = JS_NewInt32(ctx, count); + arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, is_auto ? 3 : 4, args); JS_FreeValue(ctx, ta_buffer); return arr; + exception: return JS_EXCEPTION; } @@ -55641,27 +56739,27 @@ static int js_TA_cmp_float64(const void *a, const void *b, void *opaque) { } static JSValue js_TA_get_int8(JSContext *ctx, const void *a) { - return js_int32(*(const int8_t *)a); + return JS_NewInt32(ctx, *(const int8_t *)a); } static JSValue js_TA_get_uint8(JSContext *ctx, const void *a) { - return js_int32(*(const uint8_t *)a); + return JS_NewInt32(ctx, *(const uint8_t *)a); } static JSValue js_TA_get_int16(JSContext *ctx, const void *a) { - return js_int32(*(const int16_t *)a); + return JS_NewInt32(ctx, *(const int16_t *)a); } static JSValue js_TA_get_uint16(JSContext *ctx, const void *a) { - return js_int32(*(const uint16_t *)a); + return JS_NewInt32(ctx, *(const uint16_t *)a); } static JSValue js_TA_get_int32(JSContext *ctx, const void *a) { - return js_int32(*(const int32_t *)a); + return JS_NewInt32(ctx, *(const int32_t *)a); } static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) { - return js_uint32(*(const uint32_t *)a); + return JS_NewUint32(ctx, *(const uint32_t *)a); } static JSValue js_TA_get_int64(JSContext *ctx, const void *a) { @@ -55673,20 +56771,20 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) { } static JSValue js_TA_get_float16(JSContext *ctx, const void *a) { - return js_float64(fromfp16(*(const uint16_t *)a)); + return __JS_NewFloat64(ctx, fromfp16(*(const uint16_t *)a)); } static JSValue js_TA_get_float32(JSContext *ctx, const void *a) { - return js_float64(*(const float *)a); + return __JS_NewFloat64(ctx, *(const float *)a); } static JSValue js_TA_get_float64(JSContext *ctx, const void *a) { - return js_float64(*(const double *)a); + return __JS_NewFloat64(ctx, *(const double *)a); } struct TA_sort_context { JSContext *ctx; - int exception; + int exception; /* 1 = exception, 2 = detached typed array */ JSValueConst arr; JSValueConst cmp; JSValue (*getfun)(JSContext *ctx, const void *a); @@ -55697,26 +56795,28 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { struct TA_sort_context *psc = opaque; JSContext *ctx = psc->ctx; uint32_t a_idx, b_idx; - JSValue argv[2]; + JSValueConst argv[2]; JSValue res; - JSObject *p; int cmp; - - p = JS_VALUE_GET_OBJ(psc->arr); - if (typed_array_is_oob(p)) - return 0; - + JSObject *p; + cmp = 0; if (!psc->exception) { + /* Note: the typed array can be detached without causing an + error */ a_idx = *(uint32_t *)a; b_idx = *(uint32_t *)b; - if (a_idx >= p->u.array.count || b_idx >= p->u.array.count) + p = JS_VALUE_GET_PTR(psc->arr); + if (a_idx >= p->u.array.count || b_idx >= p->u.array.count) { + /* OOB case */ + psc->exception = 2; return 0; - argv[0] = psc->getfun(ctx, (char *)p->u.array.u.ptr + + } + argv[0] = psc->getfun(ctx, p->u.array.u.uint8_ptr + a_idx * (size_t)psc->elt_size); - argv[1] = psc->getfun(ctx, (char *)p->u.array.u.ptr + + argv[1] = psc->getfun(ctx, p->u.array.u.uint8_ptr + b_idx * (size_t)(psc->elt_size)); - res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, vc(argv)); + res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv); if (JS_IsException(res)) { psc->exception = 1; goto done; @@ -55738,8 +56838,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { cmp = (a_idx > b_idx) - (a_idx < b_idx); } done: - JS_FreeValue(ctx, argv[0]); - JS_FreeValue(ctx, argv[1]); + JS_FreeValue(ctx, JS_VALUE_CONST_CAST(argv[0])); + JS_FreeValue(ctx, JS_VALUE_CONST_CAST(argv[1])); } return cmp; } @@ -55753,12 +56853,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, struct TA_sort_context tsc; int (*cmpfun)(const void *a, const void *b, void *opaque); - p = get_typed_array(ctx, this_val); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_oob(p)) - return JS_ThrowTypeErrorArrayBufferOOB(ctx); - tsc.ctx = ctx; tsc.exception = 0; tsc.arr = this_val; @@ -55766,9 +56860,12 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp)) return JS_EXCEPTION; + len = js_typed_array_get_length_unsafe(ctx, this_val); + if (len < 0) + return JS_EXCEPTION; - len = p->u.array.count; if (len > 1) { + p = JS_VALUE_GET_OBJ(this_val); switch (p->class_id) { case JS_CLASS_INT8_ARRAY: tsc.getfun = js_TA_get_int8; @@ -55833,51 +56930,52 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, tsc.elt_size = elt_size; rqsort(array_idx, len, sizeof(array_idx[0]), js_TA_cmp_generic, &tsc); - if (tsc.exception) - goto fail; - // per spec: typed array can be detached mid-iteration - if (typed_array_is_oob(p)) - goto done; - len = min_int(len, p->u.array.count); - if (len == 0) - goto done; - array_tmp = js_malloc(ctx, len * elt_size); - if (!array_tmp) { - fail: - js_free(ctx, array_idx); - return JS_EXCEPTION; - } - memcpy(array_tmp, p->u.array.u.ptr, len * elt_size); - switch(elt_size) { - case 1: - for(i = 0; i < len; i++) { - j = array_idx[i]; - p->u.array.u.uint8_ptr[i] = ((uint8_t *)array_tmp)[j]; - } - break; - case 2: - for(i = 0; i < len; i++) { - j = array_idx[i]; - p->u.array.u.uint16_ptr[i] = ((uint16_t *)array_tmp)[j]; - } - break; - case 4: - for(i = 0; i < len; i++) { - j = array_idx[i]; - p->u.array.u.uint32_ptr[i] = ((uint32_t *)array_tmp)[j]; - } - break; - case 8: - for(i = 0; i < len; i++) { - j = array_idx[i]; - p->u.array.u.uint64_ptr[i] = ((uint64_t *)array_tmp)[j]; + if (tsc.exception) { + if (tsc.exception == 1) + goto fail; + /* detached typed array during the sort: no error */ + } else { + void *array_ptr = p->u.array.u.ptr; + len = min_int(len, p->u.array.count); + if (len != 0) { + array_tmp = js_malloc(ctx, len * elt_size); + if (!array_tmp) { + fail: + js_free(ctx, array_idx); + return JS_EXCEPTION; + } + memcpy(array_tmp, array_ptr, len * elt_size); + switch(elt_size) { + case 1: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j]; + } + break; + case 2: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j]; + } + break; + case 4: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j]; + } + break; + case 8: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j]; + } + break; + default: + abort(); + } + js_free(ctx, array_tmp); } - break; - default: - abort(); } - js_free(ctx, array_tmp); - done: js_free(ctx, array_idx); } else { rqsort(p->u.array.u.ptr, len, elt_size, cmpfun, &tsc); @@ -55885,7 +56983,7 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } } - return js_dup(this_val); + return JS_DupValue(ctx, this_val); } static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val, @@ -55952,6 +57050,13 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { //JS_ALIAS_BASE_DEF("toString", "toString", 2 /* Array.prototype. */), @@@ }; +static const JSCFunctionListEntry js_typed_array_funcs[] = { + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 1, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 2, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 4, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 8, 0), +}; + static JSValue js_typed_array_base_constructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -55960,8 +57065,9 @@ static JSValue js_typed_array_base_constructor(JSContext *ctx, } /* 'obj' must be an allocated typed array object */ -static int typed_array_init(JSContext *ctx, JSValue obj, JSValue buffer, - uint64_t offset, uint64_t len, bool track_rab) +static int typed_array_init(JSContext *ctx, JSValueConst obj, + JSValue buffer, uint64_t offset, uint64_t len, + BOOL track_rab) { JSTypedArray *ta; JSObject *p, *pbuffer; @@ -55994,7 +57100,7 @@ static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen, JSValueConst obj, JSValueConst method) { JSValue arr, iter, next_method = JS_UNDEFINED, val; - int done; + BOOL done; uint32_t k; *plen = 0; @@ -56057,7 +57163,7 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx, } else { if (js_get_length64(ctx, &len, obj)) goto fail; - arr = js_dup(obj); + arr = JS_DupValue(ctx, obj); } buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, @@ -56065,7 +57171,7 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx, NULL); if (JS_IsException(buffer)) goto fail; - if (typed_array_init(ctx, ret, buffer, 0, len, /*track_rab*/false)) + if (typed_array_init(ctx, ret, buffer, 0, len, /*track_rab*/FALSE)) goto fail; for(i = 0; i < len; i++) { @@ -56119,7 +57225,7 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, goto fail; } abuf = JS_GetOpaque(buffer, JS_CLASS_ARRAY_BUFFER); - if (typed_array_init(ctx, obj, buffer, 0, len, /*track_rab*/false)) + if (typed_array_init(ctx, obj, buffer, 0, len, /*track_rab*/FALSE)) goto fail; if (p->class_id == classid) { /* same type: copy the content */ @@ -56145,7 +57251,7 @@ static JSValue js_typed_array_constructor(JSContext *ctx, int argc, JSValueConst *argv, int classid) { - bool track_rab = false; + BOOL track_rab = FALSE; JSValue buffer, obj; JSArrayBuffer *abuf; int size_log2; @@ -56189,9 +57295,10 @@ static JSValue js_typed_array_constructor(JSContext *ctx, return JS_ThrowRangeError(ctx, "invalid length"); } } - buffer = js_dup(argv[0]); + buffer = JS_DupValue(ctx, argv[0]); } else { - if (is_typed_array(p->class_id)) { + if (p->class_id >= JS_CLASS_UINT8C_ARRAY && + p->class_id <= JS_CLASS_FLOAT64_ARRAY) { return js_typed_array_constructor_ta(ctx, new_target, argv[0], classid, p->u.array.count); } else { @@ -56212,7 +57319,7 @@ static JSValue js_typed_array_constructor(JSContext *ctx, return obj; } -static void js_typed_array_finalizer(JSRuntime *rt, JSValueConst val) +static void js_typed_array_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSTypedArray *ta = p->u.typed_array; @@ -56241,8 +57348,8 @@ static JSValue js_dataview_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { - bool recompute_len = false; - bool track_rab = false; + BOOL recompute_len = FALSE; + BOOL track_rab = FALSE; JSArrayBuffer *abuf; uint64_t offset; uint32_t len; @@ -56273,7 +57380,7 @@ static JSValue js_dataview_constructor(JSContext *ctx, return JS_ThrowRangeError(ctx, "invalid byteLength"); len = l; } else { - recompute_len = true; + recompute_len = TRUE; track_rab = array_buffer_is_resizable(abuf); } @@ -56303,7 +57410,7 @@ static JSValue js_dataview_constructor(JSContext *ctx, } p = JS_VALUE_GET_OBJ(obj); ta->obj = p; - ta->buffer = JS_VALUE_GET_OBJ(js_dup(buffer)); + ta->buffer = JS_VALUE_GET_OBJ(JS_DupValue(ctx, buffer)); ta->offset = offset; ta->length = len; ta->track_rab = track_rab; @@ -56313,7 +57420,7 @@ static JSValue js_dataview_constructor(JSContext *ctx, } // is the DataView out of bounds relative to its parent arraybuffer? -static bool dataview_is_oob(JSObject *p) +static BOOL dataview_is_oob(JSObject *p) { JSArrayBuffer *abuf; JSTypedArray *ta; @@ -56322,11 +57429,11 @@ static bool dataview_is_oob(JSObject *p) ta = p->u.typed_array; abuf = ta->buffer->u.array_buffer; if (abuf->detached) - return true; + return TRUE; if (ta->offset > abuf->byte_length) - return true; + return TRUE; if (ta->track_rab) - return false; + return FALSE; return (int64_t)ta->offset + ta->length > abuf->byte_length; } @@ -56352,7 +57459,7 @@ static JSValue js_dataview_get_buffer(JSContext *ctx, JSValueConst this_val) if (!p) return JS_EXCEPTION; ta = p->u.typed_array; - return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); + return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); } static JSValue js_dataview_get_byteLength(JSContext *ctx, JSValueConst this_val) @@ -56369,9 +57476,9 @@ static JSValue js_dataview_get_byteLength(JSContext *ctx, JSValueConst this_val) ta = p->u.typed_array; if (ta->track_rab) { abuf = ta->buffer->u.array_buffer; - return js_uint32(abuf->byte_length - ta->offset); + return JS_NewUint32(ctx, abuf->byte_length - ta->offset); } - return js_uint32(ta->length); + return JS_NewUint32(ctx, ta->length); } static JSValue js_dataview_get_byteOffset(JSContext *ctx, JSValueConst this_val) @@ -56385,7 +57492,7 @@ static JSValue js_dataview_get_byteOffset(JSContext *ctx, JSValueConst this_val) if (dataview_is_oob(p)) return JS_ThrowTypeErrorArrayBufferOOB(ctx); ta = p->u.typed_array; - return js_uint32(ta->offset); + return JS_NewUint32(ctx, ta->offset); } static JSValue js_dataview_getValue(JSContext *ctx, @@ -56394,7 +57501,7 @@ static JSValue js_dataview_getValue(JSContext *ctx, { JSTypedArray *ta; JSArrayBuffer *abuf; - bool littleEndian, is_swap; + BOOL littleEndian, is_swap; int size; uint8_t *ptr; uint32_t v; @@ -56423,29 +57530,29 @@ static JSValue js_dataview_getValue(JSContext *ctx, switch(class_id) { case JS_CLASS_INT8_ARRAY: - return js_int32(*(int8_t *)ptr); + return JS_NewInt32(ctx, *(int8_t *)ptr); case JS_CLASS_UINT8_ARRAY: - return js_int32(*(uint8_t *)ptr); + return JS_NewInt32(ctx, *(uint8_t *)ptr); case JS_CLASS_INT16_ARRAY: v = get_u16(ptr); if (is_swap) v = bswap16(v); - return js_int32((int16_t)v); + return JS_NewInt32(ctx, (int16_t)v); case JS_CLASS_UINT16_ARRAY: v = get_u16(ptr); if (is_swap) v = bswap16(v); - return js_int32(v); + return JS_NewInt32(ctx, v); case JS_CLASS_INT32_ARRAY: v = get_u32(ptr); if (is_swap) v = bswap32(v); - return js_int32(v); + return JS_NewInt32(ctx, v); case JS_CLASS_UINT32_ARRAY: v = get_u32(ptr); if (is_swap) v = bswap32(v); - return js_uint32(v); + return JS_NewUint32(ctx, v); case JS_CLASS_BIG_INT64_ARRAY: { uint64_t v; @@ -56470,7 +57577,7 @@ static JSValue js_dataview_getValue(JSContext *ctx, v = get_u16(ptr); if (is_swap) v = bswap16(v); - return js_float64(fromfp16(v)); + return __JS_NewFloat64(ctx, fromfp16(v)); } case JS_CLASS_FLOAT32_ARRAY: { @@ -56482,7 +57589,7 @@ static JSValue js_dataview_getValue(JSContext *ctx, if (is_swap) v = bswap32(v); u.i = v; - return js_float64(u.f); + return __JS_NewFloat64(ctx, u.f); } case JS_CLASS_FLOAT64_ARRAY: { @@ -56493,12 +57600,11 @@ static JSValue js_dataview_getValue(JSContext *ctx, u.i = get_u64(ptr); if (is_swap) u.i = bswap64(u.i); - return js_float64(u.f); + return __JS_NewFloat64(ctx, u.f); } default: abort(); } - return JS_EXCEPTION; // pacify compiler } static JSValue js_dataview_setValue(JSContext *ctx, @@ -56507,7 +57613,7 @@ static JSValue js_dataview_setValue(JSContext *ctx, { JSTypedArray *ta; JSArrayBuffer *abuf; - bool littleEndian, is_swap; + BOOL littleEndian, is_swap; int size; uint8_t *ptr; uint64_t v64; @@ -56625,56 +57731,6 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ), }; -static JSValue js_new_uint8array(JSContext *ctx, JSValue buffer) -{ - if (JS_IsException(buffer)) - return JS_EXCEPTION; - JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_UINT8_ARRAY); - if (JS_IsException(obj)) { - JS_FreeValue(ctx, buffer); - return JS_EXCEPTION; - } - JSArrayBuffer *abuf = js_get_array_buffer(ctx, buffer); - assert(abuf != NULL); - if (typed_array_init(ctx, obj, buffer, 0, abuf->byte_length, /*track_rab*/false)) { - // 'buffer' is freed on error above. - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - return obj; -} - -JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared) -{ - JSClassID class_id = - is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER; - JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, - class_id, buf, free_func, - opaque, false); - return js_new_uint8array(ctx, buffer); -} - -JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len) -{ - JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, - JS_CLASS_ARRAY_BUFFER, - (uint8_t *)buf, - js_array_buffer_free, NULL, - true); - return js_new_uint8array(ctx, buffer); -} - -int JS_GetTypedArrayType(JSValueConst obj) -{ - JSClassID class_id = JS_GetClassID(obj); - if (is_typed_array(class_id)) - return class_id - JS_CLASS_UINT8C_ARRAY; - else - return -1; -} - /* Atomics */ #ifdef CONFIG_ATOMICS @@ -56689,19 +57745,20 @@ typedef enum AtomicsOpEnum { ATOMICS_OP_LOAD, } AtomicsOpEnum; -static void *js_atomics_get_ptr(JSContext *ctx, - JSArrayBuffer **pabuf, - int *psize_log2, JSClassID *pclass_id, - JSValueConst obj, JSValueConst idx_val, - int is_waitable) +static int js_atomics_get_ptr(JSContext *ctx, + void **pptr, + JSArrayBuffer **pabuf, + int *psize_log2, JSClassID *pclass_id, + JSValueConst obj, JSValueConst idx_val, + int is_waitable) { JSObject *p; JSTypedArray *ta; JSArrayBuffer *abuf; void *ptr; uint64_t idx; - bool err; - int size_log2; + BOOL err; + int size_log2, old_len; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) goto fail; @@ -56715,28 +57772,46 @@ static void *js_atomics_get_ptr(JSContext *ctx, if (err) { fail: JS_ThrowTypeError(ctx, "integer TypedArray expected"); - return NULL; + return -1; } ta = p->u.typed_array; abuf = ta->buffer->u.array_buffer; if (!abuf->shared) { if (is_waitable == 2) { JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray"); - return NULL; + return -1; } if (abuf->detached) { JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return NULL; + return -1; } } + old_len = p->u.array.count; + if (JS_ToIndex(ctx, &idx, idx_val)) { - return NULL; + return -1; } - /* if the array buffer is detached, p->u.array.count = 0 */ - if (idx >= p->u.array.count) { - JS_ThrowRangeError(ctx, "out-of-bound access"); - return NULL; + + if (idx >= old_len) + goto oob; + + if (is_waitable == 1) { + /* notify(): just avoid having an invalid pointer if overflow */ + if (idx >= p->u.array.count) + ptr = NULL; + } else { + /* RevalidateAtomicAccess() */ + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); + return -1; + } + if (idx >= p->u.array.count) { + oob: + JS_ThrowRangeError(ctx, "out-of-bound access"); + return -1; + } } + size_log2 = typed_array_size_log2(p->class_id); ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); if (pabuf) @@ -56745,7 +57820,8 @@ static void *js_atomics_get_ptr(JSContext *ctx, *psize_log2 = size_log2; if (pclass_id) *pclass_id = p->class_id; - return ptr; + *pptr = ptr; + return 0; } static JSValue js_atomics_op(JSContext *ctx, @@ -56759,9 +57835,8 @@ static JSValue js_atomics_op(JSContext *ctx, JSClassID class_id; JSArrayBuffer *abuf; - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, &class_id, - argv[0], argv[1], 0); - if (!ptr) + if (js_atomics_get_ptr(ctx, &ptr, &abuf, &size_log2, &class_id, + argv[0], argv[1], 0)) return JS_EXCEPTION; rep_val = 0; if (op == ATOMICS_OP_LOAD) { @@ -56778,15 +57853,15 @@ static JSValue js_atomics_op(JSContext *ctx, rep_val = v64; } } else { - uint32_t v32; - if (JS_ToUint32(ctx, &v32, argv[2])) - return JS_EXCEPTION; - v = v32; - if (op == ATOMICS_OP_COMPARE_EXCHANGE) { - if (JS_ToUint32(ctx, &v32, argv[3])) - return JS_EXCEPTION; - rep_val = v32; - } + uint32_t v32; + if (JS_ToUint32(ctx, &v32, argv[2])) + return JS_EXCEPTION; + v = v32; + if (op == ATOMICS_OP_COMPARE_EXCHANGE) { + if (JS_ToUint32(ctx, &v32, argv[3])) + return JS_EXCEPTION; + rep_val = v32; + } } if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); @@ -56796,17 +57871,18 @@ static JSValue js_atomics_op(JSContext *ctx, #define OP(op_name, func_name) \ case ATOMICS_OP_ ## op_name | (0 << 3): \ - a = func_name((_Atomic uint8_t *)ptr, v); \ + a = func_name((_Atomic(uint8_t) *)ptr, v); \ break; \ case ATOMICS_OP_ ## op_name | (1 << 3): \ - a = func_name((_Atomic uint16_t *)ptr, v); \ + a = func_name((_Atomic(uint16_t) *)ptr, v); \ break; \ case ATOMICS_OP_ ## op_name | (2 << 3): \ - a = func_name((_Atomic uint32_t *)ptr, v); \ + a = func_name((_Atomic(uint32_t) *)ptr, v); \ break; \ case ATOMICS_OP_ ## op_name | (3 << 3): \ - a = func_name((_Atomic uint64_t *)ptr, v); \ + a = func_name((_Atomic(uint64_t) *)ptr, v); \ break; + OP(ADD, atomic_fetch_add) OP(AND, atomic_fetch_and) OP(OR, atomic_fetch_or) @@ -56816,42 +57892,43 @@ static JSValue js_atomics_op(JSContext *ctx, #undef OP case ATOMICS_OP_LOAD | (0 << 3): - a = atomic_load((_Atomic uint8_t *)ptr); + a = atomic_load((_Atomic(uint8_t) *)ptr); break; case ATOMICS_OP_LOAD | (1 << 3): - a = atomic_load((_Atomic uint16_t *)ptr); + a = atomic_load((_Atomic(uint16_t) *)ptr); break; case ATOMICS_OP_LOAD | (2 << 3): - a = atomic_load((_Atomic uint32_t *)ptr); + a = atomic_load((_Atomic(uint32_t) *)ptr); break; case ATOMICS_OP_LOAD | (3 << 3): - a = atomic_load((_Atomic uint64_t *)ptr); + a = atomic_load((_Atomic(uint64_t) *)ptr); break; + case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3): { uint8_t v1 = v; - atomic_compare_exchange_strong((_Atomic uint8_t *)ptr, &v1, rep_val); + atomic_compare_exchange_strong((_Atomic(uint8_t) *)ptr, &v1, rep_val); a = v1; } break; case ATOMICS_OP_COMPARE_EXCHANGE | (1 << 3): { uint16_t v1 = v; - atomic_compare_exchange_strong((_Atomic uint16_t *)ptr, &v1, rep_val); + atomic_compare_exchange_strong((_Atomic(uint16_t) *)ptr, &v1, rep_val); a = v1; } break; case ATOMICS_OP_COMPARE_EXCHANGE | (2 << 3): { uint32_t v1 = v; - atomic_compare_exchange_strong((_Atomic uint32_t *)ptr, &v1, rep_val); + atomic_compare_exchange_strong((_Atomic(uint32_t) *)ptr, &v1, rep_val); a = v1; } break; case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3): { uint64_t v1 = v; - atomic_compare_exchange_strong((_Atomic uint64_t *)ptr, &v1, rep_val); + atomic_compare_exchange_strong((_Atomic(uint64_t) *)ptr, &v1, rep_val); a = v1; } break; @@ -56874,10 +57951,10 @@ static JSValue js_atomics_op(JSContext *ctx, goto done; case JS_CLASS_INT32_ARRAY: done: - ret = js_int32(a); + ret = JS_NewInt32(ctx, a); break; case JS_CLASS_UINT32_ARRAY: - ret = js_uint32(a); + ret = JS_NewUint32(ctx, a); break; case JS_CLASS_BIG_INT64_ARRAY: ret = JS_NewBigInt64(ctx, a); @@ -56900,13 +57977,12 @@ static JSValue js_atomics_store(JSContext *ctx, JSValue ret; JSArrayBuffer *abuf; - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, NULL, - argv[0], argv[1], 0); - if (!ptr) + if (js_atomics_get_ptr(ctx, &ptr, &abuf, &size_log2, NULL, + argv[0], argv[1], 0)) return JS_EXCEPTION; if (size_log2 == 3) { int64_t v64; - ret = JS_ToBigIntFree(ctx, js_dup(argv[2])); + ret = JS_ToBigIntFree(ctx, JS_DupValue(ctx, argv[2])); if (JS_IsException(ret)) return ret; if (JS_ToBigInt64(ctx, &v64, ret)) { @@ -56915,11 +57991,11 @@ static JSValue js_atomics_store(JSContext *ctx, } if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - atomic_store((_Atomic uint64_t *)ptr, v64); + atomic_store((_Atomic(uint64_t) *)ptr, v64); } else { uint32_t v; /* XXX: spec, would be simpler to return the written value */ - ret = JS_ToIntegerFree(ctx, js_dup(argv[2])); + ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2])); if (JS_IsException(ret)) return ret; if (JS_ToUint32(ctx, &v, ret)) { @@ -56930,13 +58006,13 @@ static JSValue js_atomics_store(JSContext *ctx, return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); switch(size_log2) { case 0: - atomic_store((_Atomic uint8_t *)ptr, v); + atomic_store((_Atomic(uint8_t) *)ptr, v); break; case 1: - atomic_store((_Atomic uint16_t *)ptr, v); + atomic_store((_Atomic(uint16_t) *)ptr, v); break; case 2: - atomic_store((_Atomic uint32_t *)ptr, v); + atomic_store((_Atomic(uint32_t) *)ptr, v); break; default: abort(); @@ -56953,21 +58029,36 @@ static JSValue js_atomics_isLockFree(JSContext *ctx, if (JS_ToInt32Sat(ctx, &v, argv[0])) return JS_EXCEPTION; ret = (v == 1 || v == 2 || v == 4 || v == 8); - return js_bool(ret); + return JS_NewBool(ctx, ret); } typedef struct JSAtomicsWaiter { struct list_head link; - bool linked; - js_cond_t cond; + BOOL linked; + pthread_cond_t cond; int32_t *ptr; } JSAtomicsWaiter; -static js_once_t js_atomics_once = JS_ONCE_INIT; -static js_mutex_t js_atomics_mutex; +static pthread_mutex_t js_atomics_mutex = PTHREAD_MUTEX_INITIALIZER; static struct list_head js_atomics_waiter_list = LIST_HEAD_INIT(js_atomics_waiter_list); +#if defined(__aarch64__) +static inline void cpu_pause(void) +{ + asm volatile("yield" ::: "memory"); +} +#elif defined(__x86_64) || defined(__i386__) +static inline void cpu_pause(void) +{ + asm volatile("pause" ::: "memory"); +} +#else +static inline void cpu_pause(void) +{ +} +#endif + // no-op: Atomics.pause() is not allowed to block or yield to another // thread, only to hint the CPU that it should back off for a bit; // the amount of work we do here is a good enough substitute @@ -56977,7 +58068,7 @@ static JSValue js_atomics_pause(JSContext *ctx, JSValueConst this_obj, double d; if (argc > 0) { - switch (JS_VALUE_GET_TAG(argv[0])) { + switch (JS_VALUE_GET_NORM_TAG(argv[0])) { case JS_TAG_FLOAT64: // accepted if and only if fraction == 0.0 d = JS_VALUE_GET_FLOAT64(argv[0]); if (isfinite(d)) @@ -56991,6 +58082,7 @@ static JSValue js_atomics_pause(JSContext *ctx, JSValueConst this_obj, break; } } + cpu_pause(); return JS_UNDEFINED; } @@ -57002,13 +58094,13 @@ static JSValue js_atomics_wait(JSContext *ctx, int32_t v32; void *ptr; int64_t timeout; + struct timespec ts; JSAtomicsWaiter waiter_s, *waiter; int ret, size_log2, res; double d; - ptr = js_atomics_get_ptr(ctx, NULL, &size_log2, NULL, - argv[0], argv[1], 2); - if (!ptr) + if (js_atomics_get_ptr(ctx, &ptr, NULL, &size_log2, NULL, + argv[0], argv[1], 2)) return JS_EXCEPTION; if (size_log2 == 3) { if (JS_ToBigInt64(ctx, &v, argv[2])) @@ -57020,6 +58112,7 @@ static JSValue js_atomics_wait(JSContext *ctx, } if (JS_ToFloat64(ctx, &d, argv[3])) return JS_EXCEPTION; + /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */ if (isnan(d) || d >= 0x1p63) timeout = INT64_MAX; else if (d < 0) @@ -57031,34 +58124,44 @@ static JSValue js_atomics_wait(JSContext *ctx, /* XXX: inefficient if large number of waiters, should hash on 'ptr' value */ - js_mutex_lock(&js_atomics_mutex); + /* XXX: use Linux futexes when available ? */ + pthread_mutex_lock(&js_atomics_mutex); if (size_log2 == 3) { res = *(int64_t *)ptr != v; } else { res = *(int32_t *)ptr != v; } if (res) { - js_mutex_unlock(&js_atomics_mutex); + pthread_mutex_unlock(&js_atomics_mutex); return JS_AtomToString(ctx, JS_ATOM_not_equal); } waiter = &waiter_s; waiter->ptr = ptr; - js_cond_init(&waiter->cond); - waiter->linked = true; + pthread_cond_init(&waiter->cond, NULL); + waiter->linked = TRUE; list_add_tail(&waiter->link, &js_atomics_waiter_list); if (timeout == INT64_MAX) { - js_cond_wait(&waiter->cond, &js_atomics_mutex); + pthread_cond_wait(&waiter->cond, &js_atomics_mutex); ret = 0; } else { - ret = js_cond_timedwait(&waiter->cond, &js_atomics_mutex, timeout * 1e6 /* to ns */); + /* XXX: use clock monotonic */ + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeout / 1000; + ts.tv_nsec += (timeout % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + ret = pthread_cond_timedwait(&waiter->cond, &js_atomics_mutex, + &ts); } if (waiter->linked) list_del(&waiter->link); - js_mutex_unlock(&js_atomics_mutex); - js_cond_destroy(&waiter->cond); - if (ret == -1) { + pthread_mutex_unlock(&js_atomics_mutex); + pthread_cond_destroy(&waiter->cond); + if (ret == ETIMEDOUT) { return JS_AtomToString(ctx, JS_ATOM_timed_out); } else { return JS_AtomToString(ctx, JS_ATOM_ok); @@ -57075,28 +58178,25 @@ static JSValue js_atomics_notify(JSContext *ctx, JSAtomicsWaiter *waiter; JSArrayBuffer *abuf; - ptr = js_atomics_get_ptr(ctx, &abuf, NULL, NULL, argv[0], argv[1], 1); - if (!ptr) + if (js_atomics_get_ptr(ctx, &ptr, &abuf, NULL, NULL, argv[0], argv[1], 1)) return JS_EXCEPTION; - + if (JS_IsUndefined(argv[2])) { count = INT32_MAX; } else { if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0)) return JS_EXCEPTION; } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); n = 0; if (abuf->shared && count > 0) { - js_mutex_lock(&js_atomics_mutex); + pthread_mutex_lock(&js_atomics_mutex); init_list_head(&waiter_list); list_for_each_safe(el, el1, &js_atomics_waiter_list) { waiter = list_entry(el, JSAtomicsWaiter, link); if (waiter->ptr == ptr) { list_del(&waiter->link); - waiter->linked = false; + waiter->linked = FALSE; list_add_tail(&waiter->link, &waiter_list); n++; if (n >= count) @@ -57105,11 +58205,11 @@ static JSValue js_atomics_notify(JSContext *ctx, } list_for_each(el, &waiter_list) { waiter = list_entry(el, JSAtomicsWaiter, link); - js_cond_signal(&waiter->cond); + pthread_cond_signal(&waiter->cond); } - js_mutex_unlock(&js_atomics_mutex); + pthread_mutex_unlock(&js_atomics_mutex); } - return js_int32(n); + return JS_NewInt32(ctx, n); } static const JSCFunctionListEntry js_atomics_funcs[] = { @@ -57133,226 +58233,158 @@ static const JSCFunctionListEntry js_atomics_obj[] = { JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; -static void js__atomics_init(void) { - js_mutex_init(&js_atomics_mutex); -} - -/* TODO(saghul) make this public and not dependent on typed arrays? */ -void JS_AddIntrinsicAtomics(JSContext *ctx) +static int JS_AddIntrinsicAtomics(JSContext *ctx) { - js_once(&js_atomics_once, js__atomics_init); - /* add Atomics as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); } #endif /* CONFIG_ATOMICS */ -void JS_AddIntrinsicTypedArrays(JSContext *ctx) +int JS_AddIntrinsicTypedArrays(JSContext *ctx) { - JSValue typed_array_base_proto, typed_array_base_func; - JSValue array_buffer_func, shared_array_buffer_func; - int i; + JSValue typed_array_base_func, typed_array_base_proto, obj; + int i, ret; + + obj = JS_NewCConstructor(ctx, JS_CLASS_ARRAY_BUFFER, "ArrayBuffer", + js_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_array_buffer_funcs, countof(js_array_buffer_funcs), + js_array_buffer_proto_funcs, countof(js_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); - ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_BUFFER], - js_array_buffer_proto_funcs, - countof(js_array_buffer_proto_funcs)); - - array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "ArrayBuffer", - js_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, array_buffer_func, - js_array_buffer_funcs, - countof(js_array_buffer_funcs)); - - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER], - js_shared_array_buffer_proto_funcs, - countof(js_shared_array_buffer_proto_funcs)); - - shared_array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "SharedArrayBuffer", - js_shared_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, shared_array_buffer_func, - js_shared_array_buffer_funcs, - countof(js_shared_array_buffer_funcs)); - - typed_array_base_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, typed_array_base_proto, - js_typed_array_base_proto_funcs, - countof(js_typed_array_base_proto_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_SHARED_ARRAY_BUFFER, "SharedArrayBuffer", + js_shared_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_shared_array_buffer_funcs, countof(js_shared_array_buffer_funcs), + js_shared_array_buffer_proto_funcs, countof(js_shared_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); - /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ - JSValue obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); - /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ - JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - typed_array_base_func = JS_NewCFunction(ctx, js_typed_array_base_constructor, - "TypedArray", 0); - JS_SetPropertyFunctionList(ctx, typed_array_base_func, - js_typed_array_base_funcs, - countof(js_typed_array_base_funcs)); - JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto); - JS_SetConstructorBit(ctx, typed_array_base_func, true); + typed_array_base_func = + JS_NewCConstructor(ctx, -1, "TypedArray", + js_typed_array_base_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_typed_array_base_funcs, countof(js_typed_array_base_funcs), + js_typed_array_base_proto_funcs, countof(js_typed_array_base_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL); + if (JS_IsException(typed_array_base_func)) + return -1; + /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ + obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); + if (JS_IsException(obj)) + goto fail; + /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ + typed_array_base_proto = JS_GetProperty(ctx, typed_array_base_func, JS_ATOM_prototype); + if (JS_IsException(typed_array_base_proto)) + goto fail; + ret = JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_FreeValue(ctx, typed_array_base_proto); + if (ret < 0) + goto fail; + /* Used to squelch a -Wcast-function-type warning. */ JSCFunctionType ft = { .generic_magic = js_typed_array_constructor }; for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) { - JSValue func_obj; char buf[ATOM_GET_STR_BUF_SIZE]; const char *name; - - ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto); - JS_DefinePropertyValueStr(ctx, ctx->class_proto[i], - "BYTES_PER_ELEMENT", - js_int32(1 << typed_array_size_log2(i)), - 0); + const JSCFunctionListEntry *bpe; + name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY); - func_obj = JS_NewCFunction3(ctx, ft.generic, - name, 3, JS_CFUNC_constructor_magic, i, - typed_array_base_func); - JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]); - JS_DefinePropertyValueStr(ctx, func_obj, - "BYTES_PER_ELEMENT", - js_int32(1 << typed_array_size_log2(i)), - 0); + bpe = js_typed_array_funcs + typed_array_size_log2(i); + obj = JS_NewCConstructor(ctx, i, name, + ft.generic, 3, JS_CFUNC_constructor_magic, i, + typed_array_base_func, + bpe, 1, + bpe, 1, + 0); + if (JS_IsException(obj)) { + fail: + JS_FreeValue(ctx, typed_array_base_func); + return -1; + } + JS_FreeValue(ctx, obj); } - JS_FreeValue(ctx, typed_array_base_proto); JS_FreeValue(ctx, typed_array_base_func); /* DataView */ - ctx->class_proto[JS_CLASS_DATAVIEW] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATAVIEW], - js_dataview_proto_funcs, - countof(js_dataview_proto_funcs)); - JS_NewGlobalCConstructorOnly(ctx, "DataView", - js_dataview_constructor, 1, - ctx->class_proto[JS_CLASS_DATAVIEW]); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATAVIEW, "DataView", + js_dataview_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + NULL, 0, + js_dataview_proto_funcs, countof(js_dataview_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + /* Atomics */ #ifdef CONFIG_ATOMICS - JS_AddIntrinsicAtomics(ctx); -#endif -} - -/* Performance */ - -static double js__now_ms(void) -{ - return js__hrtime_ns() / 1e6; -} - -static JSValue js_perf_now(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - return js_float64(js__now_ms() - ctx->time_origin); -} - -static const JSCFunctionListEntry js_perf_proto_funcs[] = { - JS_CFUNC_DEF2("now", 0, js_perf_now, JS_PROP_ENUMERABLE), -}; - -void JS_AddPerformance(JSContext *ctx) -{ - ctx->time_origin = js__now_ms(); - - JSValue performance = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, performance, js_perf_proto_funcs, countof(js_perf_proto_funcs)); - JS_DefinePropertyValueStr(ctx, performance, "timeOrigin", - js_float64(ctx->time_origin), - JS_PROP_ENUMERABLE); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "performance", - js_dup(performance), - JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE); - JS_FreeValue(ctx, performance); -} - -/* Equality comparisons and sameness */ -int JS_IsEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2) -{ - JSValue sp[2] = { js_dup(op1), js_dup(op2) }; - if (js_eq_slow(ctx, endof(sp), 0)) + if (JS_AddIntrinsicAtomics(ctx)) return -1; - return JS_VALUE_GET_BOOL(sp[0]); -} - -bool JS_IsStrictEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2) -{ - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_STRICT); -} - -bool JS_IsSameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2) -{ - return js_same_value(ctx, op1, op2); -} - -bool JS_IsSameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2) -{ - return js_same_value_zero(ctx, op1, op2); +#endif + return 0; } /* WeakRef */ typedef struct JSWeakRefData { - JSValueConst target; - JSValue obj; + JSWeakRefHeader weakref_header; + JSValue target; } JSWeakRefData; -static JSWeakRefData js_weakref_sentinel; - -static void js_weakref_finalizer(JSRuntime *rt, JSValueConst val) +static void js_weakref_finalizer(JSRuntime *rt, JSValue val) { JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF); - if (!wrd || wrd == &js_weakref_sentinel) + if (!wrd) return; + js_weakref_free(rt, wrd->target); + list_del(&wrd->weakref_header.link); + js_free_rt(rt, wrd); +} - /* Delete weak ref */ - JSWeakRefRecord **pwr, *wr; +static void weakref_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh) +{ + JSWeakRefData *wrd = container_of(wh, JSWeakRefData, weakref_header); - pwr = get_first_weak_ref(wrd->target); - for(;;) { - wr = *pwr; - assert(wr != NULL); - if (wr->kind == JS_WEAK_REF_KIND_WEAK_REF && wr->u.weak_ref_data == wrd) - break; - pwr = &wr->next_weak_ref; + if (!js_weakref_is_live(wrd->target)) { + js_weakref_free(rt, wrd->target); + wrd->target = JS_UNDEFINED; } - *pwr = wr->next_weak_ref; - js_free_rt(rt, wrd); - js_free_rt(rt, wr); } static JSValue js_weakref_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { + JSValueConst arg; + JSValue obj; + if (JS_IsUndefined(new_target)) return JS_ThrowTypeError(ctx, "constructor requires 'new'"); - JSValueConst arg = argv[0]; - if (!is_valid_weakref_target(arg)) + arg = argv[0]; + if (!js_weakref_is_target(arg)) return JS_ThrowTypeError(ctx, "invalid target"); - // TODO(saghul): short-circuit if the refcount is 1? - JSValue obj = js_create_from_ctor(ctx, new_target, JS_CLASS_WEAK_REF); + obj = js_create_from_ctor(ctx, new_target, JS_CLASS_WEAK_REF); if (JS_IsException(obj)) return JS_EXCEPTION; - JSWeakRefData *wrd = js_malloc(ctx, sizeof(*wrd)); + JSWeakRefData *wrd = js_mallocz(ctx, sizeof(*wrd)); if (!wrd) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr)); - if (!wr) { - JS_FreeValue(ctx, obj); - js_free(ctx, wrd); - return JS_EXCEPTION; - } - wrd->target = arg; - wrd->obj = obj; - wr->kind = JS_WEAK_REF_KIND_WEAK_REF; - wr->u.weak_ref_data = wrd; - insert_weakref_record(arg, wr); - - JS_SetOpaqueInternal(obj, wrd); + wrd->target = js_weakref_new(ctx, arg); + wrd->weakref_header.weakref_type = JS_WEAKREF_TYPE_WEAKREF; + list_add_tail(&wrd->weakref_header.link, &ctx->rt->weakref_list); + JS_SetOpaque(obj, wrd); return obj; } @@ -57361,9 +58393,10 @@ static JSValue js_weakref_deref(JSContext *ctx, JSValueConst this_val, int argc, JSWeakRefData *wrd = JS_GetOpaque2(ctx, this_val, JS_CLASS_WEAK_REF); if (!wrd) return JS_EXCEPTION; - if (wrd == &js_weakref_sentinel) + if (js_weakref_is_live(wrd->target)) + return JS_DupValue(ctx, wrd->target); + else return JS_UNDEFINED; - return js_dup(wrd->target); } static const JSCFunctionListEntry js_weakref_proto_funcs[] = { @@ -57377,54 +58410,33 @@ static const JSClassShortDef js_weakref_class_def[] = { typedef struct JSFinRecEntry { struct list_head link; - JSValueConst obj; - JSValueConst target; + JSValue target; JSValue held_val; JSValue token; } JSFinRecEntry; typedef struct JSFinalizationRegistryData { - struct list_head entries; - JSContext *ctx; + JSWeakRefHeader weakref_header; + struct list_head entries; /* list of JSFinRecEntry.link */ + JSContext *realm; JSValue cb; } JSFinalizationRegistryData; -static void delete_finrec_weakref(JSRuntime *rt, JSFinRecEntry *fre) -{ - JSWeakRefRecord **pwr, *wr; - - pwr = get_first_weak_ref(fre->target); - for(;;) { - wr = *pwr; - assert(wr != NULL); - if (wr->kind == JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY && wr->u.fin_rec_entry == fre) - break; - pwr = &wr->next_weak_ref; - } - *pwr = wr->next_weak_ref; - js_free_rt(rt, wr); -} - -static void js_finrec_finalizer(JSRuntime *rt, JSValueConst val) +static void js_finrec_finalizer(JSRuntime *rt, JSValue val) { JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY); if (frd) { struct list_head *el, *el1; - /* first pass to remove the weak ref entries and avoid having them modified - by freeing a token / held value. */ list_for_each_safe(el, el1, &frd->entries) { JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); - delete_finrec_weakref(rt, fre); - } - /* second pass to actually free all objects. */ - list_for_each_safe(el, el1, &frd->entries) { - JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); - list_del(&fre->link); + js_weakref_free(rt, fre->target); + js_weakref_free(rt, fre->token); JS_FreeValueRT(rt, fre->held_val); - JS_FreeValueRT(rt, fre->token); js_free_rt(rt, fre); } JS_FreeValueRT(rt, frd->cb); + JS_FreeContext(frd->realm); + list_del(&frd->weakref_header.link); js_free_rt(rt, frd); } } @@ -57433,13 +58445,46 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY); + struct list_head *el; if (frd) { - JS_MarkValue(rt, frd->cb, mark_func); - struct list_head *el; list_for_each(el, &frd->entries) { JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); JS_MarkValue(rt, fre->held_val, mark_func); - JS_MarkValue(rt, fre->token, mark_func); + } + JS_MarkValue(rt, frd->cb, mark_func); + mark_func(rt, &frd->realm->header); + } +} + +static JSValue js_finrec_job(JSContext *ctx, int argc, JSValueConst *argv) +{ + return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); +} + +static void finrec_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh) +{ + JSFinalizationRegistryData *frd = container_of(wh, JSFinalizationRegistryData, weakref_header); + struct list_head *el, *el1; + + list_for_each_safe(el, el1, &frd->entries) { + JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); + + if (!js_weakref_is_live(fre->token)) { + js_weakref_free(rt, fre->token); + fre->token = JS_UNDEFINED; + } + + if (!js_weakref_is_live(fre->target)) { + JSValueConst args[2]; + args[0] = frd->cb; + args[1] = fre->held_val; + JS_EnqueueJob(frd->realm, js_finrec_job, 2, args); + + js_weakref_free(rt, fre->target); + js_weakref_free(rt, fre->token); + JS_FreeValueRT(rt, fre->held_val); + list_del(&fre->link); + js_free_rt(rt, fre); } } } @@ -57447,92 +58492,89 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst val, static JSValue js_finrec_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { + JSValueConst cb; + JSValue obj; + JSFinalizationRegistryData *frd; + if (JS_IsUndefined(new_target)) return JS_ThrowTypeError(ctx, "constructor requires 'new'"); - JSValueConst cb = argv[0]; - if (check_function(ctx, cb)) - return JS_EXCEPTION; - JSValue obj = js_create_from_ctor(ctx, new_target, JS_CLASS_FINALIZATION_REGISTRY); + cb = argv[0]; + if (!JS_IsFunction(ctx, cb)) + return JS_ThrowTypeError(ctx, "argument must be a function"); + + obj = js_create_from_ctor(ctx, new_target, JS_CLASS_FINALIZATION_REGISTRY); if (JS_IsException(obj)) return JS_EXCEPTION; - JSFinalizationRegistryData *frd = js_malloc(ctx, sizeof(*frd)); + frd = js_mallocz(ctx, sizeof(*frd)); if (!frd) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } + frd->weakref_header.weakref_type = JS_WEAKREF_TYPE_FINREC; + list_add_tail(&frd->weakref_header.link, &ctx->rt->weakref_list); init_list_head(&frd->entries); - frd->ctx = ctx; - frd->cb = js_dup(cb); - JS_SetOpaqueInternal(obj, frd); + frd->realm = JS_DupContext(ctx); + frd->cb = JS_DupValue(ctx, cb); + JS_SetOpaque(obj, frd); return obj; } static JSValue js_finrec_register(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY); + JSValueConst target, held_val, token; + JSFinalizationRegistryData *frd; + JSFinRecEntry *fre; + + frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY); if (!frd) return JS_EXCEPTION; + target = argv[0]; + held_val = argv[1]; + token = argc > 2 ? argv[2] : JS_UNDEFINED; - JSValueConst target = argv[0]; - JSValueConst held_val = argv[1]; - // The function length needs to return 2, so the 3rd argument won't be initialized. - JSValueConst token = argc > 2 ? argv[2] : JS_UNDEFINED; - - if (!is_valid_weakref_target(target)) + if (!js_weakref_is_target(target)) return JS_ThrowTypeError(ctx, "invalid target"); - if (js_same_value(ctx, target, this_val)) - return JS_UNDEFINED; - if (!JS_IsUndefined(held_val) && js_same_value(ctx, target, held_val)) + if (js_same_value(ctx, target, held_val)) return JS_ThrowTypeError(ctx, "held value cannot be the target"); - if (!JS_IsUndefined(token) && !is_valid_weakref_target(token)) + if (!JS_IsUndefined(token) && !js_weakref_is_target(token)) return JS_ThrowTypeError(ctx, "invalid unregister token"); - - JSFinRecEntry *fre = js_malloc(ctx, sizeof(*fre)); + fre = js_malloc(ctx, sizeof(*fre)); if (!fre) return JS_EXCEPTION; - JSWeakRefRecord *wr = js_malloc(ctx, sizeof(*wr)); - if (!wr) { - js_free(ctx, fre); - return JS_EXCEPTION; - } - fre->obj = this_val; - fre->target = target; - fre->held_val = js_dup(held_val); - fre->token = js_dup(token); + fre->target = js_weakref_new(ctx, target); + fre->held_val = JS_DupValue(ctx, held_val); + fre->token = js_weakref_new(ctx, token); list_add_tail(&fre->link, &frd->entries); - wr->kind = JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY; - wr->u.fin_rec_entry = fre; - insert_weakref_record(target, wr); - return JS_UNDEFINED; } static JSValue js_finrec_unregister(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY); + JSValueConst token; + BOOL removed; + struct list_head *el, *el1; + if (!frd) return JS_EXCEPTION; - - JSValueConst token = argv[0]; - if (!is_valid_weakref_target(token)) + token = argv[0]; + if (!js_weakref_is_target(token)) return JS_ThrowTypeError(ctx, "invalid unregister token"); - struct list_head *el, *el1; - bool removed = false; + removed = FALSE; list_for_each_safe(el, el1, &frd->entries) { JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); - if (js_same_value(ctx, fre->token, token)) { - list_del(&fre->link); - delete_finrec_weakref(ctx->rt, fre); + if (js_weakref_is_live(fre->token) && js_same_value(ctx, fre->token, token)) { + js_weakref_free(ctx->rt, fre->target); + js_weakref_free(ctx->rt, fre->token); JS_FreeValue(ctx, fre->held_val); - JS_FreeValue(ctx, fre->token); + list_del(&fre->link); js_free(ctx, fre); - removed = true; + removed = TRUE; } } - - return js_bool(removed); + return JS_NewBool(ctx, removed); } static const JSCFunctionListEntry js_finrec_proto_funcs[] = { @@ -57545,592 +58587,45 @@ static const JSClassShortDef js_finrec_class_def[] = { { JS_ATOM_FinalizationRegistry, js_finrec_finalizer, js_finrec_mark }, /* JS_CLASS_FINALIZATION_REGISTRY */ }; -static JSValue js_finrec_job(JSContext *ctx, int argc, JSValueConst *argv) -{ - return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); -} - -void JS_AddIntrinsicWeakRef(JSContext *ctx) +int JS_AddIntrinsicWeakRef(JSContext *ctx) { JSRuntime *rt = ctx->rt; - + JSValue obj; + /* WeakRef */ if (!JS_IsRegisteredClass(rt, JS_CLASS_WEAK_REF)) { - init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, - countof(js_weakref_class_def)); + if (init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, + countof(js_weakref_class_def))) + return -1; } - ctx->class_proto[JS_CLASS_WEAK_REF] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_WEAK_REF], - js_weakref_proto_funcs, - countof(js_weakref_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "WeakRef", js_weakref_constructor, 1, ctx->class_proto[JS_CLASS_WEAK_REF]); + obj = JS_NewCConstructor(ctx, JS_CLASS_WEAK_REF, "WeakRef", + js_weakref_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_weakref_proto_funcs, countof(js_weakref_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); /* FinalizationRegistry */ if (!JS_IsRegisteredClass(rt, JS_CLASS_FINALIZATION_REGISTRY)) { - init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, - countof(js_finrec_class_def)); - } - ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY], - js_finrec_proto_funcs, - countof(js_finrec_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "FinalizationRegistry", js_finrec_constructor, 1, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY]); -} - -static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref) -{ - JSWeakRefRecord *wr, *wr_next; - JSWeakRefData *wrd; - JSMapRecord *mr; - JSMapState *s; - JSFinRecEntry *fre; - - /* first pass to remove the records from the WeakMap/WeakSet - lists */ - for(wr = *first_weak_ref; wr != NULL; wr = wr->next_weak_ref) { - switch(wr->kind) { - case JS_WEAK_REF_KIND_MAP: - mr = wr->u.map_record; - s = mr->map; - assert(s->is_weak); - assert(!mr->empty); /* no iterator on WeakMap/WeakSet */ - list_del(&mr->hash_link); - list_del(&mr->link); - s->record_count--; - break; - case JS_WEAK_REF_KIND_WEAK_REF: - wrd = wr->u.weak_ref_data; - wrd->target = JS_UNDEFINED; - break; - case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: - fre = wr->u.fin_rec_entry; - list_del(&fre->link); - break; - default: - abort(); - } - } - - /* second pass to free the values to avoid modifying the weak - reference list while traversing it. */ - for(wr = *first_weak_ref; wr != NULL; wr = wr_next) { - wr_next = wr->next_weak_ref; - switch(wr->kind) { - case JS_WEAK_REF_KIND_MAP: - mr = wr->u.map_record; - JS_FreeValueRT(rt, mr->value); - js_free_rt(rt, mr); - break; - case JS_WEAK_REF_KIND_WEAK_REF: - wrd = wr->u.weak_ref_data; - JS_SetOpaqueInternal(wrd->obj, &js_weakref_sentinel); - js_free_rt(rt, wrd); - break; - case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: { - fre = wr->u.fin_rec_entry; - JSFinalizationRegistryData *frd = JS_GetOpaque(fre->obj, JS_CLASS_FINALIZATION_REGISTRY); - assert(frd != NULL); - /** - * During the GC sweep phase the held object might be collected first. - */ - if (!rt->in_free && (!JS_IsObject(fre->held_val) || JS_IsLiveObject(rt, fre->held_val))) { - JSValueConst args[2]; - args[0] = frd->cb; - args[1] = fre->held_val; - JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args); - } - JS_FreeValueRT(rt, fre->held_val); - JS_FreeValueRT(rt, fre->token); - js_free_rt(rt, fre); - break; - } - default: - abort(); - } - js_free_rt(rt, wr); - } - - *first_weak_ref = NULL; /* fail safe */ -} - -static bool is_valid_weakref_target(JSValueConst val) -{ - switch (JS_VALUE_GET_TAG(val)) { - case JS_TAG_OBJECT: - break; - case JS_TAG_SYMBOL: { - // Per spec: prohibit symbols registered with Symbol.for() - JSAtomStruct *p = JS_VALUE_GET_PTR(val); - if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL) - break; - // fallthru - } - default: - return false; - } - - return true; -} - -static void insert_weakref_record(JSValueConst target, - struct JSWeakRefRecord *wr) -{ - JSWeakRefRecord **pwr = get_first_weak_ref(target); - /* Add the weak reference */ - wr->next_weak_ref = *pwr; - *pwr = wr; -} - -/* CallSite */ - -static void js_callsite_finalizer(JSRuntime *rt, JSValueConst val) -{ - JSCallSiteData *csd = JS_GetOpaque(val, JS_CLASS_CALL_SITE); - if (csd) { - JS_FreeValueRT(rt, csd->filename); - JS_FreeValueRT(rt, csd->func); - JS_FreeValueRT(rt, csd->func_name); - js_free_rt(rt, csd); - } -} - -static void js_callsite_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSCallSiteData *csd = JS_GetOpaque(val, JS_CLASS_CALL_SITE); - if (csd) { - JS_MarkValue(rt, csd->filename, mark_func); - JS_MarkValue(rt, csd->func, mark_func); - JS_MarkValue(rt, csd->func_name, mark_func); - } -} - -static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd) { - JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_CALL_SITE); - if (JS_IsException(obj)) - return JS_EXCEPTION; - - JSCallSiteData *csd1 = js_malloc(ctx, sizeof(*csd)); - if (!csd1) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - - memcpy(csd1, csd, sizeof(*csd)); - - JS_SetOpaqueInternal(obj, csd1); - - return obj; -} - -static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf) -{ - const char *func_name_str; - JSObject *p; - - csd->func = js_dup(sf->cur_func); - /* func_name_str is UTF-8 encoded if needed */ - func_name_str = get_func_name(ctx, sf->cur_func); - if (!func_name_str || func_name_str[0] == '\0') - csd->func_name = JS_NULL; - else - csd->func_name = JS_NewString(ctx, func_name_str); - JS_FreeCString(ctx, func_name_str); - if (JS_IsException(csd->func_name)) - csd->func_name = JS_NULL; - - p = JS_VALUE_GET_OBJ(sf->cur_func); - if (js_class_has_bytecode(p->class_id)) { - JSFunctionBytecode *b = p->u.func.function_bytecode; - int line_num1, col_num1; - line_num1 = find_line_num(ctx, b, - sf->cur_pc - b->byte_code_buf - 1, - &col_num1); - csd->native = false; - csd->line_num = line_num1; - csd->col_num = col_num1; - csd->filename = JS_AtomToString(ctx, b->filename); - if (JS_IsException(csd->filename)) { - csd->filename = JS_NULL; - JS_FreeValue(ctx, JS_GetException(ctx)); // Clear exception. - } - } else { - csd->native = true; - csd->line_num = -1; - csd->col_num = -1; - csd->filename = JS_NULL; - } -} - -static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num) -{ - csd->func = JS_NULL; - csd->func_name = JS_NULL; - csd->native = false; - csd->line_num = line_num; - csd->col_num = col_num; - /* filename is UTF-8 encoded if needed (original argument to __JS_EvalInternal()) */ - csd->filename = JS_NewString(ctx, filename); - if (JS_IsException(csd->filename)) { - csd->filename = JS_NULL; - JS_FreeValue(ctx, JS_GetException(ctx)); // Clear exception. - } -} - -static JSValue js_callsite_getfield(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) -{ - JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); - if (!csd) - return JS_EXCEPTION; - JSValue *field = (void *)((char *)csd + magic); - return js_dup(*field); -} - -static JSValue js_callsite_isnative(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ - JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); - if (!csd) - return JS_EXCEPTION; - return js_bool(csd->native); -} - -static JSValue js_callsite_getnumber(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) -{ - JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); - if (!csd) - return JS_EXCEPTION; - int *field = (void *)((char *)csd + magic); - return js_int32(*field); -} - -static const JSCFunctionListEntry js_callsite_proto_funcs[] = { - JS_CFUNC_DEF("isNative", 0, js_callsite_isnative), - JS_CFUNC_MAGIC_DEF("getFileName", 0, js_callsite_getfield, offsetof(JSCallSiteData, filename)), - JS_CFUNC_MAGIC_DEF("getFunction", 0, js_callsite_getfield, offsetof(JSCallSiteData, func)), - JS_CFUNC_MAGIC_DEF("getFunctionName", 0, js_callsite_getfield, offsetof(JSCallSiteData, func_name)), - JS_CFUNC_MAGIC_DEF("getColumnNumber", 0, js_callsite_getnumber, offsetof(JSCallSiteData, col_num)), - JS_CFUNC_MAGIC_DEF("getLineNumber", 0, js_callsite_getnumber, offsetof(JSCallSiteData, line_num)), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "CallSite", JS_PROP_CONFIGURABLE ), -}; - -static const JSClassShortDef js_callsite_class_def[] = { - { JS_ATOM_CallSite, js_callsite_finalizer, js_callsite_mark }, /* JS_CLASS_CALL_SITE */ -}; - -static void _JS_AddIntrinsicCallSite(JSContext *ctx) -{ - JSRuntime *rt = ctx->rt; - - if (!JS_IsRegisteredClass(rt, JS_CLASS_CALL_SITE)) { - init_class_range(rt, js_callsite_class_def, JS_CLASS_CALL_SITE, - countof(js_callsite_class_def)); - } - ctx->class_proto[JS_CLASS_CALL_SITE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_CALL_SITE], - js_callsite_proto_funcs, - countof(js_callsite_proto_funcs)); -} - -/* DOMException */ -typedef struct JSDOMExceptionData { - JSValue name; - JSValue message; - int code; -} JSDOMExceptionData; - -typedef struct JSDOMExceptionNameDef { - const char * const name; - const char * const code_name; -} JSDOMExceptionNameDef; - -static const JSDOMExceptionNameDef js_dom_exception_names_table[] = { - { "IndexSizeError", "INDEX_SIZE_ERR" }, - { NULL, "DOMSTRING_SIZE_ERR" }, - { "HierarchyRequestError", "HIERARCHY_REQUEST_ERR" }, - { "WrongDocumentError", "WRONG_DOCUMENT_ERR" }, - { "InvalidCharacterError", "INVALID_CHARACTER_ERR" }, - { NULL, "NO_DATA_ALLOWED_ERR" }, - { "NoModificationAllowedError", "NO_MODIFICATION_ALLOWED_ERR" }, - { "NotFoundError", "NOT_FOUND_ERR" }, - { "NotSupportedError", "NOT_SUPPORTED_ERR" }, - { "InUseAttributeError", "INUSE_ATTRIBUTE_ERR" }, - { "InvalidStateError", "INVALID_STATE_ERR" }, - { "SyntaxError", "SYNTAX_ERR" }, - { "InvalidModificationError", "INVALID_MODIFICATION_ERR" }, - { "NamespaceError", "NAMESPACE_ERR" }, - { "InvalidAccessError", "INVALID_ACCESS_ERR" }, - { NULL, "VALIDATION_ERR" }, - { "TypeMismatchError", "TYPE_MISMATCH_ERR" }, - { "SecurityError", "SECURITY_ERR" }, - { "NetworkError", "NETWORK_ERR" }, - { "AbortError", "ABORT_ERR" }, - { "URLMismatchError", "URL_MISMATCH_ERR" }, - { "QuotaExceededError", "QUOTA_EXCEEDED_ERR" }, - { "TimeoutError", "TIMEOUT_ERR" }, - { "InvalidNodeTypeError", "INVALID_NODE_TYPE_ERR" }, - { "DataCloneError", "DATA_CLONE_ERR" } -}; - -static void js_domexception_finalizer(JSRuntime *rt, JSValueConst val) -{ - JSDOMExceptionData *s = JS_GetOpaque(val, JS_CLASS_DOM_EXCEPTION); - if (s) { - JS_FreeValueRT(rt, s->name); - JS_FreeValueRT(rt, s->message); - js_free_rt(rt, s); - } -} - -static void js_domexception_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSDOMExceptionData *s = JS_GetOpaque(val, JS_CLASS_DOM_EXCEPTION); - if (s) { - JS_MarkValue(rt, s->name, mark_func); - JS_MarkValue(rt, s->message, mark_func); + if (init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, + countof(js_finrec_class_def))) + return -1; } -} - -static JSValue js_domexception_constructor0(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv, - int backtrace_flags) -{ - JSDOMExceptionData *s; - JSValue obj, message, name; - obj = js_create_from_ctor(ctx, new_target, JS_CLASS_DOM_EXCEPTION); + obj = JS_NewCConstructor(ctx, JS_CLASS_FINALIZATION_REGISTRY, "FinalizationRegistry", + js_finrec_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_finrec_proto_funcs, countof(js_finrec_proto_funcs), + 0); if (JS_IsException(obj)) - return JS_EXCEPTION; - if (!JS_IsUndefined(argv[0])) - message = JS_ToString(ctx, argv[0]); - else - message = js_empty_string(ctx->rt); - if (JS_IsException(message)) - goto fail1; - if (!JS_IsUndefined(argv[1])) - name = JS_ToString(ctx, argv[1]); - else - name = JS_AtomToString(ctx, JS_ATOM_Error); - if (JS_IsException(name)) - goto fail2; - s = js_malloc(ctx, sizeof(*s)); - if (!s) - goto fail3; - s->name = name; - s->message = message; - s->code = -1; - JS_SetOpaqueInternal(obj, s); - build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, backtrace_flags); - return obj; -fail3: - JS_FreeValue(ctx, name); -fail2: - JS_FreeValue(ctx, message); -fail1: + return -1; JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_domexception_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) -{ - if (JS_IsUndefined(new_target)) - return JS_ThrowTypeError(ctx, "constructor requires 'new'"); - return js_domexception_constructor0(ctx, new_target, argc, argv, - JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); -} - -static JSValue js_domexception_getfield(JSContext *ctx, JSValueConst this_val, - int magic) -{ - JSDOMExceptionData *s; - JSValue *valp; - - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_DOM_EXCEPTION); - if (!s) - return JS_EXCEPTION; - valp = (void *)((char *)s + magic); - return js_dup(*valp); -} - -static JSValue js_domexception_get_code(JSContext *ctx, JSValueConst this_val) -{ - JSDOMExceptionData *s; - const char *name, *it; - int i; - size_t len; - - s = JS_GetOpaque2(ctx, this_val, JS_CLASS_DOM_EXCEPTION); - if (!s) - return JS_EXCEPTION; - if (s->code == -1) { - name = JS_ToCStringLen(ctx, &len, s->name); - if (!name) - return JS_EXCEPTION; - for (i = 0; i < countof(js_dom_exception_names_table); i++) { - it = js_dom_exception_names_table[i].name; - if (it && !strcmp(it, name) && len == strlen(it)) { - s->code = i; - break; - } - } - s->code++; - JS_FreeCString(ctx, name); - } - return js_int32(s->code); -} - -static const JSCFunctionListEntry js_domexception_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("name", js_domexception_getfield, NULL, - offsetof(JSDOMExceptionData, name) ), - JS_CGETSET_MAGIC_DEF("message", js_domexception_getfield, NULL, - offsetof(JSDOMExceptionData, message) ), - JS_CGETSET_DEF("code", js_domexception_get_code, NULL ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DOMException", JS_PROP_CONFIGURABLE ), -}; - -static const JSClassShortDef js_domexception_class_def[] = { - { JS_ATOM_DOMException, js_domexception_finalizer, js_domexception_mark }, /* JS_CLASS_DOM_EXCEPTION */ -}; - -JSValue JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowDOMException(JSContext *ctx, const char *name, JS_PRINTF_FORMAT const char *fmt, ...) -{ - JSValue obj, js_name, js_message; - JSValueConst argv[2]; - va_list ap; - char buf[256]; - - assert(JS_IsRegisteredClass(ctx->rt, JS_CLASS_DOM_EXCEPTION)); - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - js_name = JS_NewString(ctx, name); - if (JS_IsException(js_name)) - return JS_EXCEPTION; - js_message = JS_NewString(ctx, buf); - if (JS_IsException(js_message)) { - JS_FreeValue(ctx, js_name); - return JS_EXCEPTION; - } - argv[0] = js_message; - argv[1] = js_name; - obj = js_domexception_constructor0(ctx, JS_UNDEFINED, 2, argv, 0); - JS_FreeValue(ctx, js_message); - JS_FreeValue(ctx, js_name); - if (JS_IsException(obj)) - return JS_EXCEPTION; - return JS_Throw(ctx, obj); -} - -void JS_AddIntrinsicDOMException(JSContext *ctx) -{ - JSRuntime *rt = ctx->rt; - int i; - JSAtom name; - JSValue ctor, proto; - - if (!JS_IsRegisteredClass(rt, JS_CLASS_DOM_EXCEPTION)) { - init_class_range(rt, js_domexception_class_def, JS_CLASS_DOM_EXCEPTION, - countof(js_domexception_class_def)); - } - proto = JS_NewObjectClass(ctx, JS_CLASS_ERROR); - JS_SetPropertyFunctionList(ctx, proto, - js_domexception_proto_funcs, - countof(js_domexception_proto_funcs)); - ctor = JS_NewCFunction2(ctx, js_domexception_constructor, "DOMException", 2, - JS_CFUNC_constructor_or_func, 0); - JS_SetConstructor(ctx, ctor, proto); - for (i = 0; i < countof(js_dom_exception_names_table); i++) { - name = JS_NewAtom(ctx, js_dom_exception_names_table[i].code_name); - JS_DefinePropertyValue(ctx, proto, name, js_int32(i + 1), - JS_PROP_ENUMERABLE); - JS_DefinePropertyValue(ctx, ctor, name, js_int32(i + 1), - JS_PROP_ENUMERABLE); - JS_FreeAtom(ctx, name); - } - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_DOMException, ctor, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - ctx->class_proto[JS_CLASS_DOM_EXCEPTION] = proto; -} - -bool JS_DetectModule(const char *input, size_t input_len) -{ -#ifndef QJS_DISABLE_PARSER - JSRuntime *rt; - JSContext *ctx; - JSValue val; - bool is_module; - - is_module = true; - rt = JS_NewRuntime(); - if (!rt) - return false; - ctx = JS_NewContextRaw(rt); - if (!ctx) { - JS_FreeRuntime(rt); - return false; - } - JS_AddIntrinsicRegExpCompiler(ctx); // otherwise regexp literals don't parse - val = __JS_EvalInternal(ctx, JS_UNDEFINED, input, input_len, "", 1, - JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY, -1); - if (JS_IsException(val)) { - const char *msg = JS_ToCString(ctx, rt->current_exception); - // gruesome hack to recognize exceptions from import statements; - // necessary because we don't pass in a module loader - is_module = !!strstr(msg, "ReferenceError: could not load module"); - JS_FreeCString(ctx, msg); - } - JS_FreeValue(ctx, val); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return is_module; -#else - return false; -#endif // QJS_DISABLE_PARSER -} - -uintptr_t js_std_cmd(int cmd, ...) { - JSContext *ctx; - JSRuntime *rt; - JSValue *pv; - uintptr_t rv; - va_list ap; - - rv = 0; - va_start(ap, cmd); - switch (cmd) { - case 0: // GetOpaque - rt = va_arg(ap, JSRuntime *); - rv = (uintptr_t)rt->libc_opaque; - break; - case 1: // SetOpaque - rt = va_arg(ap, JSRuntime *); - rt->libc_opaque = va_arg(ap, void *); - break; - case 2: // ErrorBackTrace - ctx = va_arg(ap, JSContext *); - pv = va_arg(ap, JSValue *); - *pv = ctx->error_back_trace; - ctx->error_back_trace = JS_UNDEFINED; - break; - case 3: // GetStringKind - ctx = va_arg(ap, JSContext *); - pv = va_arg(ap, JSValue *); - rv = -1; - if (JS_IsString(*pv)) - rv = JS_VALUE_GET_STRING(*pv)->kind; - break; - default: - rv = -1; - } - va_end(ap); - - return rv; + return 0; } -#undef malloc -#undef free -#undef realloc - #include #include diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h new file mode 100644 index 0000000..b3a80e8 --- /dev/null +++ b/quickjs/quickjs.h @@ -0,0 +1,1210 @@ +/* + * QuickJS Javascript Engine + * + * Copyright (c) 2017-2021 Fabrice Bellard + * Copyright (c) 2017-2021 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QUICKJS_H +#define QUICKJS_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define js_likely(x) __builtin_expect(!!(x), 1) +#define js_unlikely(x) __builtin_expect(!!(x), 0) +#define js_force_inline inline __attribute__((always_inline)) +#define __js_printf_like(f, a) __attribute__((format(printf, f, a))) +#else +#define js_likely(x) (x) +#define js_unlikely(x) (x) +#define js_force_inline inline +#define __js_printf_like(a, b) +#endif + +#define JS_BOOL int + +typedef struct JSRuntime JSRuntime; +typedef struct JSContext JSContext; +typedef struct JSClass JSClass; +typedef uint32_t JSClassID; +typedef uint32_t JSAtom; + +#if INTPTR_MAX >= INT64_MAX +#define JS_PTR64 +#define JS_PTR64_DEF(a) a +#else +#define JS_PTR64_DEF(a) +#endif + +#ifndef JS_PTR64 +#define JS_NAN_BOXING +#endif + +#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX) +#define JS_LIMB_BITS 64 +#else +#define JS_LIMB_BITS 32 +#endif + +#define JS_SHORT_BIG_INT_BITS JS_LIMB_BITS + +enum { + /* all tags with a reference count are negative */ + JS_TAG_FIRST = -9, /* first negative tag */ + JS_TAG_BIG_INT = -9, + JS_TAG_SYMBOL = -8, + JS_TAG_STRING = -7, + JS_TAG_STRING_ROPE = -6, + JS_TAG_MODULE = -3, /* used internally */ + JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ + JS_TAG_OBJECT = -1, + + JS_TAG_INT = 0, + JS_TAG_BOOL = 1, + JS_TAG_NULL = 2, + JS_TAG_UNDEFINED = 3, + JS_TAG_UNINITIALIZED = 4, + JS_TAG_CATCH_OFFSET = 5, + JS_TAG_EXCEPTION = 6, + JS_TAG_SHORT_BIG_INT = 7, + JS_TAG_FLOAT64 = 8, + /* any larger tag is FLOAT64 if JS_NAN_BOXING */ +}; + +typedef struct JSRefCountHeader { + int ref_count; +} JSRefCountHeader; + +#define JS_FLOAT64_NAN NAN + +#ifdef CONFIG_CHECK_JSVALUE +/* JSValue consistency : it is not possible to run the code in this + mode, but it is useful to detect simple reference counting + errors. It would be interesting to modify a static C analyzer to + handle specific annotations (clang has such annotations but only + for objective C) */ +typedef struct __JSValue *JSValue; +typedef const struct __JSValue *JSValueConst; +#define JS_VALUE_CONST_CAST(cVal) (JSValue)cVal +#define JS_VALUE_MAKE_CONST(val) (JSValueConst)val + +#define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf) +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) +#define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4) +#define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v) +#define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v) +#define JS_VALUE_GET_SHORT_BIG_INT(v) JS_VALUE_GET_INT(v) +#define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf) + +#define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag)) +#define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag)) + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) + +#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1) + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + return JS_MKVAL(JS_TAG_FLOAT64, (int)d); +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + return 0; +} + +static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) +{ + return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); +} + +#elif defined(JS_NAN_BOXING) + +typedef uint64_t JSValue; + +#define JSValueConst JSValue +#define JS_VALUE_CONST_CAST(cVal) cVal +#define JS_VALUE_MAKE_CONST(val) val + +#define JS_VALUE_GET_TAG(v) (int)((v) >> 32) +#define JS_VALUE_GET_INT(v) (int)(v) +#define JS_VALUE_GET_BOOL(v) (int)(v) +#define JS_VALUE_GET_SHORT_BIG_INT(v) (int)(v) +#define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v) + +#define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val)) +#define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr)) + +#define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */ + +static inline double JS_VALUE_GET_FLOAT64(JSValue v) +{ + union { + JSValue v; + double d; + } u; + u.v = v; + u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32; + return u.d; +} + +#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + union { + double d; + uint64_t u64; + } u; + JSValue v; + u.d = d; + /* normalize NaN */ + if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) + v = JS_NAN; + else + v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); + return v; +} + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) + +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +static inline int JS_VALUE_GET_NORM_TAG(JSValue v) +{ + uint32_t tag; + tag = JS_VALUE_GET_TAG(v); + if (JS_TAG_IS_FLOAT64(tag)) + return JS_TAG_FLOAT64; + else + return tag; +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + uint32_t tag; + tag = JS_VALUE_GET_TAG(v); + return tag == (JS_NAN >> 32); +} + +static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) +{ + return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); +} + +#else /* !JS_NAN_BOXING */ + +typedef union JSValueUnion { + int32_t int32; + double float64; + void *ptr; +#if JS_SHORT_BIG_INT_BITS == 32 + int32_t short_big_int; +#else + int64_t short_big_int; +#endif +} JSValueUnion; + +typedef struct JSValue { + JSValueUnion u; + int64_t tag; +} JSValue; + +#define JSValueConst JSValue +#define JS_VALUE_CONST_CAST(cVal) cVal +#define JS_VALUE_MAKE_CONST(val) val + +#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) +/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ +#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) +#define JS_VALUE_GET_INT(v) ((v).u.int32) +#define JS_VALUE_GET_BOOL(v) ((v).u.int32) +#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) +#define JS_VALUE_GET_SHORT_BIG_INT(v) ((v).u.short_big_int) +#define JS_VALUE_GET_PTR(v) ((v).u.ptr) + +#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } +#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } + +#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) + +#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } + +/* msvc doesn't understand designated initializers without /std:c++20 */ +#ifdef __cplusplus +#undef JS_MKVAL +#undef JS_MKPTR +#undef JS_NAN +static inline JSValue JS_MKPTR(int64_t tag, void *ptr) +{ + JSValue v; + v.u.ptr = ptr; + v.tag = tag; + return v; +} +static inline JSValue JS_MKVAL(int64_t tag, int32_t int32) +{ + JSValue v; + v.u.int32 = int32; + v.tag = tag; + return v; +} +static inline JSValue JS_MKNAN(void) +{ + JSValue v; + v.u.float64 = NAN; + v.tag = JS_TAG_FLOAT64; + return v; +} +/* provide as macros for consistency and backward compat reasons */ +#define JS_MKPTR(tag, ptr) JS_MKPTR(tag, ptr) +#define JS_MKVAL(tag, val) JS_MKVAL(tag, val) +#define JS_NAN JS_MKNAN() /* alas, not a constant expression */ +#endif + +static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +{ + JSValue v; + v.tag = JS_TAG_FLOAT64; + v.u.float64 = d; + return v; +} + +static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +{ + union { + double d; + uint64_t u64; + } u; + if (v.tag != JS_TAG_FLOAT64) + return 0; + u.d = v.u.float64; + return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000; +} + +static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int64_t d) +{ + JSValue v; + v.tag = JS_TAG_SHORT_BIG_INT; + v.u.short_big_int = d; + return v; +} + +#endif /* !JS_NAN_BOXING */ + +#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) +#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) + +#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) + +/* special values */ +#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0) +#define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0) +#define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0) +#define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1) +#define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) +#define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) + +/* flags for object properties */ +#define JS_PROP_CONFIGURABLE (1 << 0) +#define JS_PROP_WRITABLE (1 << 1) +#define JS_PROP_ENUMERABLE (1 << 2) +#define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) +#define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */ +#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ +#define JS_PROP_NORMAL (0 << 4) +#define JS_PROP_GETSET (1 << 4) +#define JS_PROP_VARREF (2 << 4) /* used internally */ +#define JS_PROP_AUTOINIT (3 << 4) /* used internally */ + +/* flags for JS_DefineProperty */ +#define JS_PROP_HAS_SHIFT 8 +#define JS_PROP_HAS_CONFIGURABLE (1 << 8) +#define JS_PROP_HAS_WRITABLE (1 << 9) +#define JS_PROP_HAS_ENUMERABLE (1 << 10) +#define JS_PROP_HAS_GET (1 << 11) +#define JS_PROP_HAS_SET (1 << 12) +#define JS_PROP_HAS_VALUE (1 << 13) + +/* throw an exception if false would be returned + (JS_DefineProperty/JS_SetProperty) */ +#define JS_PROP_THROW (1 << 14) +/* throw an exception if false would be returned in strict mode + (JS_SetProperty) */ +#define JS_PROP_THROW_STRICT (1 << 15) + +#define JS_PROP_NO_EXOTIC (1 << 16) /* internal use */ + +#ifndef JS_DEFAULT_STACK_SIZE +#define JS_DEFAULT_STACK_SIZE (1024 * 1024) +#endif + +/* JS_Eval() flags */ +#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */ +#define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */ +#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */ +#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ +#define JS_EVAL_TYPE_MASK (3 << 0) + +#define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ +/* compile but do not run. The result is an object with a + JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed + with JS_EvalFunction(). */ +#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) +/* don't include the stack frames before this eval in the Error() backtraces */ +#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6) +/* allow top-level await in normal script. JS_Eval() returns a + promise. Only allowed with JS_EVAL_TYPE_GLOBAL */ +#define JS_EVAL_FLAG_ASYNC (1 << 7) + +typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); +typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data); + +typedef struct JSMallocState { + size_t malloc_count; + size_t malloc_size; + size_t malloc_limit; + void *opaque; /* user opaque */ +} JSMallocState; + +typedef struct JSMallocFunctions { + void *(*js_malloc)(JSMallocState *s, size_t size); + void (*js_free)(JSMallocState *s, void *ptr); + void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size); + size_t (*js_malloc_usable_size)(const void *ptr); +} JSMallocFunctions; + +typedef struct JSGCObjectHeader JSGCObjectHeader; + +JSRuntime *JS_NewRuntime(void); +/* info lifetime must exceed that of rt */ +void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); +void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); +void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); +/* use 0 to disable maximum stack size check */ +void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); +/* should be called when changing thread to update the stack top value + used to check stack overflow. */ +void JS_UpdateStackTop(JSRuntime *rt); +JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); +void JS_FreeRuntime(JSRuntime *rt); +void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg)); +void *JS_GetRuntimeOpaque(JSRuntime *rt); +void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); +typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp); +void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +void JS_RunGC(JSRuntime *rt); +JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj); + +JSContext *JS_NewContext(JSRuntime *rt); +void JS_FreeContext(JSContext *s); +JSContext *JS_DupContext(JSContext *ctx); +void *JS_GetContextOpaque(JSContext *ctx); +void JS_SetContextOpaque(JSContext *ctx, void *opaque); +JSRuntime *JS_GetRuntime(JSContext *ctx); +void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); +JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); + +/* the following functions are used to select the intrinsic object to + save memory */ +JSContext *JS_NewContextRaw(JSRuntime *rt); +int JS_AddIntrinsicBaseObjects(JSContext *ctx); +int JS_AddIntrinsicDate(JSContext *ctx); +int JS_AddIntrinsicEval(JSContext *ctx); +int JS_AddIntrinsicStringNormalize(JSContext *ctx); +void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); +int JS_AddIntrinsicRegExp(JSContext *ctx); +int JS_AddIntrinsicJSON(JSContext *ctx); +int JS_AddIntrinsicProxy(JSContext *ctx); +int JS_AddIntrinsicMapSet(JSContext *ctx); +int JS_AddIntrinsicTypedArrays(JSContext *ctx); +int JS_AddIntrinsicPromise(JSContext *ctx); +int JS_AddIntrinsicWeakRef(JSContext *ctx); + +JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv); + +void *js_malloc_rt(JSRuntime *rt, size_t size); +void js_free_rt(JSRuntime *rt, void *ptr); +void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); +size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); +void *js_mallocz_rt(JSRuntime *rt, size_t size); + +void *js_malloc(JSContext *ctx, size_t size); +void js_free(JSContext *ctx, void *ptr); +void *js_realloc(JSContext *ctx, void *ptr, size_t size); +size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); +void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); +void *js_mallocz(JSContext *ctx, size_t size); +char *js_strdup(JSContext *ctx, const char *str); +char *js_strndup(JSContext *ctx, const char *s, size_t n); + +typedef struct JSMemoryUsage { + int64_t malloc_size, malloc_limit, memory_used_size; + int64_t malloc_count; + int64_t memory_used_count; + int64_t atom_count, atom_size; + int64_t str_count, str_size; + int64_t obj_count, obj_size; + int64_t prop_count, prop_size; + int64_t shape_count, shape_size; + int64_t js_func_count, js_func_size, js_func_code_size; + int64_t js_func_pc2line_count, js_func_pc2line_size; + int64_t c_func_count, array_count; + int64_t fast_array_count, fast_array_elements; + int64_t binary_object_count, binary_object_size; +} JSMemoryUsage; + +void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); +void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); + +/* atom support */ +#define JS_ATOM_NULL 0 + +JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); +JSAtom JS_NewAtom(JSContext *ctx, const char *str); +JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); +JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); +void JS_FreeAtom(JSContext *ctx, JSAtom v); +void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); +JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); +JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); +const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom); +static inline const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) +{ + return JS_AtomToCStringLen(ctx, NULL, atom); +} +JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); + +/* object class support */ + +typedef struct JSPropertyEnum { + JS_BOOL is_enumerable; + JSAtom atom; +} JSPropertyEnum; + +typedef struct JSPropertyDescriptor { + int flags; + JSValue value; + JSValue getter; + JSValue setter; +} JSPropertyDescriptor; + +typedef struct JSClassExoticMethods { + /* Return -1 if exception (can only happen in case of Proxy object), + FALSE if the property does not exists, TRUE if it exists. If 1 is + returned, the property descriptor 'desc' is filled if != NULL. */ + int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop); + /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, + -1 if exception. The 'is_enumerable' field is ignored. + */ + int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, + JSValueConst obj); + /* return < 0 if exception, or TRUE/FALSE */ + int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); + /* return < 0 if exception or TRUE/FALSE */ + int (*define_own_property)(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValueConst val, + JSValueConst getter, JSValueConst setter, + int flags); + /* The following methods can be emulated with the previous ones, + so they are usually not needed */ + /* return < 0 if exception or TRUE/FALSE */ + int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom); + JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, + JSValueConst receiver); + /* return < 0 if exception or TRUE/FALSE */ + int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, + JSValueConst value, JSValueConst receiver, int flags); + + /* To get a consistent object behavior when get_prototype != NULL, + get_property, set_property and set_prototype must be != NULL + and the object must be created with a JS_NULL prototype. */ + JSValue (*get_prototype)(JSContext *ctx, JSValueConst obj); + /* return < 0 if exception or TRUE/FALSE */ + int (*set_prototype)(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); + /* return < 0 if exception or TRUE/FALSE */ + int (*is_extensible)(JSContext *ctx, JSValueConst obj); + /* return < 0 if exception or TRUE/FALSE */ + int (*prevent_extensions)(JSContext *ctx, JSValueConst obj); +} JSClassExoticMethods; + +typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); +typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func); +#define JS_CALL_FLAG_CONSTRUCTOR (1 << 0) +typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj, + JSValueConst this_val, int argc, JSValueConst *argv, + int flags); + +typedef struct JSClassDef { + const char *class_name; + JSClassFinalizer *finalizer; + JSClassGCMark *gc_mark; + /* if call != NULL, the object is a function. If (flags & + JS_CALL_FLAG_CONSTRUCTOR) != 0, the function is called as a + constructor. In this case, 'this_val' is new.target. A + constructor call only happens if the object constructor bit is + set (see JS_SetConstructorBit()). */ + JSClassCall *call; + /* XXX: suppress this indirection ? It is here only to save memory + because only a few classes need these methods */ + JSClassExoticMethods *exotic; +} JSClassDef; + +#define JS_INVALID_CLASS_ID 0 +JSClassID JS_NewClassID(JSClassID *pclass_id); +/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */ +JSClassID JS_GetClassID(JSValue v); +int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); +int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); + +/* value handling */ + +static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) +{ + return JS_MKVAL(JS_TAG_BOOL, (val != 0)); +} + +static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) +{ + return JS_MKVAL(JS_TAG_INT, val); +} + +static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) +{ + return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); +} + +static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) +{ + JSValue v; + if (val == (int32_t)val) { + v = JS_NewInt32(ctx, val); + } else { + v = __JS_NewFloat64(ctx, val); + } + return v; +} + +static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) +{ + JSValue v; + if (val <= 0x7fffffff) { + v = JS_NewInt32(ctx, val); + } else { + v = __JS_NewFloat64(ctx, val); + } + return v; +} + +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); +JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); + +static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) +{ + int32_t val; + union { + double d; + uint64_t u; + } u, t; + if (d >= INT32_MIN && d <= INT32_MAX) { + u.d = d; + val = (int32_t)d; + t.d = val; + /* -0 cannot be represented as integer, so we compare the bit + representation */ + if (u.u == t.u) + return JS_MKVAL(JS_TAG_INT, val); + } + return __JS_NewFloat64(ctx, d); +} + +static inline JS_BOOL JS_IsNumber(JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); +} + +static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v) +{ + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT; +} + +static inline JS_BOOL JS_IsBool(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; +} + +static inline JS_BOOL JS_IsNull(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; +} + +static inline JS_BOOL JS_IsUndefined(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; +} + +static inline JS_BOOL JS_IsException(JSValueConst v) +{ + return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); +} + +static inline JS_BOOL JS_IsUninitialized(JSValueConst v) +{ + return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); +} + +static inline JS_BOOL JS_IsString(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_STRING || + JS_VALUE_GET_TAG(v) == JS_TAG_STRING_ROPE; +} + +static inline JS_BOOL JS_IsSymbol(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; +} + +static inline JS_BOOL JS_IsObject(JSValueConst v) +{ + return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; +} + +JSValue JS_Throw(JSContext *ctx, JSValue obj); +void JS_SetUncatchableException(JSContext *ctx, JS_BOOL flag); +JSValue JS_GetException(JSContext *ctx); +JS_BOOL JS_HasException(JSContext *ctx); +JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); +JSValue JS_NewError(JSContext *ctx); +JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...); +JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); +JSValue JS_ThrowOutOfMemory(JSContext *ctx); + +void __JS_FreeValue(JSContext *ctx, JSValue v); +static inline void JS_FreeValue(JSContext *ctx, JSValue v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValue(ctx, v); + } + } +} +void __JS_FreeValueRT(JSRuntime *rt, JSValue v); +static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValueRT(rt, v); + } + } +} + +static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return JS_VALUE_CONST_CAST(v); +} + +static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return JS_VALUE_CONST_CAST(v); +} + +JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2); +JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2); +JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2); + +int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ +int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); +static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) +{ + return JS_ToInt32(ctx, (int32_t*)pres, val); +} +int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val); +int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val); +/* return an exception if 'val' is a Number */ +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +/* same as JS_ToInt64() but allow BigInt */ +int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val); + +JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); +static inline JSValue JS_NewString(JSContext *ctx, const char *str) +{ + return JS_NewStringLen(ctx, str, strlen(str)); +} +JSValue JS_NewAtomString(JSContext *ctx, const char *str); +JSValue JS_ToString(JSContext *ctx, JSValueConst val); +JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8); +static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1) +{ + return JS_ToCStringLen2(ctx, plen, val1, 0); +} +static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) +{ + return JS_ToCStringLen2(ctx, NULL, val1, 0); +} +void JS_FreeCString(JSContext *ctx, const char *ptr); + +JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id); +JSValue JS_NewObjectClass(JSContext *ctx, int class_id); +JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto); +JSValue JS_NewObject(JSContext *ctx); + +JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); +JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val); +JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val); + +JSValue JS_NewArray(JSContext *ctx); +int JS_IsArray(JSContext *ctx, JSValueConst val); + +JSValue JS_NewDate(JSContext *ctx, double epoch_ms); + +JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, + JSAtom prop, JSValueConst receiver, + JS_BOOL throw_ref_error); +static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop) +{ + return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0); +} +JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, + const char *prop); +JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx); + +int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, + JSAtom prop, JSValue val, JSValueConst this_obj, + int flags); +static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val) +{ + return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW); +} +int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx, JSValue val); +int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, + int64_t idx, JSValue val); +int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, + const char *prop, JSValue val); +int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); +int JS_IsExtensible(JSContext *ctx, JSValueConst obj); +int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); +int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); +int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); +JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); + +#define JS_GPN_STRING_MASK (1 << 0) +#define JS_GPN_SYMBOL_MASK (1 << 1) +#define JS_GPN_PRIVATE_MASK (1 << 2) +/* only include the enumerable properties */ +#define JS_GPN_ENUM_ONLY (1 << 4) +/* set theJSPropertyEnum.is_enumerable field */ +#define JS_GPN_SET_ENUM (1 << 5) + +int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValueConst obj, int flags); +void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, + uint32_t len); +int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop); + +JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, + int argc, JSValueConst *argv); +JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, + int argc, JSValueConst *argv); +JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, + int argc, JSValueConst *argv); +JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, + JSValueConst new_target, + int argc, JSValueConst *argv); +JS_BOOL JS_DetectModule(const char *input, size_t input_len); +/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ +JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, + const char *filename, int eval_flags); +/* same as JS_Eval() but with an explicit 'this_obj' parameter */ +JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, + const char *input, size_t input_len, + const char *filename, int eval_flags); +JSValue JS_GetGlobalObject(JSContext *ctx); +int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); +int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValueConst val, + JSValueConst getter, JSValueConst setter, int flags); +int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue val, int flags); +int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, + uint32_t idx, JSValue val, int flags); +int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, + const char *prop, JSValue val, int flags); +int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValue getter, JSValue setter, + int flags); +void JS_SetOpaque(JSValue obj, void *opaque); +void *JS_GetOpaque(JSValueConst obj, JSClassID class_id); +void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); +void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id); + +/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ +JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename); +#define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */ +JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename, int flags); +JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, + JSValueConst replacer, JSValueConst space0); + +typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); +JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, + JSFreeArrayBufferDataFunc *free_func, void *opaque, + JS_BOOL is_shared); +JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); +void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); +uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); + +typedef enum JSTypedArrayEnum { + JS_TYPED_ARRAY_UINT8C = 0, + JS_TYPED_ARRAY_INT8, + JS_TYPED_ARRAY_UINT8, + JS_TYPED_ARRAY_INT16, + JS_TYPED_ARRAY_UINT16, + JS_TYPED_ARRAY_INT32, + JS_TYPED_ARRAY_UINT32, + JS_TYPED_ARRAY_BIG_INT64, + JS_TYPED_ARRAY_BIG_UINT64, + JS_TYPED_ARRAY_FLOAT16, + JS_TYPED_ARRAY_FLOAT32, + JS_TYPED_ARRAY_FLOAT64, +} JSTypedArrayEnum; + +JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, + JSTypedArrayEnum array_type); +JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, + size_t *pbyte_offset, + size_t *pbyte_length, + size_t *pbytes_per_element); +typedef struct { + void *(*sab_alloc)(void *opaque, size_t size); + void (*sab_free)(void *opaque, void *ptr); + void (*sab_dup)(void *opaque, void *ptr); + void *sab_opaque; +} JSSharedArrayBufferFunctions; +void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, + const JSSharedArrayBufferFunctions *sf); + +typedef enum JSPromiseStateEnum { + JS_PROMISE_PENDING, + JS_PROMISE_FULFILLED, + JS_PROMISE_REJECTED, +} JSPromiseStateEnum; + +JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); +JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise); +JSValue JS_PromiseResult(JSContext *ctx, JSValue promise); + +/* is_handled = TRUE means that the rejection is handled */ +typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, + JSValueConst reason, + JS_BOOL is_handled, void *opaque); +void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); + +/* return != 0 if the JS code needs to be interrupted */ +typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); +void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); +/* if can_block is TRUE, Atomics.wait() can be used */ +void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); +/* select which debug info is stripped from the compiled code */ +#define JS_STRIP_SOURCE (1 << 0) /* strip source code */ +#define JS_STRIP_DEBUG (1 << 1) /* strip all debug info including source code */ +void JS_SetStripInfo(JSRuntime *rt, int flags); +int JS_GetStripInfo(JSRuntime *rt); + +/* set the [IsHTMLDDA] internal slot */ +void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj); + +typedef struct JSModuleDef JSModuleDef; + +/* return the module specifier (allocated with js_malloc()) or NULL if + exception */ +typedef char *JSModuleNormalizeFunc(JSContext *ctx, + const char *module_base_name, + const char *module_name, void *opaque); +typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, + const char *module_name, void *opaque); +typedef JSModuleDef *JSModuleLoaderFunc2(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes); +/* return -1 if exception, 0 if OK */ +typedef int JSModuleCheckSupportedImportAttributes(JSContext *ctx, void *opaque, + JSValueConst attributes); + +/* module_normalize = NULL is allowed and invokes the default module + filename normalizer */ +void JS_SetModuleLoaderFunc(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc *module_loader, void *opaque); +/* same as JS_SetModuleLoaderFunc but with attributes. if + module_check_attrs = NULL, no attribute checking is done. */ +void JS_SetModuleLoaderFunc2(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc2 *module_loader, + JSModuleCheckSupportedImportAttributes *module_check_attrs, + void *opaque); +/* return the import.meta object of a module */ +JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); +JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); +JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m); + +/* JS Job support */ + +typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); +int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); + +JS_BOOL JS_IsJobPending(JSRuntime *rt); +int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); + +/* Object Writer/Reader (currently only used to handle precompiled code) */ +#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */ +#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */ +#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ +#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to + encode arbitrary object + graph */ +uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, + int flags); +uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, + int flags, uint8_t ***psab_tab, size_t *psab_tab_len); + +#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */ +#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */ +#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ +#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */ +JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags); +/* instantiate and evaluate a bytecode function. Only used when + reading a script or module with JS_ReadObject() */ +JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); +/* load the dependencies of the module 'obj'. Useful when JS_ReadObject() + returns a module. */ +int JS_ResolveModule(JSContext *ctx, JSValueConst obj); + +/* only exported for os.Worker() */ +JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); +/* only exported for os.Worker() */ +JSValue JS_LoadModule(JSContext *ctx, const char *basename, + const char *filename); + +/* C function definition */ +typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ + JS_CFUNC_generic, + JS_CFUNC_generic_magic, + JS_CFUNC_constructor, + JS_CFUNC_constructor_magic, + JS_CFUNC_constructor_or_func, + JS_CFUNC_constructor_or_func_magic, + JS_CFUNC_f_f, + JS_CFUNC_f_f_f, + JS_CFUNC_getter, + JS_CFUNC_setter, + JS_CFUNC_getter_magic, + JS_CFUNC_setter_magic, + JS_CFUNC_iterator_next, +} JSCFunctionEnum; + +typedef union JSCFunctionType { + JSCFunction *generic; + JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); + JSCFunction *constructor; + JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); + JSCFunction *constructor_or_func; + double (*f_f)(double); + double (*f_f_f)(double, double); + JSValue (*getter)(JSContext *ctx, JSValueConst this_val); + JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); + JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); + JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); + JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int *pdone, int magic); +} JSCFunctionType; + +JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic); +JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, + int length, int magic, int data_len, + JSValueConst *data); + +static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, + int length) +{ + return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0); +} + +static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic) +{ + /* Used to squelch a -Wcast-function-type warning. */ + JSCFunctionType ft = { .generic_magic = func }; + return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); +} +int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto); + +/* C property definition */ + +typedef struct JSCFunctionListEntry { + const char *name; + uint8_t prop_flags; + uint8_t def_type; + int16_t magic; + union { + struct { + uint8_t length; /* XXX: should move outside union */ + uint8_t cproto; /* XXX: should move outside union */ + JSCFunctionType cfunc; + } func; + struct { + JSCFunctionType get; + JSCFunctionType set; + } getset; + struct { + const char *name; + int base; + } alias; + struct { + const struct JSCFunctionListEntry *tab; + int len; + } prop_list; + const char *str; + int32_t i32; + int64_t i64; + double f64; + } u; +} JSCFunctionListEntry; + +#define JS_DEF_CFUNC 0 +#define JS_DEF_CGETSET 1 +#define JS_DEF_CGETSET_MAGIC 2 +#define JS_DEF_PROP_STRING 3 +#define JS_DEF_PROP_INT32 4 +#define JS_DEF_PROP_INT64 5 +#define JS_DEF_PROP_DOUBLE 6 +#define JS_DEF_PROP_UNDEFINED 7 +#define JS_DEF_OBJECT 8 +#define JS_DEF_ALIAS 9 +#define JS_DEF_PROP_ATOM 10 +#define JS_DEF_PROP_BOOL 11 + +/* Note: c++ does not like nested designators */ +#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } +#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } +#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } +#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } +#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } +#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } } +#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } } +#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } } +#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } } +#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } } +#define JS_PROP_ATOM_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_ATOM, 0, .u = { .i32 = val } } +#define JS_PROP_BOOL_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_BOOL, 0, .u = { .i32 = val } } +#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } } +#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } } +#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } } + +int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, + const JSCFunctionListEntry *tab, + int len); + +/* C module definition */ + +typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); + +JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, + JSModuleInitFunc *func); +/* can only be called before the module is instantiated */ +int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); +int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); +/* can only be called after the module is instantiated */ +int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, + JSValue val); +int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); +/* associate a JSValue to a C module */ +int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val); +JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m); + +/* debug value output */ + +typedef struct { + JS_BOOL show_hidden : 8; /* only show enumerable properties */ + JS_BOOL raw_dump : 8; /* avoid doing autoinit and avoid any malloc() call (for internal use) */ + uint32_t max_depth; /* recurse up to this depth, 0 = no limit */ + uint32_t max_string_length; /* print no more than this length for + strings, 0 = no limit */ + uint32_t max_item_count; /* print no more than this count for + arrays or objects, 0 = no limit */ +} JSPrintValueOptions; + +typedef void JSPrintValueWrite(void *opaque, const char *buf, size_t len); + +void JS_PrintValueSetDefaultOptions(JSPrintValueOptions *options); +void JS_PrintValueRT(JSRuntime *rt, JSPrintValueWrite *write_func, void *write_opaque, + JSValueConst val, const JSPrintValueOptions *options); +void JS_PrintValue(JSContext *ctx, JSPrintValueWrite *write_func, void *write_opaque, + JSValueConst val, const JSPrintValueOptions *options); + +#undef js_unlikely +#undef js_force_inline + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* QUICKJS_H */ diff --git a/quickjs/readme-cosmo.txt b/quickjs/readme-cosmo.txt new file mode 100644 index 0000000..fb524a2 --- /dev/null +++ b/quickjs/readme-cosmo.txt @@ -0,0 +1,21 @@ +The executables included in this archive run on Linux, Mac, Windows, +FreeBSD, OpenBSD and NetBSD for both the ARM64 and x86_64 +architectures. + +Platform Notes: + +- if you get errors on Linux, you should disable the binfmt_misc + module which automatically invokes wine with Windows executable: + +sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/cli' # remove Ubuntu's MZ interpreter +sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/status' # remove ALL binfmt_misc entries + +- Under Windows, you can rename the executables with a .exe extension. + +- Use the --assimilate option to build a platform specific binary for + better startup time: + + ./qjs --assimilate + +- See https://github.com/jart/cosmopolitan for more information about + platform specific issues. diff --git a/quickjs/readme.txt b/quickjs/readme.txt new file mode 100644 index 0000000..789521d --- /dev/null +++ b/quickjs/readme.txt @@ -0,0 +1 @@ +The main documentation is in doc/quickjs.pdf or doc/quickjs.html. diff --git a/quickjs/release.sh b/quickjs/release.sh new file mode 100755 index 0000000..6f4bdf5 --- /dev/null +++ b/quickjs/release.sh @@ -0,0 +1,184 @@ +#!/bin/sh +# Release the QuickJS source code + +set -e + +version=`cat VERSION` + +if [ "$1" = "-h" ] ; then + echo "release.sh [release_list]" + echo "" + echo "release_list: extras binary win_binary cosmo_binary quickjs" + + exit 1 +fi + +release_list="extras binary win_binary cosmo_binary quickjs" + +if [ "$1" != "" ] ; then + release_list="$1" +fi + +#################################################" +# extras + +if echo $release_list | grep -w -q extras ; then + +d="quickjs-${version}" +name="quickjs-extras-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir $outdir/unicode $outdir/tests + +cp unicode/* $outdir/unicode +cp -a tests/bench-v8 $outdir/tests + +( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} ) + +fi + +#################################################" +# Windows binary release + +if echo $release_list | grep -w -q win_binary ; then + +# win64 + +dlldir=/usr/x86_64-w64-mingw32/sys-root/mingw/bin +cross_prefix="x86_64-w64-mingw32-" +d="quickjs-win-x86_64-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir + +make clean +make CONFIG_WIN32=y clean + +make CONFIG_WIN32=y CONFIG_LTO=y qjs.exe +cp qjs.exe $outdir +${cross_prefix}strip $outdir/qjs.exe +cp $dlldir/libwinpthread-1.dll $outdir + +( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . ) + +make CONFIG_WIN32=y clean + +# win32 + +dlldir=/usr/i686-w64-mingw32/sys-root/mingw/bin +cross_prefix="i686-w64-mingw32-" +d="quickjs-win-i686-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir + +make clean +make CONFIG_WIN32=y clean + +make CONFIG_WIN32=y CONFIG_M32=y CONFIG_LTO=y qjs.exe +cp qjs.exe $outdir +${cross_prefix}strip $outdir/qjs.exe +cp $dlldir/libwinpthread-1.dll $outdir + +( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . ) + +fi + +#################################################" +# Linux binary release + +if echo $release_list | grep -w -q binary ; then + +make clean +make CONFIG_WIN32=y clean +make -j4 CONFIG_LTO=y qjs run-test262 +strip qjs run-test262 + +d="quickjs-linux-x86_64-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir + +cp qjs run-test262 $outdir + +( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . ) + +make clean +make -j4 CONFIG_LTO=y CONFIG_M32=y qjs run-test262 +strip qjs run-test262 + +d="quickjs-linux-i686-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir + +cp qjs run-test262 $outdir + +( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . ) + +fi + +#################################################" +# Cosmopolitan binary release + +if echo $release_list | grep -w -q cosmo_binary ; then + +export PATH=$PATH:$HOME/cosmocc/bin + +d="quickjs-cosmo-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir + +make clean +make CONFIG_COSMO=y -j4 qjs run-test262 +cp qjs run-test262 $outdir +cp readme-cosmo.txt $outdir/readme.txt + +( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . ) + +fi + +#################################################" +# quickjs + +if echo $release_list | grep -w -q quickjs ; then + +make build_doc + +d="quickjs-${version}" +outdir="/tmp/${d}" + +rm -rf $outdir +mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples + +cp Makefile VERSION TODO Changelog readme.txt LICENSE \ + release.sh unicode_download.sh \ + qjs.c qjsc.c repl.js \ + quickjs.c quickjs.h quickjs-atom.h \ + quickjs-libc.c quickjs-libc.h quickjs-opcode.h \ + cutils.c cutils.h list.h \ + libregexp.c libregexp.h libregexp-opcode.h \ + libunicode.c libunicode.h libunicode-table.h \ + dtoa.c dtoa.h \ + unicode_gen.c unicode_gen_def.h \ + run-test262.c test262o.conf test262.conf \ + test262o_errors.txt test262_errors.txt \ + $outdir + +cp tests/*.js tests/*.patch tests/bjson.c $outdir/tests + +cp examples/*.js examples/*.c examples/*.json $outdir/examples + +cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \ + $outdir/doc + +( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} ) + +fi diff --git a/quickjs-ng/repl.js b/quickjs/repl.js similarity index 55% rename from quickjs-ng/repl.js rename to quickjs/repl.js index d7e302e..06d4f26 100644 --- a/quickjs-ng/repl.js +++ b/quickjs/repl.js @@ -22,34 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import * as std from "qjs:std"; -import * as os from "qjs:os"; -import * as bjson from "qjs:bjson"; +import * as std from "std"; +import * as os from "os"; (function(g) { - /* add 'bjson', 'os' and 'std' bindings */ - g.bjson = bjson; + /* add 'os' and 'std' bindings */ g.os = os; g.std = std; /* close global objects */ var Object = g.Object; var String = g.String; - var Number = g.Number; - var Boolean = g.Boolean; - var BigInt = g.BigInt; - var Uint8Array = g.Uint8Array; var Array = g.Array; var Date = g.Date; - var RegExp = g.RegExp; - var Error = g.Error; - var Symbol = g.Symbol; var Math = g.Math; - var JSON = g.JSON; var isFinite = g.isFinite; - var isNaN = g.isNaN; - var Infinity = g.Infinity; - var console = g.console; + var parseFloat = g.parseFloat; var colors = { none: "\x1b[0m", @@ -72,73 +60,45 @@ import * as bjson from "qjs:bjson"; bright_white: "\x1b[37;1m", }; - var themes = { - dark: { - 'annotation': 'cyan', - 'boolean': 'bright_white', - 'comment': 'white', - 'date': 'magenta', - 'default': 'bright_green', - 'error': 'bright_red', - 'function': 'bright_yellow', - 'identifier': 'bright_green', - 'keyword': 'bright_white', - 'null': 'bright_white', - 'number': 'green', - 'other': 'white', - 'propname': 'white', - 'regexp': 'cyan', - 'string': 'bright_cyan', - 'symbol': 'bright_white', - 'type': 'bright_magenta', - 'undefined': 'bright_white', - }, - light: { - 'annotation': 'cyan', - 'boolean': 'bright_magenta', - 'comment': 'grey', - 'date': 'magenta', - 'default': 'black', - 'error': 'red', - 'function': 'bright_yellow', - 'identifier': 'black', - 'keyword': 'bright_magenta', - 'null': 'bright_magenta', - 'number': 'green', - 'other': 'black', - 'propname': 'black', - 'regexp': 'cyan', - 'string': 'bright_cyan', - 'symbol': 'grey', - 'type': 'bright_magenta', - 'undefined': 'bright_magenta', - }, + var styles = { + 'default': 'bright_green', + 'comment': 'white', + 'string': 'bright_cyan', + 'regex': 'cyan', + 'number': 'green', + 'keyword': 'bright_white', + 'function': 'bright_yellow', + 'type': 'bright_magenta', + 'identifier': 'bright_green', + 'error': 'red', + 'result': 'bright_white', + 'error_msg': 'bright_red', }; - var styles = themes.dark; - var utf8 = true; - var show_time = false; - var show_colors = true; - var show_hidden = false; - var show_depth = 2; - var hex_mode = false; - var use_strict = false; var history = []; - var history_index; var clip_board = ""; + var prec; + var expBits; + var log2_10; + var pstate = ""; var prompt = ""; var plen = 0; var ps1 = "qjs > "; var ps2 = " ... "; + var utf8 = true; + var show_time = false; + var show_colors = true; var eval_start_time; var eval_time = 0; + var mexpr = ""; var level = 0; var cmd = ""; var cursor_pos = 0; var last_cmd = ""; var last_cursor_pos = 0; + var history_index; var this_fun, last_fun; var quote_flag = false; @@ -260,7 +220,7 @@ import * as bjson from "qjs:bjson"; var style = style_names[i = j]; while (++j < str.length && style_names[j] == style) continue; - std.puts(colors[styles[style] || 'none']); + std.puts(colors[styles[style] || 'default']); std.puts(str.substring(i, j)); std.puts(colors['none']); } @@ -412,11 +372,6 @@ import * as bjson from "qjs:bjson"; cursor_pos = skip_word_backward(cursor_pos); } - function clear_screen() { - directives["clear"](); - return -2; - } - function accept_line() { std.puts("\n"); history_add(cmd); @@ -424,10 +379,7 @@ import * as bjson from "qjs:bjson"; } function history_add(str) { - str = str.trimRight(); if (str) { - while (history.length && !history[history.length - 1]) - history.length--; history.push(str); } history_index = history.length; @@ -590,7 +542,7 @@ import * as bjson from "qjs:bjson"; function control_c() { if (last_fun === control_c) { std.puts("\n"); - exit(0); + std.exit(0); } else { std.puts("\n(Press Ctrl-C again to quit)\n"); readline_print_prompt(); @@ -602,60 +554,51 @@ import * as bjson from "qjs:bjson"; cursor_pos = 0; } - function get_context_word(line, end) { - var pos = end; - while (pos > 0 && is_word(line[pos - 1])) + function get_context_word(line, pos) { + var s = ""; + while (pos > 0 && is_word(line[pos - 1])) { pos--; - return line.slice(pos, end); + s = line[pos] + s; + } + return s; } function get_context_object(line, pos) { - if (pos <= 0) + var obj, base, c; + if (pos <= 0 || " ~!%^&*(-+={[|:;,<>?/".indexOf(line[pos - 1]) >= 0) return g; - var c = line[pos - 1]; - if (pos === 1 && (c === '\\' || c === '.')) - return directives; - if ("'\"`@#)]}\\".indexOf(c) >= 0) - return void 0; - if (c === ".") { + if (pos >= 2 && line[pos - 1] === ".") { pos--; + obj = {}; switch (c = line[pos - 1]) { case '\'': case '\"': - case '`': return "a"; case ']': - return []; // incorrect for a[b]. + return []; + case '}': + return {}; case '/': return / /; default: if (is_word(c)) { - var base = get_context_word(line, pos); - var base_pos = pos - base.length; - if (base === 'true' || base === 'false') - return true; - if (base === 'null') - return null; - if (base === 'this') - return g; - if (!isNaN(+base)) // number literal, incorrect for 1. - return 0; - var obj = get_context_object(line, base_pos); + base = get_context_word(line, pos); + if (["true", "false", "null", "this"].includes(base) || !isNaN(+base)) + return eval(base); + // Check if `base` is a set of regexp flags + if (pos - base.length >= 3 && line[pos - base.length - 1] === '/') + return new RegExp('', base); + obj = get_context_object(line, pos - base.length); if (obj === null || obj === void 0) return obj; - if (typeof obj[base] !== 'undefined') + if (obj === g && obj[base] === void 0) + return eval(base); + else return obj[base]; - // Check if `base` is a set of regexp flags - // TODO(chqrlie): this is incorrect for a/i... - // Should use colorizer to determine the token type - if (base_pos >= 3 && line[base_pos - 1] === '/' && base.match(/^[dgimsuvy]+$/)) - return RegExp(); - // base is a local identifier, complete as generic object } - break; + return {}; } - return {}; } - return g; + return void 0; } function get_completions(line, pos) { @@ -775,7 +718,6 @@ import * as bjson from "qjs:bjson"; "\x09": completion, /* ^I - history-search-backward */ "\x0a": accept_line, /* ^J - newline */ "\x0b": kill_line, /* ^K - delete to end of line */ - "\x0c": clear_screen, /* ^L - clear screen */ "\x0d": accept_line, /* ^M - enter */ "\x0e": next_history, /* ^N - down */ "\x10": previous_history, /* ^P - up */ @@ -783,7 +725,6 @@ import * as bjson from "qjs:bjson"; "\x12": alert, /* ^R - reverse-search */ "\x13": alert, /* ^S - search */ "\x14": transpose_chars, /* ^T - transpose */ - "\x17": backward_kill_word, /* ^W - backward_kill_word */ "\x18": reset, /* ^X - cancel */ "\x19": yank, /* ^Y - yank */ "\x1bOA": previous_history, /* ^[OA - up */ @@ -918,7 +859,6 @@ import * as bjson from "qjs:bjson"; os.signal(os.SIGINT, null); /* uninstall the stdin read handler */ os.setReadHandler(term_fd, null); - save_history(); return; } last_fun = this_fun; @@ -934,589 +874,75 @@ import * as bjson from "qjs:bjson"; update(); } - function number_to_string(a, radix) { - var s; - if (!isFinite(a)) { - /* NaN, Infinite */ - return a.toString(); - } else { - if (a == 0) { - if (1 / a < 0) - s = "-0"; - else - s = "0"; - } else { - if (radix == 16 && a === Math.floor(a)) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - } - return s; - } - } + var hex_mode = false; - function bigint_to_string(a, radix) { + function number_to_string_hex(a) { var s; - if (radix == 16) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); + if (a < 0) { + a = -a; + s = "-"; } else { - s = a.toString(); - } - return s + "n"; - } - - var util = {}; - util.inspect = function(val, show_hidden, max_depth, use_colors) { - var options = {}; - if (typeof show_hidden === 'object' && show_hidden !== null) { - options = show_hidden; - show_hidden = options.showHidden; - max_depth = options.depth; - use_colors = options.colors; - } - function set(opt, def) { - return (typeof opt === 'undefined') ? def : (opt === null) ? Infinity : opt; - } - if (typeof show_hidden !== 'boolean') - show_hidden = false; - max_depth = set(max_depth, 2); - use_colors = set(use_colors, true); - var breakLength = set(options.breakLength, Math.min(term_width, 80)); - var maxArrayLength = set(options.maxArrayLength, 100); - var maxObjectLength = set(options.maxObjectLength, maxArrayLength + 10); - var maxStringLength = set(options.maxStringLength, 78); - var refs = [{}]; /* list of circular references */ - var stack = []; /* stack of pending objects */ - var tokens = []; /* list of generated tokens */ - var output = []; /* list of output fragments */ - var last_style = 'none'; - - function quote_str(s) { - if (s.includes("'")) - return JSON.stringify(s); - s = JSON.stringify(s).slice(1, -1).replaceAll('\\"', '"'); - return `'${s}'`; - } - function push_token(s) { - tokens.push("" + s); - } - function append_token(s) { - tokens[tokens.length - 1] += s; - } - function class_tag(o) { - // get the class id of an object - // works for boxed objects, Math, JSON, globalThis... - return Object.prototype.toString.call(o).slice(8, -1); - } - - function print_rec(a, level) { - var n, n0, i, k, keys, key, type, isarray, noindex, nokeys, brace, sep; - - switch (type = typeof(a)) { - case "undefined": - case "boolean": - push_token(a); - break; - case "number": - push_token(number_to_string(a, hex_mode ? 16 : 10)); - break; - case "bigint": - push_token(bigint_to_string(a, hex_mode ? 16 : 10)); + s = ""; + } + s += "0x" + a.toString(16); + return s; + } + + function extract_directive(a) { + var pos; + if (a[0] !== '\\') + return ""; + for (pos = 1; pos < a.length; pos++) { + if (!is_alpha(a[pos])) break; - case "string": - if (a.length > maxStringLength) - a = a.substring(0, maxStringLength) + "..."; - push_token(quote_str(a)); - break; - case "symbol": - push_token(String(a)); - break; - case "object": - case "function": - if (a === null) { - push_token(a); - break; - } - if ((n = refs.indexOf(a)) >= 0) { - push_token(`[Circular *${n}]`); - break; - } - if ((n = stack.indexOf(a)) >= 0) { - push_token(`[Circular *${refs.length}]`); - refs.push(stack[n]); - break; - } - var obj_index = tokens.length; - var tag = class_tag(a); - stack.push(a); - // XXX: should have Proxy instances - if (a instanceof Date) { - push_token(`Date ${JSON.stringify(a.toGMTString())}`); - } else if (a instanceof RegExp) { - push_token(a.toString()); - } else if (a instanceof Boolean || a instanceof Number || a instanceof BigInt) { - push_token(`[${tag}: ${a}]`); - } else if (a instanceof String) { - push_token(`[${tag}: ${quote_str(a)}]`); - len = a.length; - noindex = 1; - } else if (Array.isArray(a)) { - push_token("["); - isarray = 1; - } else if (tag.includes('Array') && a instanceof Uint8Array.__proto__) { - push_token(`${tag}(${a.length}) [`); - isarray = 1; - } else if (type === 'function') { - if (a.name) - push_token(`[Function: ${a.name}]`); - else - push_token(`[Function (anonymous)]`); - } else { - var cons = (a.constructor && a.constructor.name) || 'Object'; - if (tag !== 'Object') { - push_token(`${cons} [${tag}] {`); - } else if (a.__proto__ === null) { - push_token(`[${cons}: null prototype] {`); - } else if (cons !== 'Object') { - push_token(`${cons} {`); - } else { - push_token("{"); - } - brace = "}"; - } - keys = null; - n = 0; - n0 = 0; - k = 0; - if (isarray) { - brace = "]"; - var len = a.length; - if (level > max_depth && len) { - push_token("..."); - push_token(brace); - return; - } - for (i = 0; i < len; i++) { - k++; - if (i in a) { - print_rec(a[i], level + 1); - } else { - var start = i; - while (i + 1 < len && !((i + 1) in a)) - i++; - if (i > start) - push_token(`<${i - start + 1} empty items>`); - else - push_token(""); - } - if (k >= maxArrayLength && len - k > 5) { - push_token(`... ${len - k} more items`); - break; - } - } - noindex = 1; - /* avoid using Object.keys for large arrays */ - if (i !== len && len > 1000) - nokeys = 1; - } - if (!nokeys) { - keys = show_hidden ? Object.getOwnPropertyNames(a) : Object.keys(a); - n = keys.length; - } - if (noindex) { - /* skip all index properties */ - for (; n0 < n; n0++) { - i = +keys[n0]; - if (i !== (i >>> 0) || i >= len) - break; - } - } - if (n0 < n) { - if (!brace) { - append_token(" {"); - brace = "}"; - } - if (level > max_depth && n0 < n) { - push_token("..."); - push_token(brace); - return; - } - for(i = n0; i < n; i++) { - var key = keys[i]; - var desc = Object.getOwnPropertyDescriptor(a, key); - if (!desc) - continue; - if (!desc.enumerable) - push_token(`[${String(key)}]`); - else - if (+key === (key >>> 0) || key.match(/^[a-zA-Z_$][0-9a-zA-Z_$]*/)) - push_token(key); - else - push_token(quote_str(key)); - push_token(":"); - if ('value' in desc) { - print_rec(desc.value, level + 1); - } else { - var fields = []; - if (desc.get) - fields.push("Getter"); - if (desc.set) - fields.push("Setter"); - push_token(`[${fields.join('/')}]`); - } - k++; - if (k > maxObjectLength && n - k > 5) { - push_token(`... ${n - k} more properties`); - break; - } - } - } - if (brace) - push_token(brace); - stack.pop(a); - if ((i = refs.indexOf(a)) > 0) - tokens[obj_index] = ` ${tokens[obj_index]}`; - break; - default: - push_token(String(a)); - break; - } - }; - function output_str(s, style) { - if (use_colors) { - if (last_style !== style) { - output.push(colors.none); - last_style = style; - } - if (style) { - var color = colors[styles[style]]; - if (color) - output.push(color); - } - } - output.push(s); } - function output_propname(s) { - if (s[0] >= '0' && s[0] <= '9') - output_str(s, 'number'); - else - output_str(s, 'propname'); - output_str(": "); - } - function output_pretty(s) { - if (!use_colors) { - output_str(s); - return; - } - while (s.length > 0) { - var style = 'none'; - var chunk = s; - var len = 0; - var m = null; - switch (s[0]) { - case '"': - style = 'string'; - m = s.match(/^"([^\\"]|\\.)*"/); - break; - case '\'': - style = 'string'; - m = s.match(/^'([^\\']|\\.)*'/); - break; - case '/': - style = 'regexp'; - break; - case '<': - m = s.match(/^\<[^\>]+\>/); - if (m) - style = 'annotation'; - break; - case '[': - m = s.match(/^\[[^\]]+\]/); - if (m) { - style = 'annotation'; - break; - } - /* fall thru */ - case ']': - case '}': - case ',': - case ' ': - style = 'other'; - len = 1; - break; - case '.': - style = 'annotation'; - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - style = 'number'; - m = s.match(/^[0-9a-z_]+[.]?[0-9a-z_]*[eEpP]?[+-]?[0-9]*/); - break; - case '-': - len = 1; - break; - default: - if (is_block(s)) - len = s.length - 1; - if (s.startsWith('Date')) - style = 'date'; - else if (s.startsWith('Symbol')) - style = 'symbol'; - else if (s === 'Infinity' || s === 'NaN') - style = 'keyword'; - else if (s === 'true' || s === 'false') - style = 'boolean'; - else if (s === 'null') - style = 'null'; - else if (s === 'undefined') - style = 'undefined'; - break; - } - if (m) - len = m[0].length; - if (len > 0) - chunk = s.slice(0, len); - output_str(chunk, style); - s = s.slice(chunk.length); - } - } - function is_block(s) { - var c = s[s.length - 1]; - return c === '[' || c === '{'; - } - function block_width(i) { - var w = tokens[i].length; - if (tokens[i + 1] === ":") { - i += 2; - w += 2 + tokens[i].length; - } - var width = w; - if (is_block(tokens[i])) { - var seplen = 1; - while (++i < tokens.length) { - width += seplen; - var s = tokens[i]; - if (s === ']' || s === '}') - break; - [ i, w ] = block_width(i); - width += w; - seplen = 2; - } - } - return [ i, width ]; - } - function output_single(i, last) { - var sep = ""; - while (i <= last) { - var s = tokens[i++]; - if (s === ']' || s === '}') { - if (sep.length > 1) - output_str(" "); - } else { - output_str(sep); - if (tokens[i] === ":") { - output_propname(s); - i++; - s = tokens[i++]; - } - } - output_pretty(s); - sep = is_block(s) ? " " : ", "; - } - } - function output_spaces(s, count) { - if (count > 0) - s += " ".repeat(count); - output_str(s); - } - function output_indent(indent, from) { - var avail_width = breakLength - indent - 2; - var [ last, width ] = block_width(from); - if (width <= avail_width) { - output_single(from, last); - return [ last, width ]; - } - if (tokens[from + 1] === ":") { - output_propname(tokens[from]); - from += 2; - } - output_pretty(tokens[from]); - if (!is_block(tokens[from])) { - return [ from, width ]; - } - indent += 2; - avail_width -= 2; - var sep = ""; - var first = from + 1; - var i, w; - if (tokens[from].endsWith('[')) { - /* array: try multiple columns for indexed values */ - var k = 0, col, cols; - var tab = []; - for (i = first; i < last; i++) { - if (tokens[i][0] === '.' || tokens[i + 1] === ':') - break; - [ i, w ] = block_width(i); - tab[k++] = w; - } - var colwidth; - for (cols = Math.min(avail_width / 3, tab.length, 16); cols > 1; cols--) { - colwidth = []; - col = 0; - for (k = 0; k < tab.length; k++) { - colwidth[col] = Math.max(colwidth[col] || 0, tab[k] + 2); - col = (col + 1) % cols; - } - w = 0; - for (col = 0; col < cols; col++) { - w += colwidth[col]; - } - if (w <= avail_width) - break; - } - if (cols > 1) { - w = 0; - col = cols - 1; - for (i = first; i < last; i++) { - if (tokens[i][0] === '.' || tokens[i + 1] === ':') - break; - w += sep.length; - output_str(sep); - sep = ","; - if (col === cols - 1) { - output_spaces("\n", indent); - col = 0; - } else { - output_spaces("", colwidth[col++] - w); - } - [i, w] = output_indent(indent, i); - } - first = i; - } - } - for (i = first; i < last; i++) { - output_str(sep); - sep = ","; - output_spaces("\n", indent); - [i, w] = output_indent(indent, i); - } - output_spaces("\n", indent -= 2); - output_pretty(tokens[last]); - return [last, breakLength]; - } - print_rec(val, 0); - output_indent(0, 0); - output_str(""); - return output.join(""); - }; - - function print(val) { - std.puts(util.inspect(val, { depth: show_depth, colors: show_colors, showHidden: show_hidden })); - std.puts("\n"); + return a.substring(1, pos); } - /* return true if the string was a directive */ - function handle_directive(a) { - if (a === "?") { + /* return true if the string after cmd can be evaluted as JS */ + function handle_directive(cmd, expr) { + var param, prec1, expBits1; + + if (cmd === "h" || cmd === "?" || cmd == "help") { help(); - return true; - } - if (a[0] !== '\\' && a[0] !== '.') + } else if (cmd === "load") { + var filename = expr.substring(cmd.length + 1).trim(); + if (filename.lastIndexOf(".") <= filename.lastIndexOf("/")) + filename += ".js"; + std.loadScript(filename); return false; - var pos = 1; - while (pos < a.length && a[pos] !== ' ') { - pos++; - } - var cmd = a.substring(1, pos); - var partial = 0; - var fun; - for (var p in directives) { - if (p.startsWith(cmd)) { - fun = directives[p]; - partial++; - if (p === cmd) { - partial = 0; - break; - } - } - } - if (fun && partial < 2) { - fun(a.substring(pos).trim()); + } else if (cmd === "x") { + hex_mode = true; + } else if (cmd === "d") { + hex_mode = false; + } else if (cmd === "t") { + show_time = !show_time; + } else if (cmd === "clear") { + std.puts("\x1b[H\x1b[J"); + } else if (cmd === "q") { + std.exit(0); } else { - std.puts(`Unknown directive: ${cmd}\n`); + std.puts("Unknown directive: " + cmd + "\n"); + return false; } return true; } function help() { - var sel = (n) => n ? "*": " "; - std.puts(".help print this help\n" + - ".x " + sel(hex_mode) + "hexadecimal number display\n" + - ".dec " + sel(!hex_mode) + "decimal number display\n" + - ".time " + sel(show_time) + "toggle timing display\n" + - ".strict " + sel(use_strict) + "toggle strict mode evaluation\n" + - `.depth set object depth (current: ${show_depth})\n` + - ".hidden " + sel(show_hidden) + "toggle hidden properties display\n" + - ".color " + sel(show_colors) + "toggle colored output\n" + - ".dark " + sel(styles == themes.dark) + "select dark color theme\n" + - ".light " + sel(styles == themes.light) + "select light color theme\n" + - ".clear clear the terminal\n" + - ".load load source code from a file\n" + - ".quit exit\n"); - } - - function load(s) { - if (s.lastIndexOf(".") <= s.lastIndexOf("/")) - s += ".js"; - try { - std.loadScript(s); - } catch (e) { - std.puts(`${e}\n`); + function sel(n) { + return n ? "*": " "; } + std.puts("\\h this help\n" + + "\\x " + sel(hex_mode) + "hexadecimal number display\n" + + "\\d " + sel(!hex_mode) + "decimal number display\n" + + "\\t " + sel(show_time) + "toggle timing display\n" + + "\\clear clear the terminal\n" + + "\\q exit\n"); } - function exit(e) { - save_history(); - std.exit(e); - } - - function to_bool(s, def) { - return s ? "1 true yes Yes".includes(s) : def; - } - - var directives = Object.setPrototypeOf({ - "help": help, - "load": load, - "x": (s) => { hex_mode = to_bool(s, true); }, - "dec": (s) => { hex_mode = !to_bool(s, true); }, - "time": (s) => { show_time = to_bool(s, !show_time); }, - "strict": (s) => { use_strict = to_bool(s, !use_strict); }, - "depth": (s) => { show_depth = +s || 2; }, - "hidden": (s) => { show_hidden = to_bool(s, !show_hidden); }, - "color": (s) => { show_colors = to_bool(s, !show_colors); }, - "dark": () => { styles = themes.dark; }, - "light": () => { styles = themes.light; }, - "clear": () => { std.puts("\x1b[H\x1b[J") }, - "quit": () => { exit(0); }, - }, null); - function cmd_start() { - std.puts('QuickJS-ng - Type ".help" for help\n'); + std.puts('QuickJS - Type "\\h" for help\n'); + cmd_readline_start(); } @@ -1532,15 +958,29 @@ import * as bjson from "qjs:bjson"; /* return true if async termination */ function handle_cmd(expr) { - if (!expr) + var colorstate, cmd; + + if (expr === null) { + expr = ""; return false; - if (mexpr) { - expr = mexpr + '\n' + expr; - } else { - if (handle_directive(expr)) + } + if (expr === "?") { + help(); + return false; + } + cmd = extract_directive(expr); + if (cmd.length > 0) { + if (!handle_directive(cmd, expr)) { return false; + } + expr = expr.substring(cmd.length + 1); } - var colorstate = colorize_js(expr); + if (expr === "") + return false; + + if (mexpr) + expr = mexpr + '\n' + expr; + colorstate = colorize_js(expr); pstate = colorstate[0]; level = colorstate[1]; if (pstate) { @@ -1549,26 +989,47 @@ import * as bjson from "qjs:bjson"; } mexpr = ""; - eval_and_print(expr); + eval_and_print_start(expr); return true; } - function eval_and_print(expr) { + function eval_and_print_start(expr) { var result; - if (use_strict) - expr = '"use strict"; void 0;' + expr; - eval_start_time = os.now(); - /* eval as a script */ - result = Promise.try(std.evalScript, expr, { backtrace_barrier: true, async: true }); - result.then(print_eval_result, print_eval_error); + try { + eval_start_time = os.now(); + /* eval as a script */ + result = std.evalScript(expr, { backtrace_barrier: true, async: true }); + /* result is a promise */ + result.then(print_eval_result, print_eval_error); + } catch (error) { + print_eval_error(error); + } } function print_eval_result(result) { + var default_print = true; + result = result.value; eval_time = os.now() - eval_start_time; - print(result); + std.puts(colors[styles.result]); + if (hex_mode) { + if (typeof result == "number" && + result === Math.floor(result)) { + std.puts(number_to_string_hex(result)); + default_print = false; + } else if (typeof result == "bigint") { + std.puts(number_to_string_hex(result)); + std.puts("n"); + default_print = false; + } + } + if (default_print) { + std.__printObject(result); + } + std.puts("\n"); + std.puts(colors.none); /* set the last result */ g._ = result; @@ -1576,34 +1037,20 @@ import * as bjson from "qjs:bjson"; } function print_eval_error(error) { - if (show_colors) { - std.puts(colors[styles.error]); - } - if (error instanceof Error) { - std.puts(error); - std.puts('\n'); - if (error.stack) { - std.puts(error.stack); - } - } else { + std.puts(colors[styles.error_msg]); + if (!(error instanceof Error)) std.puts("Throw: "); - std.puts(error); - std.puts('\n'); - } - - if (show_colors) { - std.puts(colors.none); - } + std.__printObject(error); + std.puts("\n"); + std.puts(colors.none); handle_cmd_end(); } function handle_cmd_end() { level = 0; - /* run the garbage collector after each command */ std.gc(); - cmd_readline_start(); } @@ -1664,7 +1111,7 @@ import * as bjson from "qjs:bjson"; } function parse_regex() { - style = 'regexp'; + style = 'regex'; push_state('/'); while (i < n) { c = str[i++]; @@ -1702,8 +1149,6 @@ import * as bjson from "qjs:bjson"; function parse_number() { style = 'number'; - // TODO(chqrlie) parse partial number syntax - // TODO(chqrlie) special case bignum while (i < n && (is_word(str[i]) || (str[i] == '.' && (i == n - 1 || str[i + 1] != '.')))) { i++; } @@ -1729,19 +1174,10 @@ import * as bjson from "qjs:bjson"; while (i < n && is_word(str[i])) i++; - var s = str.substring(start, i); - var w = '|' + s + '|'; + var w = '|' + str.substring(start, i) + '|'; if (js_keywords.indexOf(w) >= 0) { style = 'keyword'; - if (s === 'true' || s === 'false') - style = 'boolean'; - else if (s === 'true' || s === 'false') - style = 'boolean'; - else if (s === 'null') - style = 'null'; - else if (s === 'undefined') - style = 'undefined'; if (js_no_regex.indexOf(w) >= 0) can_regex = 0; return; @@ -1835,7 +1271,7 @@ import * as bjson from "qjs:bjson"; can_regex = 0; break; } - if (is_word(c)) { + if (is_word(c) || c == '$') { parse_identifier(); break; } @@ -1849,43 +1285,8 @@ import * as bjson from "qjs:bjson"; return [ state, level, r ]; } - function config_file(s) { - return (std.getenv("HOME") || std.getenv("USERPROFILE") || ".") + "/" + s; - } - function save_history() { - var s = history.slice(-1000).join('\n').trim(); - if (s) { - try { - var f = std.open(config_file(".qjs_history"), "w"); - f.puts(s + '\n'); - f.close(); - } catch (e) { - } - } - } - function load_history() { - var a = std.loadFile(config_file(".qjs_history")); - if (a) { - history = a.trim().split('\n'); - history_index = history.length; - } - } - function load_config() { - var m, s = std.getenv("COLORFGBG"); - if (s && (m = s.match(/(\d+);(\d+)/))) { - if (+m[2] !== 0) { // light background - styles = themes.light; - } - } - s = std.getenv("NO_COLOR"); // https://no-color.org/ - if (s && +s[0] !== 0) { - show_colors = false; - } - } - - load_config(); - load_history(); termInit(); + cmd_start(); })(globalThis); diff --git a/quickjs-ng/run-test262.c b/quickjs/run-test262.c similarity index 66% rename from quickjs-ng/run-test262.c rename to quickjs/run-test262.c index c937313..100ed13 100644 --- a/quickjs-ng/run-test262.c +++ b/quickjs/run-test262.c @@ -29,56 +29,28 @@ #include #include #include +#include #include #include - -#ifdef _WIN32 -#include -#include -#else #include -#include -#endif +#include #include "cutils.h" #include "list.h" -#include "quickjs.h" -#include "quickjs-c-atomics.h" #include "quickjs-libc.h" -#define CMD_NAME "run-test262" - -// not quite correct because in theory someone could compile quickjs.c -// with a different compiler but in practice no one does that, right? -#ifdef __TINYC__ -#define CC_IS_TCC 1 -#else -#define CC_IS_TCC 0 -#endif +/* enable test262 thread support to test SharedArrayBuffer and Atomics */ +#define CONFIG_AGENT -typedef struct { - js_mutex_t agent_mutex; - js_cond_t agent_cond; - /* list of Test262Agent.link */ - struct list_head agent_list; - js_mutex_t report_mutex; - /* list of AgentReport.link */ - struct list_head report_list; - int async_done; -} ThreadLocalStorage; +#define CMD_NAME "run-test262" typedef struct namelist_t { char **array; int count; int size; + unsigned int sorted : 1; } namelist_t; -long nthreads; // invariant: 0 < nthreads < countof(threads) -js_thread_t threads[32]; -js_thread_t progress_thread; -js_cond_t progress_cond; -js_mutex_t progress_mutex; - namelist_t test_list; namelist_t exclude_list; namelist_t exclude_dir_list; @@ -91,38 +63,34 @@ enum test_mode_t { TEST_STRICT, /* run tests as strict, skip nostrict tests */ TEST_ALL, /* run tests in both strict and nostrict, unless restricted by spec */ } test_mode = TEST_DEFAULT_NOSTRICT; -int local; +int compact; +int show_timings; int skip_async; int skip_module; +int new_style; int dump_memory; int stats_count; JSMemoryUsage stats_all, stats_avg, stats_min, stats_max; char *stats_min_filename; char *stats_max_filename; -js_mutex_t stats_mutex; int verbose; char *harness_dir; char *harness_exclude; char *harness_features; char *harness_skip_features; +int *harness_skip_features_count; char *error_filename; char *error_file; FILE *error_out; +char *report_filename; int update_errors; -int slow_test_threshold; -int start_index, stop_index; -int test_excluded; -_Atomic int test_count, test_failed, test_skipped; -_Atomic int new_errors, changed_errors, fixed_errors; +int test_count, test_failed, test_index, test_skipped, test_excluded; +int new_errors, changed_errors, fixed_errors; +int async_done; void warning(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); void fatal(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); -void atomic_inc(volatile _Atomic int *p) -{ - atomic_fetch_add(p, 1); -} - void warning(const char *fmt, ...) { va_list ap; @@ -169,15 +137,6 @@ static inline int str_equal(const char *a, const char *b) { return !strcmp(a, b); } -static inline int str_count(const char *a, const char *b) { - int count = 0; - while ((a = strstr(a, b))) { - a += strlen(b); - count++; - } - return count; -} - char *str_append(char **pp, const char *sep, const char *str) { char *res, *p; size_t len = 0; @@ -304,12 +263,16 @@ void namelist_sort(namelist_t *lp) } lp->count = count; } + lp->sorted = 1; } -int namelist_find(const namelist_t *lp, const char *name) +int namelist_find(namelist_t *lp, const char *name) { int a, b, m, cmp; + if (!lp->sorted) { + namelist_sort(lp); + } for (a = 0, b = lp->count; a < b;) { m = a + (b - a) / 2; cmp = namelist_cmp(lp->array[m], name); @@ -351,7 +314,7 @@ void namelist_load(namelist_t *lp, const char *filename) char *base_name; FILE *f; - f = fopen(filename, "r"); + f = fopen(filename, "rb"); if (!f) { perror_exit(1, filename); } @@ -392,129 +355,72 @@ void namelist_free(namelist_t *lp) lp->size = 0; } -static int add_test_file(const char *filename) +static int add_test_file(const char *filename, const struct stat *ptr, int flag) { namelist_t *lp = &test_list; - if (js__has_suffix(filename, ".js") && !js__has_suffix(filename, "_FIXTURE.js")) + if (has_suffix(filename, ".js") && !has_suffix(filename, "_FIXTURE.js")) namelist_add(lp, NULL, filename); return 0; } -static void find_test_files(const char *path); - -static bool ispathsep(int c) -{ - return c == '/' || c == '\\'; -} - -static void consider_test_file(const char *path, const char *name, int is_dir) -{ - size_t pathlen; - char s[1024]; - - if (str_equal(name, ".") || str_equal(name, "..")) - return; - pathlen = strlen(path); - while (pathlen > 0 && ispathsep(path[pathlen-1])) - pathlen--; - snprintf(s, sizeof(s), "%.*s/%s", (int)pathlen, path, name); - if (is_dir) - find_test_files(s); - else - add_test_file(s); -} - -static void find_test_files(const char *path) -{ -#ifdef _WIN32 - WIN32_FIND_DATAA d; - HANDLE h; - char s[1024]; - - snprintf(s, sizeof(s), "%s/*", path); - h = FindFirstFileA(s, &d); - if (h != INVALID_HANDLE_VALUE) { - do { - consider_test_file(path, - d.cFileName, - d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } while (FindNextFileA(h, &d)); - FindClose(h); - } -#else - struct dirent *d, **ds = NULL; - int i, n; - - n = scandir(path, &ds, NULL, alphasort); - for (i = 0; i < n; i++) { - d = ds[i]; - consider_test_file(path, d->d_name, d->d_type == DT_DIR); - free(d); - } - free(ds); -#endif -} - /* find js files from the directory tree and sort the list */ static void enumerate_tests(const char *path) { namelist_t *lp = &test_list; int start = lp->count; - find_test_files(path); + ftw(path, add_test_file, 100); qsort(lp->array + start, lp->count - start, sizeof(*lp->array), namelist_cmp_indirect); } -static JSValue js_print_262(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static void js_print_value_write(void *opaque, const char *buf, size_t len) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); - const char *s; - JSValueConst v; - int i; + FILE *fo = opaque; + fwrite(buf, 1, len, fo); +} - for (i = 0; i < argc; i++) { - v = argv[i]; - s = JS_ToCString(ctx, v); - // same logic as js_print in quickjs-libc.c - if (local && !s && JS_IsObject(v)) { - JS_FreeValue(ctx, JS_GetException(ctx)); - JSValue t = JS_ToObjectString(ctx, v); - s = JS_ToCString(ctx, t); - JS_FreeValue(ctx, t); - } - if (!s) - return JS_EXCEPTION; - if (!strcmp(s, "Test262:AsyncTestComplete")) { - tls->async_done++; - } else if (js__strstart(s, "Test262:AsyncTestFailure", NULL)) { - tls->async_done = 2; /* force an error */ - } - if (outfile) { +static JSValue js_print(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int i; + JSValueConst v; + + if (outfile) { + for (i = 0; i < argc; i++) { if (i != 0) fputc(' ', outfile); - fputs(s, outfile); + v = argv[i]; + if (JS_IsString(v)) { + const char *str; + size_t len; + str = JS_ToCStringLen(ctx, &len, v); + if (!str) + return JS_EXCEPTION; + if (!strcmp(str, "Test262:AsyncTestComplete")) { + async_done++; + } else if (strstart(str, "Test262:AsyncTestFailure", NULL)) { + async_done = 2; /* force an error */ + } + fwrite(str, 1, len, outfile); + JS_FreeCString(ctx, str); + } else { + JS_PrintValue(ctx, js_print_value_write, outfile, v, NULL); + } } - if (verbose > 1) - printf("%s%s", &" "[i < 1], s); - JS_FreeCString(ctx, s); - } - if (outfile) fputc('\n', outfile); - if (verbose > 1) - printf("\n"); + } return JS_UNDEFINED; } -static JSValue js_detachArrayBuffer(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_detachArrayBuffer(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JS_DetachArrayBuffer(ctx, argv[0]); return JS_UNDEFINED; } -static JSValue js_evalScript_262(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_evalScript(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *str; size_t len; @@ -527,44 +433,20 @@ static JSValue js_evalScript_262(JSContext *ctx, JSValueConst this_val, return ret; } -static long cpu_count(void) -{ -#ifdef _WIN32 - DWORD_PTR procmask, sysmask; - long count; - int i; - - count = 0; - if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask)) - for (i = 0; i < 8 * sizeof(procmask); i++) - count += 1 & (procmask >> i); - return count; -#else - return sysconf(_SC_NPROCESSORS_ONLN); -#endif -} +#ifdef CONFIG_AGENT -static void init_thread_local_storage(ThreadLocalStorage *p) -{ - js_mutex_init(&p->agent_mutex); - js_cond_init(&p->agent_cond); - init_list_head(&p->agent_list); - js_mutex_init(&p->report_mutex); - init_list_head(&p->report_list); - p->async_done = 0; -} +#include typedef struct { struct list_head link; - js_thread_t tid; + pthread_t tid; char *script; JSValue broadcast_func; - bool broadcast_pending; + BOOL broadcast_pending; JSValue broadcast_sab; /* in the main context */ uint8_t *broadcast_sab_buf; size_t broadcast_sab_size; int32_t broadcast_val; - ThreadLocalStorage *tls; } Test262Agent; typedef struct { @@ -575,22 +457,27 @@ typedef struct { static JSValue add_helpers1(JSContext *ctx); static void add_helpers(JSContext *ctx); -static void agent_start(void *arg) +static pthread_mutex_t agent_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t agent_cond = PTHREAD_COND_INITIALIZER; +/* list of Test262Agent.link */ +static struct list_head agent_list = LIST_HEAD_INIT(agent_list); + +static pthread_mutex_t report_mutex = PTHREAD_MUTEX_INITIALIZER; +/* list of AgentReport.link */ +static struct list_head report_list = LIST_HEAD_INIT(report_list); + +static void *agent_start(void *arg) { - ThreadLocalStorage *tls; - Test262Agent *agent; + Test262Agent *agent = arg; JSRuntime *rt; JSContext *ctx; JSValue ret_val; int ret; - agent = arg; - tls = agent->tls; // shares thread-local storage with parent thread rt = JS_NewRuntime(); if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } - JS_SetRuntimeOpaque(rt, tls); ctx = JS_NewContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); @@ -598,7 +485,7 @@ static void agent_start(void *arg) } JS_SetContextOpaque(ctx, agent); JS_SetRuntimeInfo(rt, "agent"); - JS_SetCanBlock(rt, true); + JS_SetCanBlock(rt, TRUE); add_helpers(ctx); ret_val = JS_Eval(ctx, agent->script, strlen(agent->script), @@ -610,8 +497,7 @@ static void agent_start(void *arg) JS_FreeValue(ctx, ret_val); for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL); if (ret < 0) { js_std_dump_error(ctx); break; @@ -621,19 +507,19 @@ static void agent_start(void *arg) } else { JSValue args[2]; - js_mutex_lock(&tls->agent_mutex); + pthread_mutex_lock(&agent_mutex); while (!agent->broadcast_pending) { - js_cond_wait(&tls->agent_cond, &tls->agent_mutex); + pthread_cond_wait(&agent_cond, &agent_mutex); } - agent->broadcast_pending = false; - js_cond_signal(&tls->agent_cond); + agent->broadcast_pending = FALSE; + pthread_cond_signal(&agent_cond); - js_mutex_unlock(&tls->agent_mutex); + pthread_mutex_unlock(&agent_mutex); args[0] = JS_NewArrayBuffer(ctx, agent->broadcast_sab_buf, agent->broadcast_sab_size, - NULL, NULL, true); + NULL, NULL, TRUE); args[1] = JS_NewInt32(ctx, agent->broadcast_val); ret_val = JS_Call(ctx, agent->broadcast_func, JS_UNDEFINED, 2, (JSValueConst *)args); @@ -651,14 +537,15 @@ static void agent_start(void *arg) JS_FreeContext(ctx); JS_FreeRuntime(rt); + return NULL; } -static JSValue js_agent_start(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_start(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); const char *script; Test262Agent *agent; + pthread_attr_t attr; if (JS_GetContextOpaque(ctx) != NULL) return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); @@ -671,30 +558,33 @@ static JSValue js_agent_start(JSContext *ctx, JSValueConst this_val, agent->broadcast_func = JS_UNDEFINED; agent->broadcast_sab = JS_UNDEFINED; agent->script = strdup(script); - agent->tls = tls; JS_FreeCString(ctx, script); - list_add_tail(&agent->link, &tls->agent_list); - js_thread_create(&agent->tid, agent_start, agent, /*flags*/0); + list_add_tail(&agent->link, &agent_list); + pthread_attr_init(&attr); + // musl libc gives threads 80 kb stacks, much smaller than + // JS_DEFAULT_STACK_SIZE (256 kb) + pthread_attr_setstacksize(&attr, 2 << 20); // 2 MB, glibc default + pthread_create(&agent->tid, &attr, agent_start, agent); + pthread_attr_destroy(&attr); return JS_UNDEFINED; } static void js_agent_free(JSContext *ctx) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); struct list_head *el, *el1; Test262Agent *agent; - list_for_each_safe(el, el1, &tls->agent_list) { + list_for_each_safe(el, el1, &agent_list) { agent = list_entry(el, Test262Agent, link); - js_thread_join(agent->tid); + pthread_join(agent->tid, NULL); JS_FreeValue(ctx, agent->broadcast_sab); list_del(&agent->link); free(agent); } } -static JSValue js_agent_leaving(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { Test262Agent *agent = JS_GetContextOpaque(ctx); if (!agent) @@ -703,22 +593,21 @@ static JSValue js_agent_leaving(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static bool is_broadcast_pending(ThreadLocalStorage *tls) +static BOOL is_broadcast_pending(void) { struct list_head *el; Test262Agent *agent; - list_for_each(el, &tls->agent_list) { + list_for_each(el, &agent_list) { agent = list_entry(el, Test262Agent, link); if (agent->broadcast_pending) - return true; + return TRUE; } - return false; + return FALSE; } -static JSValue js_agent_broadcast(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); JSValueConst sab = argv[0]; struct list_head *el; Test262Agent *agent; @@ -737,10 +626,10 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValueConst this_val, /* broadcast the values and wait until all agents have started calling their callbacks */ - js_mutex_lock(&tls->agent_mutex); - list_for_each(el, &tls->agent_list) { + pthread_mutex_lock(&agent_mutex); + list_for_each(el, &agent_list) { agent = list_entry(el, Test262Agent, link); - agent->broadcast_pending = true; + agent->broadcast_pending = TRUE; /* the shared array buffer is used by the thread, so increment its refcount */ agent->broadcast_sab = JS_DupValue(ctx, sab); @@ -748,17 +637,17 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValueConst this_val, agent->broadcast_sab_size = buf_size; agent->broadcast_val = val; } - js_cond_broadcast(&tls->agent_cond); + pthread_cond_broadcast(&agent_cond); - while (is_broadcast_pending(tls)) { - js_cond_wait(&tls->agent_cond, &tls->agent_mutex); + while (is_broadcast_pending()) { + pthread_cond_wait(&agent_cond, &agent_mutex); } - js_mutex_unlock(&tls->agent_mutex); + pthread_mutex_unlock(&agent_mutex); return JS_UNDEFINED; } -static JSValue js_agent_receiveBroadcast(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_receiveBroadcast(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { Test262Agent *agent = JS_GetContextOpaque(ctx); if (!agent) @@ -770,52 +659,43 @@ static JSValue js_agent_receiveBroadcast(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_agent_sleep(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_sleep(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { uint32_t duration; if (JS_ToUint32(ctx, &duration, argv[0])) return JS_EXCEPTION; -#ifdef _WIN32 - Sleep(duration); -#else usleep(duration * 1000); -#endif return JS_UNDEFINED; } static int64_t get_clock_ms(void) { -#ifdef _WIN32 - return GetTickCount64(); -#else struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000); -#endif } -static JSValue js_agent_monotonicNow(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_NewInt64(ctx, get_clock_ms()); } -static JSValue js_agent_getReport(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); AgentReport *rep; JSValue ret; - js_mutex_lock(&tls->report_mutex); - if (list_empty(&tls->report_list)) { + pthread_mutex_lock(&report_mutex); + if (list_empty(&report_list)) { rep = NULL; } else { - rep = list_entry(tls->report_list.next, AgentReport, link); + rep = list_entry(report_list.next, AgentReport, link); list_del(&rep->link); } - js_mutex_unlock(&tls->report_mutex); + pthread_mutex_unlock(&report_mutex); if (rep) { ret = JS_NewString(ctx, rep->str); free(rep->str); @@ -826,10 +706,9 @@ static JSValue js_agent_getReport(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_agent_report(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_agent_report(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); const char *str; AgentReport *rep; @@ -840,9 +719,9 @@ static JSValue js_agent_report(JSContext *ctx, JSValueConst this_val, rep->str = strdup(str); JS_FreeCString(ctx, str); - js_mutex_lock(&tls->report_mutex); - list_add_tail(&rep->link, &tls->report_list); - js_mutex_unlock(&tls->report_mutex); + pthread_mutex_lock(&report_mutex); + list_add_tail(&rep->link, &report_list); + pthread_mutex_unlock(&report_mutex); return JS_UNDEFINED; } @@ -868,9 +747,10 @@ static JSValue js_new_agent(JSContext *ctx) countof(js_agent_funcs)); return agent; } +#endif -static JSValue js_createRealm(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_createRealm(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSContext *ctx1; JSValue ret; @@ -884,42 +764,56 @@ static JSValue js_createRealm(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_IsHTMLDDA(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_IsHTMLDDA(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_NULL; } +static JSValue js_gc(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JS_RunGC(JS_GetRuntime(ctx)); + return JS_UNDEFINED; +} + static JSValue add_helpers1(JSContext *ctx) { JSValue global_obj; - JSValue obj262, is_html_dda; + JSValue obj262, obj; global_obj = JS_GetGlobalObject(ctx); JS_SetPropertyStr(ctx, global_obj, "print", - JS_NewCFunction(ctx, js_print_262, "print", 1)); - - is_html_dda = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0); - JS_SetIsHTMLDDA(ctx, is_html_dda); -#define N 7 - static const char *props[N] = { - "detachArrayBuffer", "evalScript", "codePointRange", - "agent", "global", "createRealm", "IsHTMLDDA", - }; - JSValue values[N] = { - JS_NewCFunction(ctx, js_detachArrayBuffer, "detachArrayBuffer", 1), - JS_NewCFunction(ctx, js_evalScript_262, "evalScript", 1), - JS_NewCFunction(ctx, js_string_codePointRange, "codePointRange", 2), - js_new_agent(ctx), - JS_DupValue(ctx, global_obj), - JS_NewCFunction(ctx, js_createRealm, "createRealm", 0), - is_html_dda, - }; + JS_NewCFunction(ctx, js_print, "print", 1)); + /* $262 special object used by the tests */ - obj262 = JS_NewObjectFromStr(ctx, N, props, values); + obj262 = JS_NewObject(ctx); + JS_SetPropertyStr(ctx, obj262, "detachArrayBuffer", + JS_NewCFunction(ctx, js_detachArrayBuffer, + "detachArrayBuffer", 1)); + JS_SetPropertyStr(ctx, obj262, "evalScript", + JS_NewCFunction(ctx, js_evalScript, + "evalScript", 1)); + JS_SetPropertyStr(ctx, obj262, "codePointRange", + JS_NewCFunction(ctx, js_string_codePointRange, + "codePointRange", 2)); +#ifdef CONFIG_AGENT + JS_SetPropertyStr(ctx, obj262, "agent", js_new_agent(ctx)); +#endif + + JS_SetPropertyStr(ctx, obj262, "global", + JS_DupValue(ctx, global_obj)); + JS_SetPropertyStr(ctx, obj262, "createRealm", + JS_NewCFunction(ctx, js_createRealm, + "createRealm", 0)); + obj = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0); + JS_SetIsHTMLDDA(ctx, obj); + JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj); + JS_SetPropertyStr(ctx, obj262, "gc", + JS_NewCFunction(ctx, js_gc, "gc", 0)); + JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262)); -#undef N JS_FreeValue(ctx, global_obj); return obj262; @@ -942,13 +836,21 @@ static char *load_file(const char *filename, size_t *lenp) return buf; } +static int json_module_init_test(JSContext *ctx, JSModuleDef *m) +{ + JSValue val; + val = JS_GetModulePrivateValue(ctx, m); + JS_SetModuleExport(ctx, m, "default", val); + return 0; +} + static JSModuleDef *js_module_loader_test(JSContext *ctx, - const char *module_name, void *opaque) + const char *module_name, void *opaque, + JSValueConst attributes) { size_t buf_len; uint8_t *buf; JSModuleDef *m; - JSValue func_val; char *filename, *slash, path[1024]; // interpret import("bar.js") from path/to/foo.js as @@ -958,7 +860,7 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, slash = strrchr(filename, '/'); if (slash) { snprintf(path, sizeof(path), "%.*s/%s", - (int) (slash - filename), filename, module_name); + (int)(slash - filename), filename, module_name); module_name = path; } } @@ -970,15 +872,33 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, return NULL; } - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); + if (js_module_test_json(ctx, attributes) == 1) { + /* compile as JSON */ + JSValue val; + val = JS_ParseJSON(ctx, (char *)buf, buf_len, module_name); + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + m = JS_NewCModule(ctx, module_name, json_module_init_test); + if (!m) { + JS_FreeValue(ctx, val); + return NULL; + } + /* only export the "default" symbol which will contain the JSON object */ + JS_AddModuleExport(ctx, m, "default"); + JS_SetModulePrivateValue(ctx, m, val); + } else { + JSValue func_val; + /* compile the module */ + func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + js_free(ctx, buf); + if (JS_IsException(func_val)) + return NULL; + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(func_val); + JS_FreeValue(ctx, func_val); + } return m; } @@ -1024,14 +944,13 @@ void update_exclude_dirs(void) namelist_t *lp = &test_list; namelist_t *ep = &exclude_list; namelist_t *dp = &exclude_dir_list; - char *name, *path; + char *name; int i, j, count; - size_t include, exclude; /* split directpries from exclude_list */ for (count = i = 0; i < ep->count; i++) { name = ep->array[i]; - if (js__has_suffix(name, "/")) { + if (has_suffix(name, "/")) { namelist_add(dp, NULL, name); free(name); } else { @@ -1045,19 +964,15 @@ void update_exclude_dirs(void) /* filter out excluded directories */ for (count = i = 0; i < lp->count; i++) { name = lp->array[i]; - include = exclude = 0; for (j = 0; j < dp->count; j++) { - path = dp->array[j]; - if (has_prefix(name, path)) - exclude = strlen(path); - if (*path == '!' && has_prefix(name, &path[1])) - include = strlen(&path[1]); + if (has_prefix(name, dp->array[j])) { + test_excluded++; + free(name); + name = NULL; + break; + } } - // most specific include/exclude wins - if (exclude > include) { - test_excluded++; - free(name); - } else { + if (name) { lp->array[count++] = name; } } @@ -1078,7 +993,7 @@ void load_config(const char *filename, const char *ignore) } section = SECTION_NONE; int lineno = 0; - f = fopen(filename, "r"); + f = fopen(filename, "rb"); if (!f) { perror_exit(1, filename); } @@ -1123,8 +1038,8 @@ void load_config(const char *filename, const char *ignore) printf("%s:%d: ignoring %s=%s\n", filename, lineno, p, q); continue; } - if (str_equal(p, "local")) { - local = str_equal(q, "yes"); + if (str_equal(p, "style")) { + new_style = str_equal(q, "new"); continue; } if (str_equal(p, "testdir")) { @@ -1183,8 +1098,7 @@ void load_config(const char *filename, const char *ignore) continue; } if (str_equal(p, "verbose")) { - int count = str_count(q, "yes"); - verbose = max_int(verbose, count); + verbose = str_equal(q, "yes"); continue; } if (str_equal(p, "errorfile")) { @@ -1197,11 +1111,15 @@ void load_config(const char *filename, const char *ignore) free(path); continue; } + if (str_equal(p, "reportfile")) { + report_filename = compose_path(base_name, q); + continue; + } case SECTION_EXCLUDE: namelist_add(&exclude_list, base_name, p); break; case SECTION_FEATURES: - if (!q || str_equal(q, "yes") || (!CC_IS_TCC && str_equal(q, "!tcc"))) + if (!q || str_equal(q, "yes")) str_append(&harness_features, " ", p); else str_append(&harness_skip_features, " ", p); @@ -1238,7 +1156,7 @@ char *find_error(const char *filename, int *pline, int is_strict) q++; } /* check strict mode indicator */ - if (!js__strstart(q, "strict mode: ", &q) != !is_strict) + if (!strstart(q, "strict mode: ", &q) != !is_strict) continue; r = q = skip_prefix(q, "unexpected error: "); r += strcspn(r, "\n"); @@ -1324,27 +1242,24 @@ int longest_match(const char *str, const char *find, int pos, int *ppos, int lin static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, const char *filename, int is_test, int is_negative, - const char *error_type, int eval_flags, int is_async, - int *msec) + const char *error_type, FILE *outfile, int eval_flags, + int is_async) { - ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); JSValue res_val, exception_val; int ret, error_line, pos, pos_line; - bool is_error, has_error_line, ret_promise; + BOOL is_error, has_error_line, ret_promise; const char *error_name; - int start, duration; pos = skip_comments(buf, 1, &pos_line); error_line = pos_line; - has_error_line = false; + has_error_line = FALSE; exception_val = JS_UNDEFINED; error_name = NULL; /* a module evaluation returns a promise */ ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0); - tls->async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ + async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ - start = get_clock_ms(); res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); if ((is_async || ret_promise) && !JS_IsException(res_val)) { @@ -1355,15 +1270,14 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, JS_FreeValue(ctx, res_val); } for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL); if (ret < 0) { res_val = JS_EXCEPTION; break; } else if (ret == 0) { if (is_async) { /* test if the test called $DONE() once */ - if (tls->async_done != 1) { + if (async_done != 1) { res_val = JS_ThrowTypeError(ctx, "$DONE() not called"); } else { res_val = JS_UNDEFINED; @@ -1384,13 +1298,16 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, JS_FreeValue(ctx, promise); } - duration = get_clock_ms() - start; - *msec += duration; - if (JS_IsException(res_val)) { exception_val = JS_GetException(ctx); is_error = JS_IsError(ctx, exception_val); - js_print_262(ctx, JS_NULL, 1, (JSValueConst *)&exception_val); + /* XXX: should get the filename and line number */ + if (outfile) { + if (!is_error) + fprintf(outfile, "%sThrow: ", (eval_flags & JS_EVAL_FLAG_STRICT) ? + "strict mode: " : ""); + js_print(ctx, JS_NULL, 1, &exception_val); + } if (is_error) { JSValue name, stack; const char *stack_str; @@ -1404,11 +1321,14 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, const char *p; int len; + if (outfile) + fprintf(outfile, "%s", stack_str); + len = strlen(filename); p = strstr(stack_str, filename); if (p != NULL && p[len] == ':') { error_line = atoi(p + len + 1); - has_error_line = true; + has_error_line = TRUE; } JS_FreeCString(ctx, stack_str); } @@ -1423,15 +1343,11 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, const char *msg; msg = JS_ToCString(ctx, exception_val); - if (msg == NULL) { + error_class = strdup_len(msg, strcspn(msg, ":")); + if (!str_equal(error_class, error_type)) ret = -1; - } else { - error_class = strdup_len(msg, strcspn(msg, ":")); - if (!str_equal(error_class, error_type)) - ret = -1; - free(error_class); - JS_FreeCString(ctx, msg); - } + free(error_class); + JS_FreeCString(ctx, msg); } } else { ret = -1; @@ -1449,7 +1365,6 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, int s_line; char *s = find_error(filename, &s_line, eval_flags & JS_EVAL_FLAG_STRICT); const char *strict_mode = (eval_flags & JS_EVAL_FLAG_STRICT) ? "strict mode: " : ""; - bool is_unexpected_error = true; if (!JS_IsUndefined(exception_val)) { msg_val = JS_ToString(ctx, exception_val); @@ -1459,15 +1374,14 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, if (ret == 0) { if (msg && s && (str_equal(s, "expected error") || - js__strstart(s, "unexpected error type:", NULL) || + strstart(s, "unexpected error type:", NULL) || str_equal(s, msg))) { // did not have error yet if (!has_error_line) { longest_match(buf, msg, pos, &pos, pos_line, &error_line); } printf("%s:%d: %sOK, now has error %s\n", filename, error_line, strict_mode, msg); - atomic_inc(&fixed_errors); - is_unexpected_error = false; + fixed_errors++; } } else { if (!s) { // not yet reported @@ -1478,7 +1392,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, fprintf(error_out, "%s:%d: %sexpected error\n", filename, error_line, strict_mode); } - atomic_inc(&new_errors); + new_errors++; } } } else { // should not have error @@ -1497,42 +1411,22 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, if (s && (!str_equal(s, msg) || error_line != s_line)) { printf("%s:%d: %sprevious error: %s\n", filename, s_line, strict_mode, s); - atomic_inc(&changed_errors); + changed_errors++; } else { - atomic_inc(&new_errors); + new_errors++; } } } else { if (s) { printf("%s:%d: %sOK, fixed error: %s\n", filename, s_line, strict_mode, s); - atomic_inc(&fixed_errors); - is_unexpected_error = false; + fixed_errors++; } } } - if (is_unexpected_error && verbose > 1 && JS_IsException(exception_val)) { - JSValue val = JS_GetPropertyStr(ctx, exception_val, "stack"); - if (!JS_IsException(val) && - !JS_IsUndefined(val) && - !JS_IsNull(val)) { - const char *str = JS_ToCString(ctx, val); - if (str) - printf("%s\n", str); - JS_FreeCString(ctx, str); - JS_FreeValue(ctx, val); - } - } JS_FreeValue(ctx, msg_val); JS_FreeCString(ctx, msg); free(s); } - - if (local) { - ret = js_std_loop(ctx); - if (ret) - js_std_dump_error(ctx); - } - JS_FreeCString(ctx, error_name); JS_FreeValue(ctx, exception_val); JS_FreeValue(ctx, res_val); @@ -1545,15 +1439,14 @@ static int eval_file(JSContext *ctx, const char *base, const char *p, char *buf; size_t buf_len; char *filename = compose_path(base, p); - int msec = 0; buf = load_file(filename, &buf_len); if (!buf) { warning("cannot load %s", filename); goto fail; } - if (eval_buf(ctx, buf, buf_len, filename, false, false, NULL, - eval_flags, false, &msec)) { + if (eval_buf(ctx, buf, buf_len, filename, FALSE, FALSE, NULL, stderr, + eval_flags, FALSE)) { warning("error evaluating %s", filename); goto fail; } @@ -1567,7 +1460,7 @@ static int eval_file(JSContext *ctx, const char *base, const char *p, return 1; } -char *extract_desc(const char *buf) +char *extract_desc(const char *buf, char style) { const char *p, *desc_start; char *desc; @@ -1575,7 +1468,7 @@ char *extract_desc(const char *buf) p = buf; while (*p != '\0') { - if (p[0] == '/' && p[1] == '*' && p[2] == '-' && p[3] != '/') { + if (p[0] == '/' && p[1] == '*' && p[2] == style && p[3] != '/') { p += 3; desc_start = p; while (*p != '\0' && (p[0] != '*' || p[1] != '/')) @@ -1652,12 +1545,9 @@ static char *get_option(char **pp, int *state) void update_stats(JSRuntime *rt, const char *filename) { JSMemoryUsage stats; JS_ComputeMemoryUsage(rt, &stats); - js_mutex_lock(&stats_mutex); if (stats_count++ == 0) { stats_avg = stats_all = stats_min = stats_max = stats; - free(stats_min_filename); stats_min_filename = strdup(filename); - free(stats_max_filename); stats_max_filename = strdup(filename); } else { if (stats_max.malloc_size < stats.malloc_size) { @@ -1697,44 +1587,12 @@ void update_stats(JSRuntime *rt, const char *filename) { update(fast_array_elements); } #undef update - js_mutex_unlock(&stats_mutex); -} - -static JSValue qjs_black_box(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst argv[], int magic) -{ - return JS_NewInt32(ctx, js_std_cmd(magic, ctx, &argv[0])); -} - -static const JSCFunctionListEntry qjs_methods[] = { - JS_CFUNC_MAGIC_DEF("getStringKind", 1, qjs_black_box, /*GetStringKind*/3), -}; - -static const JSCFunctionListEntry qjs_object = - JS_OBJECT_DEF("qjs", qjs_methods, countof(qjs_methods), JS_PROP_C_W_E); - -JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx; - JSValue obj; - - ctx = JS_NewContext(rt); - if (ctx && local) { - js_init_module_std(ctx, "qjs:std"); - js_init_module_os(ctx, "qjs:os"); - js_init_module_bjson(ctx, "qjs:bjson"); - obj = JS_GetGlobalObject(ctx); - JS_SetPropertyFunctionList(ctx, obj, &qjs_object, 1); - JS_FreeValue(ctx, obj); - } - return ctx; } -int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness, - namelist_t *ip, char *buf, size_t buf_len, - const char* error_type, int eval_flags, bool is_negative, - bool is_async, bool can_block, bool track_promise_rejections, - int *msec) +int run_test_buf(const char *filename, const char *harness, namelist_t *ip, + char *buf, size_t buf_len, const char* error_type, + int eval_flags, BOOL is_negative, BOOL is_async, + BOOL can_block) { JSRuntime *rt; JSContext *ctx; @@ -1744,10 +1602,7 @@ int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness, if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } - JS_SetDumpFlags(rt, JS_DUMP_LEAKS); - JS_SetRuntimeOpaque(rt, tls); - js_std_init_handlers(rt); - ctx = JS_NewCustomContext(rt); + ctx = JS_NewContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); fatal(1, "JS_NewContext failure"); @@ -1757,47 +1612,42 @@ int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness, JS_SetCanBlock(rt, can_block); /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); - - if (track_promise_rejections) - JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *)filename); add_helpers(ctx); for (i = 0; i < ip->count; i++) { - if (eval_file(ctx, harness, ip->array[i], JS_EVAL_TYPE_GLOBAL)) { + if (eval_file(ctx, harness, ip->array[i], + JS_EVAL_TYPE_GLOBAL)) { fatal(1, "error including %s for %s", ip->array[i], filename); } - // hack to get useful stack traces from Test262Error exceptions - if (verbose > 1 && str_equal(ip->array[i], "sta.js")) { - static const char hack[] = - ";(function(C){" - "globalThis.Test262Error = class Test262Error extends Error {};" - "globalThis.Test262Error.thrower = C.thrower;" - "})(Test262Error)"; - JS_FreeValue(ctx, JS_Eval(ctx, hack, sizeof(hack)-1, "sta.js", JS_EVAL_TYPE_GLOBAL)); - } } - ret = eval_buf(ctx, buf, buf_len, filename, true, is_negative, - error_type, eval_flags, is_async, msec); + ret = eval_buf(ctx, buf, buf_len, filename, TRUE, is_negative, + error_type, outfile, eval_flags, is_async); ret = (ret != 0); if (dump_memory) { update_stats(rt, filename); } +#ifdef CONFIG_AGENT js_agent_free(ctx); +#endif JS_FreeContext(ctx); - js_std_free_handlers(rt); JS_FreeRuntime(rt); - atomic_inc(&test_count); - if (ret) - atomic_inc(&test_failed); + test_count++; + if (ret) { + test_failed++; + if (outfile) { + /* do not output a failure number to minimize diff */ + fprintf(outfile, " FAILED\n"); + } + } return ret; } -int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) +int run_test(const char *filename, int index) { char harnessbuf[1024]; char *harness; @@ -1806,111 +1656,165 @@ int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) char *desc, *p; char *error_type; int ret, eval_flags, use_strict, use_nostrict; - bool is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip; - bool detect_module = true; - bool track_promise_rejections = false; - bool can_block; + BOOL is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip; + BOOL can_block; namelist_t include_list = { 0 }, *ip = &include_list; - is_nostrict = is_onlystrict = is_negative = is_async = is_module = skip = false; - can_block = true; + is_nostrict = is_onlystrict = is_negative = is_async = is_module = skip = FALSE; + can_block = TRUE; error_type = NULL; buf = load_file(filename, &buf_len); harness = harness_dir; - if (!harness) { - p = strstr(filename, "test/"); - if (p) { - snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", - (int)(p - filename), filename, "harness"); + if (new_style) { + if (!harness) { + p = strstr(filename, "test/"); + if (p) { + snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", + (int)(p - filename), filename, "harness"); + } else { + pstrcpy(harnessbuf, sizeof(harnessbuf), ""); + } + harness = harnessbuf; } - harness = harnessbuf; - } - if (!local) { namelist_add(ip, NULL, "sta.js"); namelist_add(ip, NULL, "assert.js"); - } - /* extract the YAML frontmatter */ - desc = extract_desc(buf); - if (desc) { - char *ifile, *option; - int state; - p = find_tag(desc, "includes:", &state); - if (p) { - while ((ifile = get_option(&p, &state)) != NULL) { - // skip unsupported harness files - if (find_word(harness_exclude, ifile)) { - skip |= 1; - } else { - namelist_add(ip, NULL, ifile); + /* extract the YAML frontmatter */ + desc = extract_desc(buf, '-'); + if (desc) { + char *ifile, *option; + int state; + p = find_tag(desc, "includes:", &state); + if (p) { + while ((ifile = get_option(&p, &state)) != NULL) { + // skip unsupported harness files + if (find_word(harness_exclude, ifile)) { + skip |= 1; + } else { + namelist_add(ip, NULL, ifile); + } + free(ifile); } - free(ifile); } - } - p = find_tag(desc, "flags:", &state); - if (p) { - while ((option = get_option(&p, &state)) != NULL) { - if (str_equal(option, "noStrict") || - str_equal(option, "raw")) { - is_nostrict = true; - skip |= (test_mode == TEST_STRICT); - } - else if (str_equal(option, "onlyStrict")) { - is_onlystrict = true; - skip |= (test_mode == TEST_NOSTRICT); - } - else if (str_equal(option, "async")) { - is_async = true; - skip |= skip_async; - } - else if (str_equal(option, "qjs:no-detect-module")) { - detect_module = false; - } - else if (str_equal(option, "qjs:track-promise-rejections")) { - track_promise_rejections = true; + p = find_tag(desc, "flags:", &state); + if (p) { + while ((option = get_option(&p, &state)) != NULL) { + if (str_equal(option, "noStrict") || + str_equal(option, "raw")) { + is_nostrict = TRUE; + skip |= (test_mode == TEST_STRICT); + } + else if (str_equal(option, "onlyStrict")) { + is_onlystrict = TRUE; + skip |= (test_mode == TEST_NOSTRICT); + } + else if (str_equal(option, "async")) { + is_async = TRUE; + skip |= skip_async; + } + else if (str_equal(option, "module")) { + is_module = TRUE; + skip |= skip_module; + } + else if (str_equal(option, "CanBlockIsFalse")) { + can_block = FALSE; + } + free(option); } - else if (str_equal(option, "module")) { - is_module = true; - skip |= skip_module; + } + p = find_tag(desc, "negative:", &state); + if (p) { + /* XXX: should extract the phase */ + char *q = find_tag(p, "type:", &state); + if (q) { + while (isspace((unsigned char)*q)) + q++; + error_type = strdup_len(q, strcspn(q, " \n")); } - else if (str_equal(option, "CanBlockIsFalse")) { - can_block = false; + is_negative = TRUE; + } + p = find_tag(desc, "features:", &state); + if (p) { + while ((option = get_option(&p, &state)) != NULL) { + char *p1; + if (find_word(harness_features, option)) { + /* feature is enabled */ + } else if ((p1 = find_word(harness_skip_features, option)) != NULL) { + /* skip disabled feature */ + if (harness_skip_features_count) + harness_skip_features_count[p1 - harness_skip_features]++; + skip |= 1; + } else { + /* feature is not listed: skip and warn */ + printf("%s:%d: unknown feature: %s\n", filename, 1, option); + skip |= 1; + } + free(option); } - free(option); } + free(desc); } - p = find_tag(desc, "negative:", &state); - if (p) { - /* XXX: should extract the phase */ - char *q = find_tag(p, "type:", &state); - if (q) { - while (isspace((unsigned char)*q)) - q++; - error_type = strdup_len(q, strcspn(q, " \r\n")); + if (is_async) + namelist_add(ip, NULL, "doneprintHandle.js"); + } else { + char *ifile; + + if (!harness) { + p = strstr(filename, "test/"); + if (p) { + snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", + (int)(p - filename), filename, "test/harness"); + } else { + pstrcpy(harnessbuf, sizeof(harnessbuf), ""); } - is_negative = true; + harness = harnessbuf; } - p = find_tag(desc, "features:", &state); - if (p) { - while ((option = get_option(&p, &state)) != NULL) { - if (find_word(harness_features, option)) { - /* feature is enabled */ - } else if (find_word(harness_skip_features, option)) { - /* skip disabled feature */ - skip |= 1; - } else { - /* feature is not listed: skip and warn */ - printf("%s:%d: unknown feature: %s\n", filename, 1, option); - skip |= 1; - } - free(option); + + namelist_add(ip, NULL, "sta.js"); + + /* include extra harness files */ + for (p = buf; (p = strstr(p, "$INCLUDE(\"")) != NULL; p++) { + p += 10; + ifile = strdup_len(p, strcspn(p, "\"")); + // skip unsupported harness files + if (find_word(harness_exclude, ifile)) { + skip |= 1; + } else { + namelist_add(ip, NULL, ifile); } + free(ifile); } - free(desc); + + /* locate the old style configuration comment */ + desc = extract_desc(buf, '*'); + if (desc) { + if (strstr(desc, "@noStrict")) { + is_nostrict = TRUE; + skip |= (test_mode == TEST_STRICT); + } + if (strstr(desc, "@onlyStrict")) { + is_onlystrict = TRUE; + skip |= (test_mode == TEST_NOSTRICT); + } + if (strstr(desc, "@negative")) { + /* XXX: should extract the regex to check error type */ + is_negative = TRUE; + } + free(desc); + } + } + + if (outfile && index >= 0) { + fprintf(outfile, "%d: %s%s%s%s%s%s%s\n", index, filename, + is_nostrict ? " @noStrict" : "", + is_onlystrict ? " @onlyStrict" : "", + is_async ? " async" : "", + is_module ? " module" : "", + is_negative ? " @negative" : "", + skip ? " SKIPPED" : ""); + fflush(outfile); } - if (is_async) - namelist_add(ip, NULL, "doneprintHandle.js"); use_strict = use_nostrict = 0; /* XXX: should remove 'test_mode' or simplify it just to force @@ -1949,28 +1853,32 @@ int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) } if (skip || use_strict + use_nostrict == 0) { - atomic_inc(&test_skipped); + test_skipped++; ret = -2; } else { - if (local && detect_module) { - is_module = JS_DetectModule(buf, buf_len); - } + clock_t clocks; + if (is_module) { eval_flags = JS_EVAL_TYPE_MODULE; } else { eval_flags = JS_EVAL_TYPE_GLOBAL; } + clocks = clock(); ret = 0; if (use_nostrict) { - ret = run_test_buf(tls, filename, harness, ip, buf, buf_len, + ret = run_test_buf(filename, harness, ip, buf, buf_len, error_type, eval_flags, is_negative, is_async, - can_block, track_promise_rejections, msec); + can_block); } if (use_strict) { - ret |= run_test_buf(tls, filename, harness, ip, buf, buf_len, + ret |= run_test_buf(filename, harness, ip, buf, buf_len, error_type, eval_flags | JS_EVAL_FLAG_STRICT, - is_negative, is_async, can_block, - track_promise_rejections, msec); + is_negative, is_async, can_block); + } + clocks = clock() - clocks; + if (outfile && index >= 0 && clocks >= CLOCKS_PER_SEC / 10) { + /* output timings for tests that take more than 100 ms */ + fprintf(outfile, " time: %d ms\n", (int)(clocks * 1000LL / CLOCKS_PER_SEC)); } } namelist_free(&include_list); @@ -1981,8 +1889,7 @@ int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) } /* run a test when called by test262-harness+eshost */ -int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, - bool is_module) +int run_test262_harness_test(const char *filename, BOOL is_module) { JSRuntime *rt; JSContext *ctx; @@ -1990,16 +1897,14 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, size_t buf_len; int eval_flags, ret_code, ret; JSValue res_val; - bool can_block; + BOOL can_block; - outfile = stdout; /* for js_print_262 */ + outfile = stdout; /* for js_print */ rt = JS_NewRuntime(); if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } - JS_SetDumpFlags(rt, JS_DUMP_LEAKS); - JS_SetRuntimeOpaque(rt, tls); ctx = JS_NewContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); @@ -2007,11 +1912,11 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, } JS_SetRuntimeInfo(rt, filename); - can_block = true; + can_block = TRUE; JS_SetCanBlock(rt, can_block); /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *)filename); add_helpers(ctx); @@ -2035,28 +1940,29 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, JS_FreeValue(ctx, res_val); } for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL); if (ret < 0) { - js_std_dump_error(ctx1); + js_std_dump_error(ctx); ret_code = 1; } else if (ret == 0) { break; } - } - /* dump the error if the module returned an error. */ - if (is_module) { - JSPromiseStateEnum state = JS_PromiseState(ctx, promise); - if (state == JS_PROMISE_REJECTED) { - JS_Throw(ctx, JS_PromiseResult(ctx, promise)); - js_std_dump_error(ctx); - ret_code = 1; - } - } - JS_FreeValue(ctx, promise); + } + /* dump the error if the module returned an error. */ + if (is_module) { + JSPromiseStateEnum state = JS_PromiseState(ctx, promise); + if (state == JS_PROMISE_REJECTED) { + JS_Throw(ctx, JS_PromiseResult(ctx, promise)); + js_std_dump_error(ctx); + ret_code = 1; + } + } + JS_FreeValue(ctx, promise); } free(buf); +#ifdef CONFIG_AGENT js_agent_free(ctx); +#endif JS_FreeContext(ctx); JS_FreeRuntime(rt); return ret_code; @@ -2064,74 +1970,92 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, clock_t last_clock; -void show_progress(void *unused) { - int interval = 1000*1000*1000 / 4; // 250 ms - - js_mutex_lock(&progress_mutex); - while (js_cond_timedwait(&progress_cond, &progress_mutex, interval)) { - /* output progress indicator: erase end of line and return to col 0 */ - fprintf(stderr, "%d/%d/%d \r", - atomic_load(&test_failed), - atomic_load(&test_count), - atomic_load(&test_skipped)); +void show_progress(int force) { + clock_t t = clock(); + if (force || !last_clock || (t - last_clock) > CLOCKS_PER_SEC / 20) { + last_clock = t; + if (compact) { + static int last_test_skipped; + static int last_test_failed; + static int dots; + char c = '.'; + if (test_skipped > last_test_skipped) + c = '-'; + if (test_failed > last_test_failed) + c = '!'; + last_test_skipped = test_skipped; + last_test_failed = test_failed; + fputc(c, stderr); + if (force || ++dots % 60 == 0) { + fprintf(stderr, " %d/%d/%d\n", + test_failed, test_count, test_skipped); + } + } else { + /* output progress indicator: erase end of line and return to col 0 */ + fprintf(stderr, "%d/%d/%d\033[K\r", + test_failed, test_count, test_skipped); + } fflush(stderr); } - js_mutex_unlock(&progress_mutex); } -enum { INCLUDE, EXCLUDE, SKIP }; +static int slow_test_threshold; -int include_exclude_or_skip(int i) // naming is hard... +void run_test_dir_list(namelist_t *lp, int start_index, int stop_index) { - if (namelist_find(&exclude_list, test_list.array[i]) >= 0) - return EXCLUDE; - if (i < start_index) - return SKIP; - if (stop_index >= 0 && i > stop_index) - return SKIP; - return INCLUDE; -} - -void run_test_dir_list(void *arg) -{ - ThreadLocalStorage tls_s, *tls = &tls_s; - const char *p; - int i, msec; - - init_thread_local_storage(tls); + int i; - for (i = (uintptr_t)arg; i < test_list.count; i += nthreads) { - if (INCLUDE != include_exclude_or_skip(i)) - continue; - p = test_list.array[i]; - msec = 0; - run_test(tls, p, &msec); - if (verbose > 1 || (slow_test_threshold && msec >= slow_test_threshold)) - fprintf(stderr, "%s (%d ms)\n", p, msec); + namelist_sort(lp); + for (i = 0; i < lp->count; i++) { + const char *p = lp->array[i]; + if (namelist_find(&exclude_list, p) >= 0) { + test_excluded++; + } else if (test_index < start_index) { + test_skipped++; + } else if (stop_index >= 0 && test_index > stop_index) { + test_skipped++; + } else { + int ti; + if (slow_test_threshold != 0) { + ti = get_clock_ms(); + } else { + ti = 0; + } + run_test(p, test_index); + if (slow_test_threshold != 0) { + ti = get_clock_ms() - ti; + if (ti >= slow_test_threshold) + fprintf(stderr, "\n%s (%d ms)\n", p, ti); + } + show_progress(FALSE); + } + test_index++; } + show_progress(TRUE); } void help(void) { - printf("run-test262 version %s\n" + printf("run-test262 version " CONFIG_VERSION "\n" "usage: run-test262 [options] {-f file ... | [dir_list] [index range]}\n" "-h help\n" "-a run tests in strict and nostrict modes\n" "-m print memory usage summary\n" + "-n use new style harness\n" "-N run test prepared by test262-harness+eshost\n" "-s run tests in strict mode, skip @nostrict tests\n" "-E only run tests from the error file\n" + "-C use compact progress indicator\n" + "-t show timings\n" "-u update error file\n" "-v verbose: output error messages\n" - "-vv like -v but also print test name and running time\n" "-T duration display tests taking more than 'duration' ms\n" - "-t threads number of parallel threads; default: numcpus - 1\n" "-c file read configuration from 'file'\n" "-d dir run all test files in directory tree 'dir'\n" "-e file load the known errors from 'file'\n" "-f file execute single test from 'file'\n" - "-x file exclude tests listed in 'file'\n", - JS_GetVersion()); + "-r file set the report file name (default=none)\n" + "-x file exclude tests listed in 'file'\n"); exit(1); } @@ -2145,36 +2069,29 @@ char *get_opt_arg(const char *option, char *arg) int main(int argc, char **argv) { - ThreadLocalStorage tls_s, *tls = &tls_s; - int i, optind; - bool is_dir_list; - bool only_check_errors = false; + int optind, start_index, stop_index; + BOOL is_dir_list; + BOOL only_check_errors = FALSE; const char *filename; const char *ignore = ""; - bool is_test262_harness = false; - bool is_module = false; - bool enable_progress = true; + BOOL is_test262_harness = FALSE; + BOOL is_module = FALSE; + BOOL count_skipped_features = FALSE; + clock_t clocks; - js_std_set_worker_new_context_func(JS_NewCustomContext); - - init_thread_local_storage(tls); - js_mutex_init(&stats_mutex); - -#ifndef _WIN32 +#if !defined(_WIN32) + compact = !isatty(STDERR_FILENO); /* Date tests assume California local time */ setenv("TZ", "America/Los_Angeles", 1); #endif - // minus one to not (over)commit the system completely - nthreads = cpu_count() - 1; - optind = 1; while (optind < argc) { char *arg = argv[optind]; if (*arg != '-') break; optind++; - if (strstr("-c -d -e -x -f -E -T -t", arg)) + if (strstr("-c -d -e -x -f -r -E -T", arg)) optind++; if (strstr("-d -f", arg)) ignore = "testdir"; // run only the tests from -d or -f @@ -2183,7 +2100,7 @@ int main(int argc, char **argv) /* cannot use getopt because we want to pass the command line to the script */ optind = 1; - is_dir_list = true; + is_dir_list = TRUE; while (optind < argc) { char *arg = argv[optind]; if (*arg != '-') @@ -2193,14 +2110,20 @@ int main(int argc, char **argv) help(); } else if (str_equal(arg, "-m")) { dump_memory++; + } else if (str_equal(arg, "-n")) { + new_style++; } else if (str_equal(arg, "-s")) { test_mode = TEST_STRICT; } else if (str_equal(arg, "-a")) { test_mode = TEST_ALL; + } else if (str_equal(arg, "-t")) { + show_timings++; } else if (str_equal(arg, "-u")) { update_errors++; - } else if (arg == strstr(arg, "-v")) { - verbose += str_count(arg, "v"); + } else if (str_equal(arg, "-v")) { + verbose++; + } else if (str_equal(arg, "-C")) { + compact = 1; } else if (str_equal(arg, "-c")) { load_config(get_opt_arg(arg, argv[optind++]), ignore); } else if (str_equal(arg, "-d")) { @@ -2210,17 +2133,19 @@ int main(int argc, char **argv) } else if (str_equal(arg, "-x")) { namelist_load(&exclude_list, get_opt_arg(arg, argv[optind++])); } else if (str_equal(arg, "-f")) { - is_dir_list = false; + is_dir_list = FALSE; + } else if (str_equal(arg, "-r")) { + report_filename = get_opt_arg(arg, argv[optind++]); } else if (str_equal(arg, "-E")) { - only_check_errors = true; + only_check_errors = TRUE; } else if (str_equal(arg, "-T")) { slow_test_threshold = atoi(get_opt_arg(arg, argv[optind++])); - } else if (str_equal(arg, "-t")) { - nthreads = atoi(get_opt_arg(arg, argv[optind++])); } else if (str_equal(arg, "-N")) { - is_test262_harness = true; + is_test262_harness = TRUE; } else if (str_equal(arg, "--module")) { - is_module = true; + is_module = TRUE; + } else if (str_equal(arg, "--count_skipped_features")) { + count_skipped_features = TRUE; } else { fatal(1, "unknown option: %s", arg); break; @@ -2231,12 +2156,9 @@ int main(int argc, char **argv) help(); if (is_test262_harness) { - return run_test262_harness_test(tls, argv[optind], is_module); + return run_test262_harness_test(argv[optind], is_module); } - nthreads = max_int(nthreads, 1); - nthreads = min_int(nthreads, countof(threads)); - error_out = stdout; if (error_filename) { error_file = load_file(error_filename, NULL); @@ -2256,12 +2178,16 @@ int main(int argc, char **argv) update_exclude_dirs(); -#ifndef _WIN32 - if (!isatty(STDOUT_FILENO)) { - enable_progress = false; - } -#endif + clocks = clock(); + if (count_skipped_features) { + /* not storage efficient but it is simple */ + size_t size; + size = sizeof(harness_skip_features_count[0]) * strlen(harness_skip_features); + harness_skip_features_count = malloc(size); + memset(harness_skip_features_count, 0, size); + } + if (is_dir_list) { if (optind < argc && !isdigit((unsigned char)argv[optind][0])) { filename = argv[optind++]; @@ -2275,45 +2201,31 @@ int main(int argc, char **argv) stop_index = atoi(argv[optind++]); } } - // exclude_dir_list has already been sorted by update_exclude_dirs() - namelist_sort(&test_list); - namelist_sort(&exclude_list); - for (i = 0; i < test_list.count; i++) { - switch (include_exclude_or_skip(i)) { - case EXCLUDE: - test_excluded++; - break; - case SKIP: - test_skipped++; - break; + if (!report_filename || str_equal(report_filename, "none")) { + outfile = NULL; + } else if (str_equal(report_filename, "-")) { + outfile = stdout; + } else { + outfile = fopen(report_filename, "wb"); + if (!outfile) { + perror_exit(1, report_filename); } } - js_cond_init(&progress_cond); - js_mutex_init(&progress_mutex); - if (enable_progress) { - js_thread_create(&progress_thread, show_progress, NULL, /*flags*/0); - } - for (i = 0; i < nthreads; i++) { - js_thread_create(&threads[i], run_test_dir_list, - (void *)(uintptr_t)i, /*flags*/0); - } - for (i = 0; i < nthreads; i++) - js_thread_join(threads[i]); - js_mutex_lock(&progress_mutex); - js_cond_signal(&progress_cond); - js_mutex_unlock(&progress_mutex); - if (enable_progress) { - js_thread_join(progress_thread); + run_test_dir_list(&test_list, start_index, stop_index); + + if (outfile && outfile != stdout) { + fclose(outfile); + outfile = NULL; } - js_mutex_destroy(&progress_mutex); - js_cond_destroy(&progress_cond); } else { + outfile = stdout; while (optind < argc) { - int msec = 0; - run_test(tls, argv[optind++], &msec); + run_test(argv[optind++], -1); } } + clocks = clock() - clocks; + if (dump_memory) { if (dump_memory > 1 && stats_count > 1) { printf("\nMininum memory statistics for %s:\n\n", stats_min_filename); @@ -2326,6 +2238,30 @@ int main(int argc, char **argv) printf("\n"); } + if (count_skipped_features) { + size_t i, n, len = strlen(harness_skip_features); + BOOL disp = FALSE; + int c; + for(i = 0; i < len; i++) { + if (harness_skip_features_count[i] != 0) { + if (!disp) { + disp = TRUE; + printf("%-30s %7s\n", "SKIPPED FEATURE", "COUNT"); + } + for(n = 0; n < 30; n++) { + c = harness_skip_features[i + n]; + if (is_word_sep(c)) + break; + putchar(c); + } + for(; n < 30; n++) + putchar(' '); + printf(" %7d\n", harness_skip_features_count[i]); + } + } + printf("\n"); + } + if (is_dir_list) { fprintf(stderr, "Result: %d/%d error%s", test_failed, test_count, test_count != 1 ? "s" : ""); @@ -2342,6 +2278,8 @@ int main(int argc, char **argv) fprintf(stderr, ", %d fixed", fixed_errors); } fprintf(stderr, "\n"); + if (show_timings) + fprintf(stderr, "Total time: %.3fs\n", (double)clocks / CLOCKS_PER_SEC); } if (error_out && error_out != stdout) { @@ -2353,13 +2291,11 @@ int main(int argc, char **argv) namelist_free(&exclude_list); namelist_free(&exclude_dir_list); free(harness_dir); + free(harness_skip_features); + free(harness_skip_features_count); free(harness_features); free(harness_exclude); - free(harness_skip_features); free(error_file); - free(error_filename); - free(stats_min_filename); - free(stats_max_filename); /* Signal that the error file is out of date. */ return new_errors || changed_errors || fixed_errors; diff --git a/quickjs/test262.conf b/quickjs/test262.conf new file mode 100644 index 0000000..430843a --- /dev/null +++ b/quickjs/test262.conf @@ -0,0 +1,345 @@ +[config] +# general settings for test262 ES6 version + +# framework style: old, new +style=new + +# handle tests tagged as [noStrict]: yes, no, skip +nostrict=yes + +# handle tests tagged as [strictOnly]: yes, no, skip +strict=yes + +# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all +mode=default + +# handle tests flagged as [async]: yes, no, skip +# for these, load 'harness/doneprintHandle.js' prior to test +# and expect `print('Test262:AsyncTestComplete')` to be called for +# successful termination +async=yes + +# handle tests flagged as [module]: yes, no, skip +module=yes + +# output error messages: yes, no +verbose=yes + +# load harness files from this directory +harnessdir=test262/harness + +# names of harness include files to skip +#harnessexclude= + +# name of the error file for known errors +errorfile=test262_errors.txt + +# exclude tests enumerated in this file (see also [exclude] section) +#excludefile=test262_exclude.txt + +# report test results to this file +reportfile=test262_report.txt + +# enumerate tests from this directory +testdir=test262/test + +[features] +# Standard language features and proposed extensions +# list the features that are included +# skipped features are tagged as such to avoid warnings +# Keep this list alpha-sorted (:sort i in vim) + +__getter__ +__proto__ +__setter__ +AggregateError +align-detached-buffer-semantics-with-web-reality +arbitrary-module-namespace-names=skip +array-find-from-last +array-grouping +Array.fromAsync=skip +Array.prototype.at +Array.prototype.flat +Array.prototype.flatMap +Array.prototype.includes +Array.prototype.values +ArrayBuffer +arraybuffer-transfer +arrow-function +async-functions +async-iteration +Atomics +Atomics.pause +Atomics.waitAsync=skip +BigInt +caller +canonical-tz=skip +change-array-by-copy +class +class-fields-private +class-fields-private-in +class-fields-public +class-methods-private +class-static-block +class-static-fields-private +class-static-fields-public +class-static-methods-private +coalesce-expression +computed-property-names +const +cross-realm +DataView +DataView.prototype.getFloat32 +DataView.prototype.getFloat64 +DataView.prototype.getInt16 +DataView.prototype.getInt32 +DataView.prototype.getInt8 +DataView.prototype.getUint16 +DataView.prototype.getUint32 +DataView.prototype.setUint8 +decorators=skip +default-parameters +destructuring-assignment +destructuring-binding +dynamic-import +error-cause +Error.isError +explicit-resource-management=skip +exponentiation +export-star-as-namespace-from-module +FinalizationRegistry +Float16Array +Float32Array +Float64Array +for-in-order +for-of +generators +globalThis +hashbang +host-gc-required +immutable-arraybuffer=skip +import-attributes +import-defer=skip +import.meta +Int16Array +Int32Array +Int8Array +Intl-enumeration=skip +intl-normative-optional=skip +Intl.DateTimeFormat-datetimestyle=skip +Intl.DateTimeFormat-dayPeriod=skip +Intl.DateTimeFormat-extend-timezonename=skip +Intl.DateTimeFormat-formatRange=skip +Intl.DateTimeFormat-fractionalSecondDigits=skip +Intl.DisplayNames-v2=skip +Intl.DisplayNames=skip +Intl.DurationFormat=skip +Intl.ListFormat=skip +Intl.Locale-info=skip +Intl.Locale=skip +Intl.NumberFormat-unified=skip +Intl.NumberFormat-v3=skip +Intl.RelativeTimeFormat=skip +Intl.Segmenter=skip +IsHTMLDDA +iterator-helpers +iterator-sequencing=skip +json-modules +json-parse-with-source=skip +json-superset +legacy-regexp=skip +let +logical-assignment-operators +Map +Math.sumPrecise +new.target +nonextensible-applies-to-private=skip +numeric-separator-literal +object-rest +object-spread +Object.fromEntries +Object.hasOwn +Object.is +optional-catch-binding +optional-chaining +Promise +promise-try +promise-with-resolvers +Promise.allSettled +Promise.any +Promise.prototype.finally +Proxy +proxy-missing-checks +Reflect +Reflect.construct +Reflect.set +Reflect.setPrototypeOf +regexp-dotall +regexp-duplicate-named-groups=skip +regexp-lookbehind +regexp-match-indices +regexp-modifiers +regexp-named-groups +regexp-unicode-property-escapes +regexp-v-flag +RegExp.escape +resizable-arraybuffer +rest-parameters +Set +set-methods +ShadowRealm=skip +SharedArrayBuffer +source-phase-imports-module-source=skip +source-phase-imports=skip +stable-array-sort +stable-typedarray-sort +string-trimming +String.fromCodePoint +String.prototype.at +String.prototype.endsWith +String.prototype.includes +String.prototype.isWellFormed +String.prototype.matchAll +String.prototype.replaceAll +String.prototype.toWellFormed +String.prototype.trimEnd +String.prototype.trimStart +super +Symbol +Symbol.asyncIterator +Symbol.hasInstance +Symbol.isConcatSpreadable +Symbol.iterator +Symbol.match +Symbol.matchAll +Symbol.prototype.description +Symbol.replace +Symbol.search +Symbol.species +Symbol.split +Symbol.toPrimitive +Symbol.toStringTag +Symbol.unscopables +symbols-as-weakmap-keys +tail-call-optimization=skip +template +Temporal=skip +top-level-await +TypedArray +TypedArray.prototype.at +u180e +Uint16Array +Uint32Array +Uint8Array +uint8array-base64=skip +Uint8ClampedArray +upsert +WeakMap +WeakRef +WeakSet +well-formed-json-stringify + +[exclude] +# list excluded tests and directories here + +# intl not supported +test262/test/intl402/ + +# incompatible with the "caller" feature +test262/test/built-ins/Function/prototype/restricted-property-caller.js +test262/test/built-ins/Function/prototype/restricted-property-arguments.js +test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js + +# slow tests +#test262/test/built-ins/RegExp/CharacterClassEscapes/ +#test262/test/built-ins/RegExp/property-escapes/ + +# not yet in official specification +test262/test/built-ins/String/prototype/match/cstm-matcher-on-bigint-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-bigint-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-boolean-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-boolean-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-number-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-number-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-string-primitive.js +test262/test/built-ins/String/prototype/match/cstm-matcher-on-string-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-bigint-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-bigint-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-number-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-number-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-string-primitive.js +test262/test/built-ins/String/prototype/matchAll/cstm-matchall-on-string-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-bigint-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-bigint-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-boolean-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-boolean-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-number-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-number-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-string-primitive.js +test262/test/built-ins/String/prototype/replace/cstm-replace-on-string-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-bigint-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-bigint-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-boolean-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-boolean-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-number-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-number-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-string-primitive.js +test262/test/built-ins/String/prototype/replaceAll/cstm-replaceall-on-string-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-bigint-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-bigint-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-boolean-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-boolean-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-number-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-number-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-string-primitive.js +test262/test/built-ins/String/prototype/search/cstm-search-on-string-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-bigint-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-bigint-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-boolean-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-boolean-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-number-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-number-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-string-primitive.js +test262/test/built-ins/String/prototype/split/cstm-split-on-string-primitive.js + +#################################### +# staging tests + +# sort() does not modify the array and we don't update it (XXX: the +# spec updates it in this case) +test262/test/staging/sm/Array/frozen-dense-array.js + +# does not match spec +test262/test/staging/sm/Iterator/from/wrap-next-not-object-throws.js + +# not supported +test262/test/staging/sm/extensions/censor-strict-caller.js +test262/test/staging/sm/JSON/parse-with-source.js + +# not standard +test262/test/staging/sm/Function/builtin-no-construct.js +test262/test/staging/sm/Function/function-caller-restrictions.js +test262/test/staging/sm/Function/function-toString-builtin-name.js +test262/test/staging/sm/extensions/arguments-property-access-in-function.js +test262/test/staging/sm/extensions/function-caller-skips-eval-frames.js +test262/test/staging/sm/extensions/function-properties.js +test262/test/staging/sm/regress/regress-577648-1.js +test262/test/staging/sm/regress/regress-577648-2.js +test262/test/staging/sm/regress/regress-584355.js +test262/test/staging/sm/regress/regress-586482-1.js +test262/test/staging/sm/regress/regress-586482-2.js +test262/test/staging/sm/regress/regress-586482-3.js +test262/test/staging/sm/regress/regress-586482-4.js +test262/test/staging/sm/regress/regress-699682.js + +# RegExp toSource not fully compliant +test262/test/staging/sm/RegExp/toString.js +test262/test/staging/sm/RegExp/source.js +test262/test/staging/sm/RegExp/escape.js +# source directives are not standard yet +test262/test/staging/sm/syntax/syntax-parsed-arrow-then-directive.js +# returning "bound fn" as initialName for a function is permitted by the spec +test262/test/staging/sm/Function/function-toString-builtin.js + +[tests] +# list test files or use config.testdir diff --git a/quickjs/test262_errors.txt b/quickjs/test262_errors.txt new file mode 100644 index 0000000..ec3df0f --- /dev/null +++ b/quickjs/test262_errors.txt @@ -0,0 +1,61 @@ +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js:27: SyntaxError: invalid for in/of left hand-side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js:27: SyntaxError: invalid for in/of left hand-side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js:33: SyntaxError: invalid assignment left-hand side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js:27: SyntaxError: invalid increment/decrement operand +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand +test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side +test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side +test262/test/language/identifier-resolution/assign-to-global-undefined.js:20: strict mode: expected error +test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called +test262/test/staging/sm/Function/arguments-parameter-shadowing.js:14: Test262Error: Expected SameValue(«true», «false») to be true +test262/test/staging/sm/Function/constructor-binding.js:11: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true +test262/test/staging/sm/Function/constructor-binding.js:11: strict mode: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true +test262/test/staging/sm/Function/function-bind.js:24: Test262Error: Conforms to NativeFunction Syntax: "function bound unbound() {\n [native code]\n}" +test262/test/staging/sm/Function/function-name-for.js:13: Test262Error: Expected SameValue(«""», «"forInHead"») to be true +test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:12: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true +test262/test/staging/sm/Function/invalid-parameter-list.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/Function/invalid-parameter-list.js:13: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: Test262Error: Expected SameValue(«false», «true») to be true +test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: strict mode: Test262Error: Expected SameValue(«false», «true») to be true +test262/test/staging/sm/RegExp/regress-613820-1.js:12: Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same contents. +test262/test/staging/sm/RegExp/regress-613820-1.js:12: strict mode: Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same contents. +test262/test/staging/sm/RegExp/regress-613820-2.js:12: Test262Error: Actual [foobar, f, o, o, b, a, r] and expected [foobar, undefined, undefined, undefined, b, a, r] should have the same contents. +test262/test/staging/sm/RegExp/regress-613820-2.js:12: strict mode: Test262Error: Actual [foobar, f, o, o, b, a, r] and expected [foobar, undefined, undefined, undefined, b, a, r] should have the same contents. +test262/test/staging/sm/RegExp/regress-613820-3.js:12: Test262Error: Actual [aab, a, undefined, ab] and expected [aa, undefined, a, undefined] should have the same contents. +test262/test/staging/sm/RegExp/regress-613820-3.js:12: strict mode: Test262Error: Actual [aab, a, undefined, ab] and expected [aa, undefined, a, undefined] should have the same contents. +test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:29: Test262Error: Expected a ExpectedError but got a Error +test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:29: strict mode: Test262Error: Expected a ExpectedError but got a Error +test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: Test262Error: Expected SameValue(«2», «6») to be true +test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: strict mode: Test262Error: Expected SameValue(«2», «6») to be true +test262/test/staging/sm/TypedArray/sort_modifications.js:9: Test262Error: Int8Array at index 0 for size 4 Expected SameValue(«0», «1») to be true +test262/test/staging/sm/TypedArray/sort_modifications.js:9: strict mode: Test262Error: Int8Array at index 0 for size 4 Expected SameValue(«0», «1») to be true +test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:10: Test262Error: AsyncFunction:(a = (b = await/r/g) => {}) => {} Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:10: strict mode: Test262Error: AsyncFunction:(a = (b = await/r/g) => {}) => {} Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/class/boundFunctionSubclassing.js:9: Test262Error: Expected SameValue(«false», «true») to be true +test262/test/staging/sm/class/boundFunctionSubclassing.js:9: strict mode: Test262Error: Expected SameValue(«false», «true») to be true +test262/test/staging/sm/class/strictExecution.js:13: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/staging/sm/class/superPropOrdering.js:17: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/staging/sm/class/superPropOrdering.js:17: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/staging/sm/expressions/short-circuit-compound-assignment-const.js:96: TypeError: 'a' is read-only +test262/test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js:18: Test262Error: Expected a ReferenceError but got a TypeError +test262/test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js:18: strict mode: Test262Error: Expected a ReferenceError but got a TypeError +test262/test/staging/sm/generators/syntax.js:50: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-arguments.js:13: Test262Error: Expected SameValue(«"object"», «"function"») to be true +test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-eval.js:11: Test262Error: Expected SameValue(«"outer-gouter-geval-gtruefalseq"», «"outer-geval-gwith-gtruefalseq"») to be true +test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-if.js:19: TypeError: not a function +test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-notapplicable.js:14: Test262Error: Expected SameValue(«function x() {2}», «function x() {1}») to be true +test262/test/staging/sm/lexical-environment/block-scoped-functions-deprecated-redecl.js:23: Test262Error: Expected SameValue(«3», «4») to be true +test262/test/staging/sm/lexical-environment/var-in-catch-body-annex-b-eval.js:16: Test262Error: Expected SameValue(«"g"», «"global-x"») to be true +test262/test/staging/sm/object/defineProperties-order.js:11: Test262Error: Expected SameValue(«"ownKeys,getOwnPropertyDescriptor,getOwnPropertyDescriptor,get,get"», «"ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get"») to be true +test262/test/staging/sm/object/defineProperties-order.js:11: strict mode: Test262Error: Expected SameValue(«"ownKeys,getOwnPropertyDescriptor,getOwnPropertyDescriptor,get,get"», «"ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get"») to be true +test262/test/staging/sm/regress/regress-602621.js:13: Test262Error: function sub-statement must override arguments Expected SameValue(«"function"», «"object"») to be true +test262/test/staging/sm/regress/regress-1383630.js:28: Test262Error: proxy must report the same value for the non-writable, non-configurable property Expected a TypeError to be thrown but no exception was thrown at all +test262/test/staging/sm/regress/regress-1383630.js:28: strict mode: Test262Error: proxy must report the same value for the non-writable, non-configurable property Expected a TypeError to be thrown but no exception was thrown at all +test262/test/staging/sm/statements/arrow-function-in-for-statement-head.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/statements/arrow-function-in-for-statement-head.js:13: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all +test262/test/staging/sm/statements/regress-642975.js:11: Test262Error: Expected SameValue(«undefined», «"y"») to be true +test262/test/staging/sm/statements/regress-642975.js:11: strict mode: Test262Error: Expected SameValue(«undefined», «"y"») to be true +test262/test/staging/sm/statements/try-completion.js:11: Test262Error: Expected SameValue(«"try"», «undefined») to be true +test262/test/staging/sm/statements/try-completion.js:11: strict mode: Test262Error: Expected SameValue(«"try"», «undefined») to be true diff --git a/quickjs/test262o.conf b/quickjs/test262o.conf new file mode 100644 index 0000000..96f8667 --- /dev/null +++ b/quickjs/test262o.conf @@ -0,0 +1,413 @@ +[config] +# general settings for test262 ES5 version + +# framework style: old, new +style=old + +# handle tests tagged as @noStrict: yes, no, skip +nostrict=yes + +# handle tests tagged as @strictOnly: yes, no, skip +strict=yes + +# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all +mode=default + +# output error messages: yes, no +verbose=yes + +# load harness files this directory +harnessdir=test262o/test/harness + +# name of the error file for known errors +errorfile=test262o_errors.txt + +# exclude tests enumerated in this file +#excludefile=test262o_excluded.txt + +# report test results to this file +reportfile=test262o_report.txt + +# enumerate tests from this directory +testdir=test262o/test/suite + +[exclude] +# list excluded tests and directories here + +# intl not supported +test262o/test/suite/intl402/ + +# ES6 != ES5: block scoped function definitions allowed in strict mode +test262o/test/suite/bestPractice/Sbp_A1_T1.js +test262o/test/suite/bestPractice/Sbp_A2_T1.js +test262o/test/suite/bestPractice/Sbp_A2_T2.js +test262o/test/suite/bestPractice/Sbp_A3_T1.js +test262o/test/suite/bestPractice/Sbp_A3_T2.js +test262o/test/suite/bestPractice/Sbp_A4_T1.js +test262o/test/suite/bestPractice/Sbp_A4_T2.js +test262o/test/suite/bestPractice/Sbp_A5_T2.js + +# ES6 != ES5: `y={x};` is shorthand for `y={x:x}` +test262o/test/suite/ch12/12.1/S12.1_A4_T2.js +test262o/test/suite/ch12/12.6/12.6.4/S12.6.4_A15.js + +# ES6 != ES5: function length property is configurable +test262o/test/suite/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js +test262o/test/suite/ch13/13.2/13.2-15-1.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2.js +test262o/test/suite/ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2.js +test262o/test/suite/ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2.js +test262o/test/suite/ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2.js +test262o/test/suite/ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9.js +test262o/test/suite/ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9.js +test262o/test/suite/ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-15-2.js +test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T1.js +test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T2.js +test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T3.js +test262o/test/suite/ch15/15.4/15.4.3/S15.4.3_A2.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9.js +test262o/test/suite/ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2.js +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2.js +test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9.js +test262o/test/suite/ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9.js +test262o/test/suite/ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9.js + +# ES6 != ES5: object literals may have duplicates +test262o/test/suite/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js +test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js + +# ES6 != ES5: Date.prototype is no longer an instance of Date +test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/15.9.5.40_1.js + +# ES6 != ES5: Object.getPrototypeOf converts argument to object +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1.js + +# ES6 != ES5: Object.getPrototypeOf(NativeError) +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-12.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-13.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-14.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-15.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-16.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-17.js + +# ES6 != ES5: Object.getOwnPropertyDescriptor converts argument to object +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1.js + +# ES6 != ES5: Object.getOwnPropertyNames converts argument to object +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1.js + +# ES6 != ES5: Object.seal accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1.js + +# ES6 != ES5: Object.freeze accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1.js + +# ES6 != ES5: Object.preventExtensions accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1.js + +# ES6 != ES5: Object.isSealed accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.11/15.2.3.11-1.js + +# ES6 != ES5: Object.isFrozen accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1.js + +# ES6 != ES5: Object.isExtensible accepts all types +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-3.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-4.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1.js + +# ES6 != ES5: Object.keys converts argument to object +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3.js + +# ES6 != ES5: source and other properties of RegExp.prototype are not own properties +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214.js +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215.js + +# ES6 != ES5: String numeric object properties are enumerated first +test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-44.js + +# ES6: new RegExp(regex, flags) is valid +test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js +test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T2.js +test262o/test/suite/ch15/15.10/15.10.4/15.10.4.1/15.10.4.1-1.js +test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T1.js +test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T2.js + +# ES6 != ES5: RegExp.prototype.test behavior +test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A5_T3.js + +# ES6 != ES5: source, global, ignoreCase, multiline, lastIndex are not data properties +# of RegExp objects and RegExp.prototype is not a RegExp object +test262o/test/suite/ch15/15.10/15.10.6/15.10.6.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-2.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A8.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A9.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A10.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-1.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-2.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A8.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A9.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A10.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-1.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-2.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A8.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A9.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A10.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-1.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-2.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A8.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A9.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A10.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-1.js +test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-2.js + +# ES6 != ES5: Error.prototype is a normal object +test262o/test/suite/ch15/15.11/15.11.4/S15.11.4_A2.js + +# ES6 different ToLength() semantics +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A4_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A2_T2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T1.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A2_T2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T1.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A3_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A3_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T1.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A4_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T1.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T3.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A3_T2.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-8.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-28.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-29.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-28.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-8.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-29.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-8.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-28.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-29.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-8.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-28.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-29.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-25.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-7.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-12.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-25.js + +# ES6 different ToLength() semantics causes near infinite runtime +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-14.js +test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-14.js + +# ES6 arguments/caller changes +test262o/test/suite/ch10/10.6/10.6-13-b-1-s.js +test262o/test/suite/ch10/10.6/10.6-13-b-2-s.js +test262o/test/suite/ch10/10.6/10.6-13-b-3-s.js +test262o/test/suite/ch10/10.6/10.6-14-1-s.js +test262o/test/suite/ch10/10.6/10.6-14-b-1-s.js +test262o/test/suite/ch10/10.6/10.6-14-b-4-s.js +test262o/test/suite/ch13/13.2/13.2-29-s.js +test262o/test/suite/ch13/13.2/13.2-30-s.js +test262o/test/suite/ch13/13.2/13.2-31-s.js +test262o/test/suite/ch13/13.2/13.2-32-s.js +test262o/test/suite/ch13/13.2/13.2-33-s.js +test262o/test/suite/ch13/13.2/13.2-34-s.js +test262o/test/suite/ch13/13.2/13.2-35-s.js +test262o/test/suite/ch13/13.2/13.2-36-s.js +test262o/test/suite/ch13/13.2/S13.2.3_A1.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-1.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-4.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-5.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-1.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-4.js +test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-5.js + +# u180e is no longer considered as a space +test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A2.js +test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T1.js +test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T2.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A2_T10.js +test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A2_T10.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-2.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-3.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-4.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-5.js +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-6.js +test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A1_T1.js +test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A2_T1.js + +# E6 eval return value is different +test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.js +test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.1.js + +# ECMA 2019 optional-catch-binding feature allows try{}catch{} +test262o/test/suite/ch12/12.14/S12.14_A16_T4.js + +# Syntax error instead of ReferenceError in ES2020 +test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-1.js +test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-2.js +test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-3.js +test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-4.js + +# String.prototype.localeCompare special cases +test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/15.5.4.9_CE.js + +[tests] +# list test files or use config.testdir diff --git a/quickjs-ng/docs/static/.nojekyll b/quickjs/test262o_errors.txt similarity index 100% rename from quickjs-ng/docs/static/.nojekyll rename to quickjs/test262o_errors.txt diff --git a/quickjs-ng/tests/assert.js b/quickjs/tests/assert.js similarity index 79% rename from quickjs-ng/tests/assert.js rename to quickjs/tests/assert.js index c8240c8..42369ed 100644 --- a/quickjs-ng/tests/assert.js +++ b/quickjs/tests/assert.js @@ -3,14 +3,8 @@ export function assert(actual, expected, message) { expected = true; if (typeof actual === typeof expected) { - if (actual === expected) { - if (actual !== 0 || (1 / actual) === (1 / expected)) - return; - } - if (typeof actual === 'number') { - if (isNaN(actual) && isNaN(expected)) - return; - } + if (Object.is(actual, expected)) + return; if (typeof actual === 'object') { if (actual !== null && expected !== null && actual.constructor === expected.constructor diff --git a/quickjs/tests/bjson.c b/quickjs/tests/bjson.c new file mode 100644 index 0000000..78b1375 --- /dev/null +++ b/quickjs/tests/bjson.c @@ -0,0 +1,96 @@ +/* + * QuickJS: binary JSON module (test only) + * + * Copyright (c) 2017-2019 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "../quickjs-libc.h" +#include "../cutils.h" + +static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + uint8_t *buf; + uint64_t pos, len; + JSValue obj; + size_t size; + int flags; + + if (JS_ToIndex(ctx, &pos, argv[1])) + return JS_EXCEPTION; + if (JS_ToIndex(ctx, &len, argv[2])) + return JS_EXCEPTION; + buf = JS_GetArrayBuffer(ctx, &size, argv[0]); + if (!buf) + return JS_EXCEPTION; + if (pos + len > size) + return JS_ThrowRangeError(ctx, "array buffer overflow"); + flags = 0; + if (JS_ToBool(ctx, argv[3])) + flags |= JS_READ_OBJ_REFERENCE; + obj = JS_ReadObject(ctx, buf + pos, len, flags); + return obj; +} + +static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + size_t len; + uint8_t *buf; + JSValue array; + int flags; + + flags = 0; + if (JS_ToBool(ctx, argv[1])) + flags |= JS_WRITE_OBJ_REFERENCE; + buf = JS_WriteObject(ctx, &len, argv[0], flags); + if (!buf) + return JS_EXCEPTION; + array = JS_NewArrayBufferCopy(ctx, buf, len); + js_free(ctx, buf); + return array; +} + +static const JSCFunctionListEntry js_bjson_funcs[] = { + JS_CFUNC_DEF("read", 4, js_bjson_read ), + JS_CFUNC_DEF("write", 2, js_bjson_write ), +}; + +static int js_bjson_init(JSContext *ctx, JSModuleDef *m) +{ + return JS_SetModuleExportList(ctx, m, js_bjson_funcs, + countof(js_bjson_funcs)); +} + +#ifdef JS_SHARED_LIBRARY +#define JS_INIT_MODULE js_init_module +#else +#define JS_INIT_MODULE js_init_module_bjson +#endif + +JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, js_bjson_init); + if (!m) + return NULL; + JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); + return m; +} diff --git a/quickjs-ng/tests/fixture_cyclic_import.js b/quickjs/tests/fixture_cyclic_import.js similarity index 100% rename from quickjs-ng/tests/fixture_cyclic_import.js rename to quickjs/tests/fixture_cyclic_import.js diff --git a/quickjs-ng/tests/microbench.js b/quickjs/tests/microbench.js similarity index 67% rename from quickjs-ng/tests/microbench.js rename to quickjs/tests/microbench.js index 445c6c0..9000f36 100644 --- a/quickjs-ng/tests/microbench.js +++ b/quickjs/tests/microbench.js @@ -22,8 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import * as std from "qjs:std"; -import * as os from "qjs:os"; + +if (typeof require !== 'undefined') { + var fs = require('fs'); +} function pad(str, n) { str += ""; @@ -50,32 +52,16 @@ function pad_center(str, n) { return str; } -function toPrec(n, prec) { - var i, s; - for (i = 0; i < prec; i++) - n *= 10; - s = "" + Math.round(n); - for (i = s.length - prec; i <= 0; i++) - s = "0" + s; - if (prec > 0) - s = s.substring(0, i) + "." + s.substring(i); - return s; -} - var ref_data; var log_data; -var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (%)" ]; +var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (1000)" ]; var widths = [ 22, 10, 9, 9, 9 ]; -var precs = [ 0, 0, 2, 2, 2 ]; +var precs = [ 0, 0, 2, 2, 0 ]; var total = [ 0, 0, 0, 0, 0 ]; var total_score = 0; var total_scale = 0; -if (typeof console == "undefined") { - var console = { log: print }; -} - function log_line() { var i, n, s, a; s = ""; @@ -83,9 +69,9 @@ function log_line() { if (i > 0) s += " "; a = arguments[i]; - if (typeof a == "number") { + if (typeof a === "number") { total[i] += a; - a = toPrec(a, precs[i]); + a = a.toFixed(precs[i]); s += pad_left(a, widths[i]); } else { s += pad_left(a, widths[i]); @@ -94,11 +80,29 @@ function log_line() { console.log(s); } -var clocks_per_sec = 1000000; +var clocks_per_sec = 1000; var max_iterations = 100; -var clock_threshold = 2000; /* favoring short measuring spans */ +var clock_threshold = 2; /* favoring short measuring spans */ var min_n_argument = 1; -var get_clock = os.cputime ?? os.now; +var get_clock; +if (typeof performance !== "undefined") { + // use more precise clock on NodeJS + // need a method call on performance object + get_clock = () => performance.now(); +} else +if (typeof os !== "undefined") { + // use more precise clock on QuickJS + get_clock = os.now; +} else { + // use Date.now and round up to the next millisecond + get_clock = () => { + var t0 = Date.now(); + var t; + while ((t = Date.now()) == t0) + continue; + return t; + } +} function log_one(text, n, ti) { var ref; @@ -111,7 +115,7 @@ function log_one(text, n, ti) { ti = Math.round(ti * 100) / 100; log_data[text] = ti; if (typeof ref === "number") { - log_line(text, n, ti, ref, ti * 100 / ref); + log_line(text, n, ti, ref, Math.round(ref * 1000 / ti)); total_score += ti * 100 / ref; total_scale += 100; } else { @@ -123,28 +127,27 @@ function log_one(text, n, ti) { function bench(f, text) { - var i, j, n, t, t1, ti, nb_its, ref, ti_n, ti_n1, min_ti; + var i, j, n, t, ti, nb_its, ref, ti_n, ti_n1; nb_its = n = 1; if (f.bench) { ti_n = f(text); } else { + // measure ti_n: the shortest time for an individual operation ti_n = 1000000000; - min_ti = clock_threshold / 10; for(i = 0; i < 30; i++) { + // measure ti: the shortest time for max_iterations iterations ti = 1000000000; for (j = 0; j < max_iterations; j++) { t = get_clock(); - while ((t1 = get_clock()) == t) - continue; nb_its = f(n); + t = get_clock() - t; if (nb_its < 0) return; // test failure - t1 = get_clock() - t1; - if (ti > t1) - ti = t1; + if (ti > t) + ti = t; } - if (ti >= min_ti) { + if (ti >= clock_threshold / 10) { ti_n1 = ti / nb_its; if (ti_n > ti_n1) ti_n = ti_n1; @@ -170,6 +173,26 @@ function empty_loop(n) { return n; } +function empty_down_loop(n) { + var j; + for(j = n; j > 0; j--) { + } + return n; +} + +function empty_down_loop2(n) { + var j; + for(j = n; j --> 0;) { + } + return n; +} + +function empty_do_loop(n) { + var j = n; + do { } while (--j > 0); + return n; +} + function date_now(n) { var j; for(j = 0; j < n; j++) { @@ -178,6 +201,32 @@ function date_now(n) { return n; } +function date_parse(n) { + var x0 = 0, dx = 0; + var j; + for(j = 0; j < n; j++) { + var x1 = x0 - x0 % 1000; + var x2 = -x0; + var x3 = -x1; + var d0 = new Date(x0); + var d1 = new Date(x1); + var d2 = new Date(x2); + var d3 = new Date(x3); + if (Date.parse(d0.toISOString()) != x0 + || Date.parse(d1.toGMTString()) != x1 + || Date.parse(d1.toString()) != x1 + || Date.parse(d2.toISOString()) != x2 + || Date.parse(d3.toGMTString()) != x3 + || Date.parse(d3.toString()) != x3) { + console.log("Date.parse error for " + x0); + return -1; + } + dx = (dx * 1.1 + 1) >> 0; + x0 = (x0 + dx) % 8.64e15; + } + return n * 6; +} + function prop_read(n) { var obj, sum, j; @@ -206,30 +255,78 @@ function prop_write(n) return n * 4; } -function prop_create(n) +function prop_update(n) { var obj, j; + obj = {a: 1, b: 2, c:3, d:4 }; + for(j = 0; j < n; j++) { + obj.a += j; + obj.b += j; + obj.c += j; + obj.d += j; + } + return n * 4; +} + +function prop_create(n) +{ + var obj, i, j; for(j = 0; j < n; j++) { - obj = new Object(); + obj = {}; obj.a = 1; obj.b = 2; obj.c = 3; obj.d = 4; + obj.e = 5; + obj.f = 6; + obj.g = 7; + obj.h = 8; + obj.i = 9; + obj.j = 10; + for(i = 0; i < 10; i++) { + obj[i] = i; + } } - return n * 4; + return n * 20; } -function prop_delete(n) +function prop_clone(n) { - var obj, j; - obj = {}; - for(j = 0; j < n; j++) { - obj[j] = 1; + var ref, obj, j, k; + ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; + for(k = 0; k < 10; k++) { + ref[k] = k; } - for(j = 0; j < n; j++) { - delete obj[j]; + for (j = 0; j < n; j++) { + global_res = { ...ref }; } - return n; + return n * 20; +} + +function prop_delete(n) +{ + var ref, obj, j, k; + ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; + for(k = 0; k < 10; k++) { + ref[k] = k; + } + for (j = 0; j < n; j++) { + obj = { ...ref }; + delete obj.a; + delete obj.b; + delete obj.c; + delete obj.d; + delete obj.e; + delete obj.f; + delete obj.g; + delete obj.h; + delete obj.i; + delete obj.j; + for(k = 0; k < 10; k++) { + delete obj[k]; + } + } + return n * 20; } function array_read(n) @@ -278,6 +375,28 @@ function array_write(n) return len * n; } +function array_update(n) +{ + var tab, len, i, j; + tab = []; + len = 10; + for(i = 0; i < len; i++) + tab[i] = i; + for(j = 0; j < n; j++) { + tab[0] += j; + tab[1] += j; + tab[2] += j; + tab[3] += j; + tab[4] += j; + tab[5] += j; + tab[6] += j; + tab[7] += j; + tab[8] += j; + tab[9] += j; + } + return len * n; +} + function array_prop_create(n) { var tab, i, j, len; @@ -290,15 +409,32 @@ function array_prop_create(n) return len * n; } +function array_slice(n) +{ + var ref, a, i, j, len; + len = 1000; + ref = []; + for(i = 0; i < len; i++) + ref[i] = i; + for(j = 0; j < n; j++) { + ref[0] = j; + a = ref.slice(); + a[0] = 0; + global_res = a; + } + return len * n; +} + function array_length_decr(n) { - var tab, i, j, len; + var tab, ref, i, j, len; len = 1000; - tab = []; + ref = []; for(i = 0; i < len; i++) - tab[i] = i; + ref[i] = i; for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) + tab = ref.slice(); + for(i = len; i --> 0;) tab.length = i; } return len * n; @@ -306,15 +442,16 @@ function array_length_decr(n) function array_hole_length_decr(n) { - var tab, i, j, len; + var tab, ref, i, j, len; len = 1000; - tab = []; + ref = []; for(i = 0; i < len; i++) { - if (i != 3) - tab[i] = i; + if (i % 10 == 9) + ref[i] = i; } for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) + tab = ref.slice(); + for(i = len; i --> 0;) tab.length = i; } return len * n; @@ -334,12 +471,13 @@ function array_push(n) function array_pop(n) { - var tab, i, j, len, sum; + var tab, ref, i, j, len, sum; len = 500; + ref = []; + for(i = 0; i < len; i++) + ref[i] = i; for(j = 0; j < n; j++) { - tab = []; - for(i = 0; i < len; i++) - tab[i] = i; + tab = ref.slice(); sum = 0; for(i = 0; i < len; i++) sum += tab.pop(); @@ -411,21 +549,21 @@ function global_read(n) return n * 4; } -var global_write = - (1, eval)(`(function global_write(n) - { - var j; - for(j = 0; j < n; j++) { - global_var0 = j; - global_var0 = j; - global_var0 = j; - global_var0 = j; - } - return n * 4; - })`); +function global_write(n) +{ + var j; + for(j = 0; j < n; j++) { + global_var0 = j; + global_var0 = j; + global_var0 = j; + global_var0 = j; + } + return n * 4; +} function global_write_strict(n) { + "use strict"; var j; for(j = 0; j < n; j++) { global_var0 = j; @@ -453,22 +591,22 @@ function local_destruct(n) var global_v1, global_v2, global_v3, global_v4; var global_a, global_b, global_c, global_d; -var global_destruct = - (1, eval)(`(function global_destruct(n) - { - var j, v1, v2, v3, v4; - var array = [ 1, 2, 3, 4, 5 ]; - var o = { a:1, b:2, c:3, d:4 }; - var a, b, c, d; - for(j = 0; j < n; j++) { - [ global_v1, global_v2,, global_v3, ...global_v4] = array; - ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); - } - return n * 8; - })`); +function global_destruct(n) +{ + var j, v1, v2, v3, v4; + var array = [ 1, 2, 3, 4, 5 ]; + var o = { a:1, b:2, c:3, d:4 }; + var a, b, c, d; + for(j = 0; j < n; j++) { + [ global_v1, global_v2,, global_v3, ...global_v4] = array; + ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); + } + return n * 8; +} function global_destruct_strict(n) { + "use strict"; var j, v1, v2, v3, v4; var array = [ 1, 2, 3, 4, 5 ]; var o = { a:1, b:2, c:3, d:4 }; @@ -480,6 +618,25 @@ function global_destruct_strict(n) return n * 8; } +function g(a) +{ + return 1; +} + +function global_func_call(n) +{ + var j, sum; + sum = 0; + for(j = 0; j < n; j++) { + sum += g(j); + sum += g(j); + sum += g(j); + sum += g(j); + } + global_res = sum; + return n * 4; +} + function func_call(n) { function f(a) @@ -499,7 +656,7 @@ function func_call(n) return n * 4; } -function closure_var(n) +function func_closure_call(n) { function f(a) { @@ -568,6 +725,11 @@ function bigint_arith(n, bits) return n * 1000; } +function bigint32_arith(n) +{ + return bigint_arith(n, 32); +} + function bigint64_arith(n) { return bigint_arith(n, 64); @@ -578,9 +740,9 @@ function bigint256_arith(n) return bigint_arith(n, 256); } -function map_set(n) +function map_set_string(n) { - var s, i, j, len = 100; + var s, i, j, len = 1000; for(j = 0; j < n; j++) { s = new Map(); for(i = 0; i < len; i++) { @@ -594,9 +756,41 @@ function map_set(n) return n * len; } +function map_set_int(n) +{ + var s, i, j, len = 1000; + for(j = 0; j < n; j++) { + s = new Map(); + for(i = 0; i < len; i++) { + s.set(i, i); + } + for(i = 0; i < len; i++) { + if (!s.has(i)) + throw Error("bug in Map"); + } + } + return n * len; +} + +function map_set_bigint(n) +{ + var s, i, j, len = 1000; + for(j = 0; j < n; j++) { + s = new Map(); + for(i = 0; i < len; i++) { + s.set(BigInt(i), i); + } + for(i = 0; i < len; i++) { + if (!s.has(BigInt(i))) + throw Error("bug in Map"); + } + } + return n * len; +} + function map_delete(n) { - var a, i, j, len; + var a, i, j; len = 1000; for(j = 0; j < n; j++) { @@ -613,7 +807,7 @@ function map_delete(n) function weak_map_set(n) { - var a, i, j, len, tab; + var a, i, j, tab; len = 1000; tab = []; @@ -631,7 +825,7 @@ function weak_map_set(n) function weak_map_delete(n) { - var a, i, j, len, tab; + var a, i, j, tab; len = 1000; for(j = 0; j < n; j++) { @@ -650,27 +844,28 @@ function weak_map_delete(n) return len * n; } + function array_for(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; - for(i = 0; i < 100; i++) { + for(i = 0; i < len; i++) { sum += r[i]; } global_res = sum; } - return n * 100; + return n * len; } function array_for_in(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; @@ -679,14 +874,14 @@ function array_for_in(n) } global_res = sum; } - return n * 100; + return n * len; } function array_for_of(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; @@ -695,7 +890,7 @@ function array_for_of(n) } global_res = sum; } - return n * 100; + return n * len; } function math_min(n) @@ -710,25 +905,16 @@ function math_min(n) return n * 1000; } -function object_null(n) -{ - var j; - for(j = 0; j < n; j++) { - global_res = {__proto__: null}; - } - return n; -} - function regexp_ascii(n) { var i, j, r, s; s = "the quick brown fox jumped over the lazy dog" for(j = 0; j < n; j++) { - for(i = 0; i < 10000; i++) + for(i = 0; i < 1000; i++) r = /the quick brown fox/.exec(s) global_res = r; } - return n * 10000; + return n * 1000; } function regexp_utf16(n) @@ -736,98 +922,117 @@ function regexp_utf16(n) var i, j, r, s; s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" for(j = 0; j < n; j++) { - for(i = 0; i < 10000; i++) + for(i = 0; i < 1000; i++) r = /the quick brown ᶠᵒˣ/.exec(s) global_res = r; } - return n * 10000; + return n * 1000; } /* incremental string contruction as local var */ function string_build1(n) { var i, j, r; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r += "x"; global_res = r; } - return n * 100; + return n * 1000; +} + +/* incremental string contruction using + */ +function string_build1x(n) +{ + var i, j, r; + for(j = 0; j < n; j++) { + r = ""; + for(i = 0; i < 1000; i++) + r = r + "x"; + global_res = r; + } + return n * 1000; +} + +/* incremental string contruction using +2c */ +function string_build2c(n) +{ + var i, j; + for(j = 0; j < n; j++) { + var r = ""; + for(i = 0; i < 1000; i++) + r += "xy"; + global_res = r; + } + return n * 1000; } /* incremental string contruction as arg */ function string_build2(n, r) { var i, j; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r += "x"; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction by prepending */ -function string_build3(n, r) +function string_build3(n) { - var i, j; - r = ""; + var i, j, r; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r = "x" + r; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction with multiple reference */ function string_build4(n) { var i, j, r, s; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) { + r = ""; + for(i = 0; i < 1000; i++) { s = r; r += "x"; } global_res = r; } - return n * 100; -} - -function string_slice1(n) -{ - var i, j, s; - s = "x".repeat(1<<16); - for (i = 0; i < n; i++) { - for (j = 0; j < 1000; j++) - s.slice(-1); // too short for JSStringSlice - } return n * 1000; } -function string_slice2(n) +/* append */ +function string_build_large1(n) { - var i, j, s; - s = "x".repeat(1<<16); - for (i = 0; i < n; i++) { - for (j = 0; j < 1000; j++) - s.slice(-1024); + var i, j, r, len = 20000; + for(j = 0; j < n; j++) { + r = ""; + for(i = 0; i < len; i++) + r += "abcdef"; + global_res = r; } - return n * 1000; + return n * len; } -function string_slice3(n) +/* prepend */ +function string_build_large2(n) { - var i, j, s; - s = "x".repeat(1<<16); - for (i = 0; i < n; i++) { - for (j = 0; j < 1000; j++) - s.slice(1); + var i, j, r, len = 20000; + for(j = 0; j < n; j++) { + r = ""; + for(i = 0; i < len; i++) + r = "abcdef" + r; + global_res = r; } - return n * 1000; + return n * len; } /* sort bench */ @@ -960,15 +1165,26 @@ function sort_bench(text) { ": " + arr[i - 1] + " > " + arr[i]); } if (sort_bench.verbose) - log_one("sort_" + f.name, n, ti, n * 100); + log_one("sort_" + f.name, 1, ti / 100); } total_score = save_total_score; total_scale = save_total_scale; - return total / n / 1000; + return total / n / 100; } sort_bench.bench = true; sort_bench.verbose = false; +function int_to_string(n) +{ + var s, j; + for(j = 0; j < n; j++) { + s = (j % 1000).toString(); + s = (1234000 + j % 1000).toString(); + } + global_res = s; + return n * 2; +} + function int_to_string(n) { var s, r, j; @@ -1058,7 +1274,6 @@ function string_to_int(n) var s, r, j; r = 0; s = "12345"; - r = 0; for(j = 0; j < n; j++) { r += (s | 0); } @@ -1071,7 +1286,6 @@ function string_to_float(n) var s, r, j; r = 0; s = "12345.6"; - r = 0; for(j = 0; j < n; j++) { r -= s; } @@ -1081,41 +1295,93 @@ function string_to_float(n) function load_result(filename) { - var f, str, res; - if (typeof std === "undefined") + var has_filename = filename; + var has_error = false; + var str, res; + + if (!filename) + filename = "microbench.txt"; + + if (typeof fs !== "undefined") { + // read the file in Node.js + try { + str = fs.readFileSync(filename, { encoding: "utf8" }); + } catch { + has_error = true; + } + } else + if (typeof std !== "undefined") { + // read the file in QuickJS + var f = std.open(filename, "r"); + if (f) { + str = f.readAsString(); + f.close(); + } else { + has_error = true; + } + } else { return null; - f = std.open(filename, "r"); - if (!f) + } + if (has_error) { + if (has_filename) { + // Should throw exception? + console.log("cannot load " + filename); + } return null; - str = f.readAsString(); + } res = JSON.parse(str); - f.close(); return res; } function save_result(filename, obj) { - var f; - if (typeof std === "undefined") + var str = JSON.stringify(obj, null, 2) + "\n"; + var has_error = false; + + if (typeof fs !== "undefined") { + // save the file in Node.js + try { + str = fs.writeFileSync(filename, str, { encoding: "utf8" }); + } catch { + has_error = true; + } + } else + if (typeof std !== "undefined") { + // save the file in QuickJS + var f = std.open(filename, "w"); + if (f) { + f.puts(str); + f.close(); + } else { + has_error = 'true'; + } + } else { return; - f = std.open(filename, "w"); - f.puts(JSON.stringify(obj, null, 2)); - f.puts("\n"); - f.close(); + } + if (has_error) + console.log("cannot save " + filename); } function main(argc, argv, g) { var test_list = [ empty_loop, + empty_down_loop, + empty_down_loop2, + empty_do_loop, date_now, + date_parse, prop_read, prop_write, + prop_update, prop_create, + prop_clone, prop_delete, array_read, array_write, + array_update, array_prop_create, + array_slice, array_length_decr, array_hole_length_decr, array_push, @@ -1128,11 +1394,14 @@ function main(argc, argv, g) local_destruct, global_destruct, global_destruct_strict, + global_func_call, func_call, - closure_var, + func_closure_call, int_arith, float_arith, - map_set, + map_set_string, + map_set_int, + map_set_bigint, map_delete, weak_map_set, weak_map_delete, @@ -1140,17 +1409,16 @@ function main(argc, argv, g) array_for_in, array_for_of, math_min, - object_null, regexp_ascii, regexp_utf16, string_build1, + string_build1x, + string_build2c, string_build2, - //string_build3, - //string_build4, - string_slice1, - string_slice2, - string_slice3, - sort_bench, + string_build3, + string_build4, + string_build_large1, + string_build_large2, int_to_string, int_toString, float_to_string, @@ -1163,12 +1431,15 @@ function main(argc, argv, g) ]; var tests = []; var i, j, n, f, name, found; + var ref_file, new_ref_file = "microbench-new.txt"; - if (typeof BigInt == "function") { + if (typeof BigInt === "function") { /* BigInt test */ + test_list.push(bigint32_arith); test_list.push(bigint64_arith); test_list.push(bigint256_arith); } + test_list.push(sort_bench); for (i = 1; i < argc;) { name = argv[i++]; @@ -1179,7 +1450,7 @@ function main(argc, argv, g) if (name == "-t") { name = argv[i++]; sort_bench.array_type = g[name]; - if (typeof sort_bench.array_type != "function") { + if (typeof sort_bench.array_type !== "function") { console.log("unknown array type: " + name); return 1; } @@ -1189,6 +1460,14 @@ function main(argc, argv, g) sort_bench.array_size = +argv[i++]; continue; } + if (name == "-r") { + ref_file = argv[i++]; + continue; + } + if (name == "-s") { + new_ref_file = argv[i++]; + continue; + } for (j = 0, found = false; j < test_list.length; j++) { f = test_list[j]; if (f.name.startsWith(name)) { @@ -1204,7 +1483,7 @@ function main(argc, argv, g) if (tests.length == 0) tests = test_list; - ref_data = load_result("microbench.txt"); + ref_data = load_result(ref_file); log_data = {}; log_line.apply(null, heads); n = 0; @@ -1216,12 +1495,12 @@ function main(argc, argv, g) n++; } if (ref_data) - log_line("total", "", total[2], total[3], total_score * 100 / total_scale); + log_line("total", "", total[2], total[3], Math.round(total_scale * 1000 / total_score)); else log_line("total", "", total[2]); - if (tests == test_list) - save_result("microbench-new.txt", log_data); + if (tests == test_list && new_ref_file) + save_result(new_ref_file, log_data); } if (typeof scriptArgs === "undefined") { diff --git a/quickjs/tests/test262.patch b/quickjs/tests/test262.patch new file mode 100644 index 0000000..d7cba88 --- /dev/null +++ b/quickjs/tests/test262.patch @@ -0,0 +1,72 @@ +diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js +index 9828b15..9e24d64 100644 +--- a/harness/atomicsHelper.js ++++ b/harness/atomicsHelper.js +@@ -272,10 +272,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { + * } + */ + $262.agent.timeouts = { +- yield: 100, +- small: 200, +- long: 1000, +- huge: 10000, ++// yield: 100, ++// small: 200, ++// long: 1000, ++// huge: 10000, ++ yield: 40, ++ small: 40, ++ long: 200, ++ huge: 1000, + }; + + /** +diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js +index b397be0..c197ddc 100644 +--- a/harness/regExpUtils.js ++++ b/harness/regExpUtils.js +@@ -6,27 +6,30 @@ description: | + defines: [buildString, testPropertyEscapes, testPropertyOfStrings, testExtendedCharacterClass, matchValidator] + ---*/ + ++if ($262 && typeof $262.codePointRange === "function") { ++ /* use C function to build the codePointRange (much faster with ++ slow JS engines) */ ++ codePointRange = $262.codePointRange; ++} else { ++ codePointRange = function codePointRange(start, end) { ++ const codePoints = []; ++ let length = 0; ++ for (codePoint = start; codePoint < end; codePoint++) { ++ codePoints[length++] = codePoint; ++ } ++ return String.fromCodePoint.apply(null, codePoints); ++ } ++} ++ + function buildString(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const loneCodePoints = args.loneCodePoints; + const ranges = args.ranges; +- const CHUNK_SIZE = 10000; + let result = String.fromCodePoint.apply(null, loneCodePoints); +- for (let i = 0; i < ranges.length; i++) { +- let range = ranges[i]; +- let start = range[0]; +- let end = range[1]; +- let codePoints = []; +- for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { +- codePoints[length++] = codePoint; +- if (length === CHUNK_SIZE) { +- result += String.fromCodePoint.apply(null, codePoints); +- codePoints.length = length = 0; +- } +- } +- result += String.fromCodePoint.apply(null, codePoints); ++ for (const [start, end] of ranges) { ++ result += codePointRange(start, end + 1); + } + return result; + } diff --git a/quickjs/tests/test_bigint.js b/quickjs/tests/test_bigint.js new file mode 100644 index 0000000..a0d028c --- /dev/null +++ b/quickjs/tests/test_bigint.js @@ -0,0 +1,249 @@ +"use strict"; + +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +function assertThrows(err, func) +{ + var ex; + ex = false; + try { + func(); + } catch(e) { + ex = true; + assert(e instanceof err); + } + assert(ex, true, "exception expected"); +} + +// load more elaborate version of assert if available +try { __loadScript("test_assert.js"); } catch(e) {} + +/*----------------*/ + +function bigint_pow(a, n) +{ + var r, i; + r = 1n; + for(i = 0n; i < n; i++) + r *= a; + return r; +} + +/* a must be < b */ +function test_less(a, b) +{ + assert(a < b); + assert(!(b < a)); + assert(a <= b); + assert(!(b <= a)); + assert(b > a); + assert(!(a > b)); + assert(b >= a); + assert(!(a >= b)); + assert(a != b); + assert(!(a == b)); +} + +/* a must be numerically equal to b */ +function test_eq(a, b) +{ + assert(a == b); + assert(b == a); + assert(!(a != b)); + assert(!(b != a)); + assert(a <= b); + assert(b <= a); + assert(!(a < b)); + assert(a >= b); + assert(b >= a); + assert(!(a > b)); +} + +function test_bigint1() +{ + var a, r; + + test_less(2n, 3n); + test_eq(3n, 3n); + + test_less(2, 3n); + test_eq(3, 3n); + + test_less(2.1, 3n); + test_eq(Math.sqrt(4), 2n); + + a = bigint_pow(3n, 100n); + assert((a - 1n) != a); + assert(a == 515377520732011331036461129765621272702107522001n); + assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1n); + + r = 1n << 31n; + assert(r, 2147483648n, "1 << 31n === 2147483648n"); + + r = 1n << 32n; + assert(r, 4294967296n, "1 << 32n === 4294967296n"); +} + +function test_bigint2() +{ + assert(BigInt(""), 0n); + assert(BigInt(" 123"), 123n); + assert(BigInt(" 123 "), 123n); + assertThrows(SyntaxError, () => { BigInt("+") } ); + assertThrows(SyntaxError, () => { BigInt("-") } ); + assertThrows(SyntaxError, () => { BigInt("\x00a") } ); + assertThrows(SyntaxError, () => { BigInt(" 123 r") } ); +} + +function test_bigint3() +{ + assert(Number(0xffffffffffffffffn), 18446744073709552000); + assert(Number(-0xffffffffffffffffn), -18446744073709552000); + assert(100000000000000000000n == 1e20, true); + assert(100000000000000000001n == 1e20, false); + assert((1n << 100n).toString(10), "1267650600228229401496703205376"); + assert((-1n << 100n).toString(36), "-3ewfdnca0n6ld1ggvfgg"); + assert((1n << 100n).toString(8), "2000000000000000000000000000000000"); + + assert(0x5a4653ca673768565b41f775n << 78n, 8443945299673273647701379149826607537748959488376832n); + assert(-0x5a4653ca673768565b41f775n << 78n, -8443945299673273647701379149826607537748959488376832n); + assert(0x5a4653ca673768565b41f775n >> 78n, 92441n); + assert(-0x5a4653ca673768565b41f775n >> 78n, -92442n); + + assert(~0x5a653ca6n, -1516584103n); + assert(0x5a463ca6n | 0x67376856n, 2138537206n); + assert(0x5a463ca6n & 0x67376856n, 1107699718n); + assert(0x5a463ca6n ^ 0x67376856n, 1030837488n); + + assert(3213213213213213432453243n / 123434343439n, 26031760073331n); + assert(-3213213213213213432453243n / 123434343439n, -26031760073331n); + assert(-3213213213213213432453243n % -123434343439n, -26953727934n); + assert(3213213213213213432453243n % 123434343439n, 26953727934n); + + assert((-2n) ** 127n, -170141183460469231731687303715884105728n); + assert((2n) ** 127n, 170141183460469231731687303715884105728n); + assert((-256n) ** 11n, -309485009821345068724781056n); + assert((7n) ** 20n, 79792266297612001n); +} + +/* pi computation */ + +/* return floor(log2(a)) for a > 0 and 0 for a = 0 */ +function floor_log2(a) +{ + var k_max, a1, k, i; + k_max = 0n; + while ((a >> (2n ** k_max)) != 0n) { + k_max++; + } + k = 0n; + a1 = a; + for(i = k_max - 1n; i >= 0n; i--) { + a1 = a >> (2n ** i); + if (a1 != 0n) { + a = a1; + k |= (1n << i); + } + } + return k; +} + +/* return ceil(log2(a)) for a > 0 */ +function ceil_log2(a) +{ + return floor_log2(a - 1n) + 1n; +} + +/* return floor(sqrt(a)) (not efficient but simple) */ +function int_sqrt(a) +{ + var l, u, s; + if (a == 0n) + return a; + l = ceil_log2(a); + u = 1n << ((l + 1n) / 2n); + /* u >= floor(sqrt(a)) */ + for(;;) { + s = u; + u = ((a / s) + s) / 2n; + if (u >= s) + break; + } + return s; +} + +/* return pi * 2**prec */ +function calc_pi(prec) { + const CHUD_A = 13591409n; + const CHUD_B = 545140134n; + const CHUD_C = 640320n; + const CHUD_C3 = 10939058860032000n; /* C^3/24 */ + const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ + + /* return [P, Q, G] */ + function chud_bs(a, b, need_G) { + var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; + if (a == (b - 1n)) { + G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); + P = G * (CHUD_B * b + CHUD_A); + if (b & 1n) + P = -P; + Q = b * b * b * CHUD_C3; + } else { + c = (a + b) >> 1n; + [P1, Q1, G1] = chud_bs(a, c, true); + [P2, Q2, G2] = chud_bs(c, b, need_G); + P = P1 * Q2 + P2 * G1; + Q = Q1 * Q2; + if (need_G) + G = G1 * G2; + else + G = 0n; + } + return [P, Q, G]; + } + + var n, P, Q, G; + /* number of serie terms */ + n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n; + [P, Q, G] = chud_bs(0n, n, false); + Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A); + G = int_sqrt(CHUD_C << (2n * prec)); + return (Q * G) >> prec; +} + +function compute_pi(n_digits) { + var r, n_digits, n_bits, out; + /* we add more bits to reduce the probability of bad rounding for + the last digits */ + n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n; + r = calc_pi(n_bits); + r = ((10n ** BigInt(n_digits)) * r) >> n_bits; + out = r.toString(); + return out[0] + "." + out.slice(1); +} + +function test_pi() +{ + assert(compute_pi(2000), "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009"); +} + +test_bigint1(); +test_bigint2(); +test_bigint3(); +test_pi(); diff --git a/quickjs-ng/tests/test_bjson.js b/quickjs/tests/test_bjson.js similarity index 56% rename from quickjs-ng/tests/test_bjson.js rename to quickjs/tests/test_bjson.js index 7020bd8..c29ded4 100644 --- a/quickjs-ng/tests/test_bjson.js +++ b/quickjs/tests/test_bjson.js @@ -1,44 +1,20 @@ -import * as std from "qjs:std"; -import * as bjson from "qjs:bjson"; -import { assert } from "./assert.js"; +import * as bjson from "./bjson.so"; -function base64decode(s) { - var A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var n = s.indexOf("="); - if (n < 0) n = s.length; - if (n & 3 === 1) throw Error("bad base64"); // too much padding - var r = new Uint8Array(3 * (n>>2) + (n>>1 & 1) + (n & 1)); - var a, b, c, d, i, j; - a = b = c = d = i = j = 0; - while (i+3 < n) { - a = A.indexOf(s[i++]); - b = A.indexOf(s[i++]); - c = A.indexOf(s[i++]); - d = A.indexOf(s[i++]); - if (~63 & (a|b|c|d)) throw Error("bad base64"); - r[j++] = a<<2 | b>>4; - r[j++] = 255 & b<<4 | c>>2; - r[j++] = 255 & c<<6 | d; - } - switch (n & 3) { - case 2: - a = A.indexOf(s[i++]); - b = A.indexOf(s[i++]); - if (~63 & (a|b)) throw Error("bad base64"); - if (b & 15) throw Error("bad base64"); - r[j++] = a<<2 | b>>4; - break; - case 3: - a = A.indexOf(s[i++]); - b = A.indexOf(s[i++]); - c = A.indexOf(s[i++]); - if (~63 & (a|b|c)) throw Error("bad base64"); - if (c & 3) throw Error("bad base64"); - r[j++] = a<<2 | b>>4; - r[j++] = 255 & b<<4 | c>>2; - break; - } - return r.buffer; +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); } function toHex(a) @@ -189,9 +165,9 @@ function bjson_test_reference() array[i].idx = i; array[i].typed_array = new Uint8Array(array_buffer, i, 1); } - buf = bjson.write(array, bjson.WRITE_OBJ_REFERENCE); + buf = bjson.write(array, true); - array = bjson.read(buf, 0, buf.byteLength, bjson.READ_OBJ_REFERENCE); + array = bjson.read(buf, 0, buf.byteLength, true); /* check the result */ for(i = 0; i < n; i++) { @@ -203,103 +179,6 @@ function bjson_test_reference() } } -function bjson_test_regexp() -{ - var buf, r; - - bjson_test(/xyzzy/); - bjson_test(/xyzzy/digu); - - buf = bjson.write(/(?<𝓓𝓸𝓰>dog)/); - r = bjson.read(buf, 0, buf.byteLength); - assert("sup dog".match(r).groups["𝓓𝓸𝓰"], "dog"); -} - -function bjson_test_map() -{ - var buf, r, xs; - - xs = [["key", "value"]]; - buf = bjson.write(new Map(xs)); - r = bjson.read(buf, 0, buf.byteLength); - assert(r instanceof Map); - assert([...r].toString(), xs.toString()); -} - -function bjson_test_set() -{ - var buf, r, xs; - - xs = ["one", "two", "three"]; - buf = bjson.write(new Set(xs)); - r = bjson.read(buf, 0, buf.byteLength); - assert(r instanceof Set); - assert([...r].toString(), xs.toString()); -} - -function bjson_test_symbol() -{ - var buf, r, o; - - o = {[Symbol.toStringTag]: "42"}; - buf = bjson.write(o); - r = bjson.read(buf, 0, buf.byteLength); - assert(o.toString(), r.toString()); - - o = Symbol('foo'); - buf = bjson.write(o); - r = bjson.read(buf, 0, buf.byteLength); - assert(o.toString(), r.toString()); - assert(o !== r); - - o = Symbol.for('foo'); - buf = bjson.write(o); - r = bjson.read(buf, 0, buf.byteLength); - assert(o, r); - - o = Symbol.toStringTag; - buf = bjson.write(o); - r = bjson.read(buf, 0, buf.byteLength); - assert(o, r); -} - -function bjson_test_bytecode() -{ - var buf, o, r, e, i; - - o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true}); - buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0)); - try { - bjson.read(buf, 0, buf.byteLength); - } catch (_e) { - e = _e; - } - assert(String(e), "SyntaxError: no bytecode allowed"); - - o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0)); - assert(String(o), "[function bytecode]"); - o = std.evalScript(o, {eval_function: true}); - for (i = 0; i < 42; i++) o({i}); // exercise o.i IC -} - -function bjson_test_fuzz() -{ - var corpus = [ - "FRAAAAAABGA=", - "Febm5oIt", - "FQARABMGBgYGBgYGBgYGBv////8QABEALxH/vy8R/78=", - "FQAIfwAK/////3//////////////////////////////3/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAD5+fn5+fn5+fn5+fkAAAAAAAYAqw==", - ]; - for (var input of corpus) { - var buf = base64decode(input); - try { - bjson.read(buf, 0, buf.byteLength); - } catch (e) { - if (/invalid version/.test(e.message)) throw e; // corpus needs update - } - } -} - function bjson_test_all() { var obj; @@ -311,7 +190,6 @@ function bjson_test_all() bjson_test([BigInt("1"), -BigInt("0x123456789"), BigInt("0x123456789abcdef123456789abcdef")]); } - bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]); bjson_test(new Int32Array([123123, 222111, -32222])); @@ -330,12 +208,6 @@ function bjson_test_all() bjson_test_arraybuffer(); bjson_test_reference(); - bjson_test_regexp(); - bjson_test_map(); - bjson_test_set(); - bjson_test_symbol(); - bjson_test_bytecode(); - bjson_test_fuzz(); } bjson_test_all(); diff --git a/quickjs-ng/tests/test_builtin.js b/quickjs/tests/test_builtin.js similarity index 65% rename from quickjs-ng/tests/test_builtin.js rename to quickjs/tests/test_builtin.js index 462558e..a11407e 100644 --- a/quickjs-ng/tests/test_builtin.js +++ b/quickjs/tests/test_builtin.js @@ -1,116 +1,79 @@ -import * as os from "qjs:os"; -import { assert, assertThrows } from "./assert.js"; +"use strict"; -// Keep this at the top; it tests source positions. -function test_exception_source_pos() -{ - var e; - - try { - throw new Error(""); // line 10, column 19 - } catch(_e) { - e = _e; - } - - assert(e.stack.includes("test_builtin.js:10:19")); -} +var status = 0; +var throw_errors = true; -// Keep this at the top; it tests source positions. -function test_function_source_pos() // line 19, column 1 -{ - function inner() {} // line 21, column 5 - var f = eval("function f() {} f"); - assert(`${test_function_source_pos.lineNumber}:${test_function_source_pos.columnNumber}`, "19:1"); - assert(`${inner.lineNumber}:${inner.columnNumber}`, "21:5"); - assert(`${f.lineNumber}:${f.columnNumber}`, "1:1"); +function throw_error(msg) { + if (throw_errors) + throw Error(msg); + console.log(msg); + status = 1; } -// Keep this at the top; it tests source positions. -function test_exception_prepare_stack() -{ - var e; - - Error.prepareStackTrace = (_, frames) => { - // Just return the array to check. - return frames; - }; - - try { - throw new Error(""); // line 39, column 19 - } catch(_e) { - e = _e; +function assert(actual, expected, message) { + function get_full_type(o) { + var type = typeof(o); + if (type === 'object') { + if (o === null) + return 'null'; + if (o.constructor && o.constructor.name) + return o.constructor.name; + } + return type; } - Error.prepareStackTrace = undefined; + if (arguments.length == 1) + expected = true; - assert(e.stack.length, 2); - const f = e.stack[0]; - assert(f.getFunctionName(), 'test_exception_prepare_stack'); - assert(f.getFileName().endsWith('test_builtin.js')); - assert(f.getLineNumber(), 39); - assert(f.getColumnNumber(), 19); - assert(!f.isNative()); + if (typeof actual === typeof expected) { + if (actual === expected) { + if (actual !== 0 || (1 / actual) === (1 / expected)) + return; + } + if (typeof actual === 'number') { + if (isNaN(actual) && isNaN(expected)) + return true; + } + if (typeof actual === 'object') { + if (actual !== null && expected !== null + && actual.constructor === expected.constructor + && actual.toString() === expected.toString()) + return; + } + } + // Should output the source file and line number and extract + // the expression from the assert call + throw_error("assertion failed: got " + + get_full_type(actual) + ":|" + actual + "|, expected " + + get_full_type(expected) + ":|" + expected + "|" + + (message ? " (" + message + ")" : "")); } -// Keep this at the top; it tests source positions. -function test_exception_stack_size_limit() +function assert_throws(expected_error, func) { - var e; - - Error.stackTraceLimit = 1; - Error.prepareStackTrace = (_, frames) => { - // Just return the array to check. - return frames; - }; - + var err = false; try { - throw new Error(""); // line 67, column 19 - } catch(_e) { - e = _e; + func(); + } catch(e) { + err = true; + if (!(e instanceof expected_error)) { + // Should output the source file and line number and extract + // the expression from the assert_throws() call + throw_error("unexpected exception type"); + return; + } + } + if (!err) { + // Should output the source file and line number and extract + // the expression from the assert_throws() call + throw_error("expected exception"); } - - Error.stackTraceLimit = 10; - Error.prepareStackTrace = undefined; - - assert(e.stack.length, 1); - const f = e.stack[0]; - assert(f.getFunctionName(), 'test_exception_stack_size_limit'); - assert(f.getFileName().endsWith('test_builtin.js')); - assert(f.getLineNumber(), 67); - assert(f.getColumnNumber(), 19); - assert(!f.isNative()); } -function test_exception_capture_stack_trace() -{ - var o = {}; - - assertThrows(TypeError, (function() { - Error.captureStackTrace(); - })); - - Error.captureStackTrace(o); - - assert(typeof o.stack === 'string'); - assert(o.stack.includes('test_exception_capture_stack_trace')); -} +// load more elaborate version of assert if available +try { __loadScript("test_assert.js"); } catch(e) {} -function test_exception_capture_stack_trace_filter() -{ - var o = {}; - const fun1 = () => { fun2(); }; - const fun2 = () => { fun3(); }; - const fun3 = () => { log_stack(); }; - function log_stack() { - Error.captureStackTrace(o, fun3); - } - fun1(); - - Error.captureStackTrace(o); - - assert(!o.stack.includes('fun3')); - assert(!o.stack.includes('log_stack')); -} +/*----------------*/ function my_func(a, b) { @@ -141,7 +104,7 @@ function test_function() r = (function () { return 1; }).apply(null, undefined); assert(r, 1); - assertThrows(TypeError, (function() { + assert_throws(TypeError, (function() { Reflect.apply((function () { return 1; }), null, undefined); })); @@ -206,8 +169,6 @@ function test() assert(Object.isExtensible(a), false, "extensible"); assert(typeof a.y, "undefined", "extensible"); assert(err, true, "extensible"); - - assertThrows(TypeError, () => Object.setPrototypeOf(Object.prototype, {})); } function test_enum() @@ -378,11 +339,6 @@ function test_string() assert(eval('"\0"'), "\0"); assert("abc".padStart(Infinity, ""), "abc"); - - assert(qjs.getStringKind("xyzzy".slice(1)), - /*JS_STRING_KIND_NORMAL*/0); - assert(qjs.getStringKind("xyzzy".repeat(512).slice(1)), - /*JS_STRING_KIND_SLICE*/1); } function test_math() @@ -458,20 +414,6 @@ function test_eval2() f1(g); f2(g); assert(g_call_count, 2); - var e; - try { - new class extends Object { - constructor() { - (() => { - for (const _ in this); - eval(""); - })(); - } - }; - } catch (_e) { - e = _e; - } - assert(e?.message, "this is not initialized"); } function test_eval() @@ -513,7 +455,7 @@ function test_eval() function test_typed_array() { - var buffer, a, i, str, b; + var buffer, a, i, str; a = new Uint8Array(4); assert(a.length, 4); @@ -569,27 +511,66 @@ function test_typed_array() assert(a.toString(), "1,2,3,4"); a.set([10, 11], 2); assert(a.toString(), "1,2,10,11"); +} - a = new Uint8Array(buffer, 0, 4); - a.constructor = { - [Symbol.species]: function (len) { - return new Uint8Array(buffer, 1, len); - }, - }; - b = a.slice(); - assert(a.buffer, b.buffer); - assert(a.toString(), "0,0,0,255"); - assert(b.toString(), "0,0,255,255"); - - const TypedArray = class extends Object.getPrototypeOf(Uint8Array) {}; - let caught = false; +/* return [s, line_num, col_num] where line_num and col_num are the + position of the '@' character in 'str'. 's' is str without the '@' + character */ +function get_string_pos(str) +{ + var p, line_num, col_num, s, q, r; + p = str.indexOf('@'); + assert(p >= 0, true); + q = 0; + line_num = 1; + for(;;) { + r = str.indexOf('\n', q); + if (r < 0 || r >= p) + break; + q = r + 1; + line_num++; + } + col_num = p - q + 1; + s = str.slice(0, p) + str.slice(p + 1); + return [s, line_num, col_num]; +} + +function check_error_pos(e, expected_error, line_num, col_num, level) +{ + var expected_pos, tab, line; + level |= 0; + expected_pos = ":" + line_num + ":" + col_num; + tab = e.stack.split("\n"); + line = tab[level]; + if (line.slice(-1) == ')') + line = line.slice(0, -1); + if (line.indexOf(expected_pos) < 0) { + throw_error("unexpected line or column number. error=" + e.message + + ".got |" + line + "|, expected |" + expected_pos + "|"); + } +} + +function assert_json_error(str, line_num, col_num) +{ + var err = false; + var expected_pos, tab; + + tab = get_string_pos(str); + try { - new TypedArray(); // extensible but not instantiable - } catch (e) { - assert(/cannot be called/.test(e.message)); - caught = true; + JSON.parse(tab[0]); + } catch(e) { + err = true; + if (!(e instanceof SyntaxError)) { + throw_error("unexpected exception type"); + return; + } + /* XXX: the way quickjs returns JSON errors is not similar to Node or spiderMonkey */ + check_error_pos(e, SyntaxError, tab[1], tab[2]); + } + if (!err) { + throw_error("expected exception"); } - assert(caught); } function test_json() @@ -615,6 +596,9 @@ function test_json() 3 ] ]`); + + assert_json_error('\n" \\@x"'); + assert_json_error('\n{ "a": @x }"'); } function test_date() @@ -629,26 +613,11 @@ function test_date() // Hence the fractional part after . should have 3 digits and how // a different number of digits is handled is implementation defined. assert(Date.parse(""), NaN); - assert(Date.parse("13"), NaN); - assert(Date.parse("31"), NaN); - assert(Date.parse("1000"), -30610224000000); - assert(Date.parse("1969"), -31536000000); - assert(Date.parse("1970"), 0); assert(Date.parse("2000"), 946684800000); - assert(Date.parse("9999"), 253370764800000); - assert(Date.parse("275761"), NaN); - assert(Date.parse("999999"), NaN); - assert(Date.parse("1000000000"), NaN); - assert(Date.parse("-271821"), NaN); - assert(Date.parse("-271820"), -8639977881600000); - assert(Date.parse("-100000"), -3217862419200000); - assert(Date.parse("+100000"), 3093527980800000); - assert(Date.parse("+275760"), 8639977881600000); - assert(Date.parse("+275761"), NaN); assert(Date.parse("2000-01"), 946684800000); assert(Date.parse("2000-01-01"), 946684800000); - assert(Date.parse("2000-01-01T"), NaN); - assert(Date.parse("2000-01-01T00Z"), NaN); + //assert(Date.parse("2000-01-01T"), NaN); + //assert(Date.parse("2000-01-01T00Z"), NaN); assert(Date.parse("2000-01-01T00:00Z"), 946684800000); assert(Date.parse("2000-01-01T00:00:00Z"), 946684800000); assert(Date.parse("2000-01-01T00:00:00.1Z"), 946684800100); @@ -721,7 +690,7 @@ function test_date() assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91, NaN), 1508695811091); // TODO: Fix rounding errors on Windows/Cygwin. - if (!['win32', 'cygwin'].includes(os.platform)) { + if (!(typeof os !== 'undefined' && ['win32', 'cygwin'].includes(os.platform))) { // from test262/test/built-ins/Date/UTC/fp-evaluation-order.js assert(Date.UTC(1970, 0, 1, 80063993375, 29, 1, -288230376151711740), 29312, 'order of operations / precision in MakeTime'); @@ -733,14 +702,6 @@ function test_date() assert(Date.UTC(2017, 9, 22, 18 - 1e10, 10 + 60e10), 1508695800000); assert(Date.UTC(2017, 9, 22, 18, 10 - 1e10, 11 + 60e10), 1508695811000); assert(Date.UTC(2017, 9, 22, 18, 10, 11 - 1e12, 91 + 1000e12), 1508695811091); - assert(new Date("2024 Apr 7 1:00 AM").toLocaleString(), "04/07/2024, 01:00:00 AM"); - assert(new Date("2024 Apr 7 2:00 AM").toLocaleString(), "04/07/2024, 02:00:00 AM"); - assert(new Date("2024 Apr 7 11:00 AM").toLocaleString(), "04/07/2024, 11:00:00 AM"); - assert(new Date("2024 Apr 7 12:00 AM").toLocaleString(), "04/07/2024, 12:00:00 AM"); - assert(new Date("2024 Apr 7 1:00 PM").toLocaleString(), "04/07/2024, 01:00:00 PM"); - assert(new Date("2024 Apr 7 2:00 PM").toLocaleString(), "04/07/2024, 02:00:00 PM"); - assert(new Date("2024 Apr 7 11:00 PM").toLocaleString(), "04/07/2024, 11:00:00 PM"); - assert(new Date("2024 Apr 7 12:00 PM").toLocaleString(), "04/07/2024, 12:00:00 PM"); } function test_regexp() @@ -778,25 +739,9 @@ function test_regexp() assert(/{1a}/.toString(), "/{1a}/"); a = /a{1+/.exec("a{11"); - assert(a, ["a{11"] ); - - eval("/[a-]/"); // accepted with no flag - eval("/[a-]/u"); // accepted with 'u' flag - - let ex; - try { - eval("/[a-]/v"); // rejected with 'v' flag - } catch (_ex) { - ex = _ex; - } - assert(ex?.message, "invalid class range"); - - eval("/[\\-]/"); - eval("/[\\-]/u"); + assert(a, ["a{11"]); /* test zero length matches */ - a = /()*?a/.exec(","); - assert(a, null); a = /(?:(?=(abc)))a/.exec("abc"); assert(a, ["a", "abc"]); a = /(?:(?=(abc)))?a/.exec("abc"); @@ -805,8 +750,53 @@ function test_regexp() assert(a, ["a", undefined]); a = /(?:|[\w])+([0-9])/.exec("123a23"); assert(a, ["123a23", "3"]); - a = "ab".split(/(c)*/); - assert(a, ["a", undefined, "b"]); + a = /()*?a/.exec(","); + assert(a, null); + + /* test \b escape */ + assert(/[\q{a\b}]/.test("a\b"), true); + assert(/[\b]/.test("\b"), true); + + /* test case insensitive matching (test262 hardly tests it) */ + assert("aAbBcC#4".replace(/\p{Lower}/gu,"X"), "XAXBXC#4"); + + assert("aAbBcC#4".replace(/\p{Lower}/gui,"X"), "XXXXXX#4"); + assert("aAbBcC#4".replace(/\p{Upper}/gui,"X"), "XXXXXX#4"); + assert("aAbBcC#4".replace(/\P{Lower}/gui,"X"), "XXXXXXXX"); + assert("aAbBcC#4".replace(/\P{Upper}/gui,"X"), "XXXXXXXX"); + assert("aAbBcC".replace(/[^b]/gui, "X"), "XXbBXX"); + assert("aAbBcC".replace(/[^A-B]/gui, "X"), "aAbBXX"); + + assert("aAbBcC#4".replace(/\p{Lower}/gvi,"X"), "XXXXXX#4"); + assert("aAbBcC#4".replace(/\P{Lower}/gvi,"X"), "aAbBcCXX"); + assert("aAbBcC#4".replace(/[^\P{Lower}]/gvi,"X"), "XXXXXX#4"); + assert("aAbBcC#4".replace(/\P{Upper}/gvi,"X"), "aAbBcCXX"); + assert("aAbBcC".replace(/[^b]/gvi, "X"), "XXbBXX"); + assert("aAbBcC".replace(/[^A-B]/gvi, "X"), "aAbBXX"); + assert("aAbBcC".replace(/[[a-c]&&B]/gvi, "X"), "aAXXcC"); + assert("aAbBcC".replace(/[[a-c]--B]/gvi, "X"), "XXbBXX"); + + assert("abcAbC".replace(/[\q{AbC}]/gvi,"X"), "XX"); + /* Note: SpiderMonkey and v8 may not be correct */ + assert("abcAbC".replace(/[\q{BC|A}]/gvi,"X"), "XXXX"); + assert("abcAbC".replace(/[\q{BC|A}--a]/gvi,"X"), "aXAX"); + + /* case where lastIndex points to the second element of a + surrogate pair */ + a = /(?:)/gu; + a.lastIndex = 1; + a.exec("🐱"); + assert(a.lastIndex, 0); + + a.lastIndex = 1; + a.exec("a\udc00"); + assert(a.lastIndex, 1); + + a = /\u{10000}/vgd; + a.lastIndex = 1; + a = a.exec("\u{10000}_\u{10000}"); + assert(a.indices[0][0], 0); + assert(a.indices[0][1], 2); } function test_symbol() @@ -841,25 +831,26 @@ function test_symbol() assert(b.toString(), "Symbol(aaa)"); } -function test_map() +function test_map1(key_type, n) { - var a, i, n, tab, o, v; - n = 1000; - - a = new Map(); - for (var i = 0; i < n; i++) { - a.set(i, i); - } - a.set(-2147483648, 1); - assert(a.get(-2147483648), 1); - assert(a.get(-2147483647 - 1), 1); - assert(a.get(-2147483647.5 - 0.5), 1); - + var a, i, tab, o, v; a = new Map(); tab = []; for(i = 0; i < n; i++) { v = { }; - o = { id: i }; + switch(key_type) { + case "small_bigint": + o = BigInt(i); + break; + case "bigint": + o = BigInt(i) + (1n << 128n); + break; + case "object": + o = { id: i }; + break; + default: + assert(false); + } tab[i] = [o, v]; a.set(o, v); } @@ -880,125 +871,126 @@ function test_map() assert(a.size, 0); } +function test_map() +{ + var a, i, n, tab, o, v; + n = 1000; + + a = new Map(); + for (var i = 0; i < n; i++) { + a.set(i, i); + } + a.set(-2147483648, 1); + assert(a.get(-2147483648), 1); + assert(a.get(-2147483647 - 1), 1); + assert(a.get(-2147483647.5 - 0.5), 1); + + a.set(1n, 1n); + assert(a.get(1n), 1n); + assert(a.get(2n**1000n - (2n**1000n - 1n)), 1n); + + test_map1("object", n); + test_map1("small_bigint", n); + test_map1("bigint", n); +} + function test_weak_map() { - var a, e, i, n, tab, o, v, n2; + var a, i, n, tab, o, v, n2; a = new WeakMap(); n = 10; tab = []; - for (const k of [null, 42, "no", Symbol.for("forbidden")]) { - e = undefined; - try { - a.set(k, 42); - } catch (_e) { - e = _e; - } - assert(!!e); - assert(e.message, "invalid value used as WeakMap key"); - } for(i = 0; i < n; i++) { v = { }; - o = { id: i }; + if (i & 1) + o = Symbol("x" + i); + else + o = { id: i }; tab[i] = [o, v]; a.set(o, v); } o = null; - n2 = n >> 1; + n2 = 5; for(i = 0; i < n2; i++) { a.delete(tab[i][0]); } for(i = n2; i < n; i++) { tab[i][0] = null; /* should remove the object from the WeakMap too */ } + std.gc(); /* the WeakMap should be empty here */ } -function test_set() +function test_weak_map_cycles() { - const iter = { - a: [4, 5, 6], - nextCalls: 0, - returnCalls: 0, - next() { - const done = this.nextCalls >= this.a.length - const value = this.a[this.nextCalls] - this.nextCalls++ - return {done, value} - }, - return() { - this.returnCalls++ - return this - }, + const weak1 = new WeakMap(); + const weak2 = new WeakMap(); + function createCyclicKey() { + const parent = {}; + const child = {parent}; + parent.child = child; + return child; } - const setlike = { - size: iter.a.length, - has(v) { return iter.a.includes(v) }, - keys() { return iter }, + function testWeakMap() { + const cyclicKey = createCyclicKey(); + const valueOfCyclicKey = {}; + weak1.set(cyclicKey, valueOfCyclicKey); + weak2.set(valueOfCyclicKey, 1); } - // set must be bigger than iter.a to hit iter.next and iter.return - assert(new Set([4,5,6,7]).isSupersetOf(setlike), true) - assert(iter.nextCalls, 4) - assert(iter.returnCalls, 0) - iter.nextCalls = iter.returnCalls = 0 - assert(new Set([0,1,2,3]).isSupersetOf(setlike), false) - assert(iter.nextCalls, 1) - assert(iter.returnCalls, 1) - iter.nextCalls = iter.returnCalls = 0 - // set must be bigger than iter.a to hit iter.next and iter.return - assert(new Set([4,5,6,7]).isDisjointFrom(setlike), false) - assert(iter.nextCalls, 1) - assert(iter.returnCalls, 1) - iter.nextCalls = iter.returnCalls = 0 - assert(new Set([0,1,2,3]).isDisjointFrom(setlike), true) - assert(iter.nextCalls, 4) - assert(iter.returnCalls, 0) - iter.nextCalls = iter.returnCalls = 0 - function expectException(klass, sizes) { - for (const size of sizes) { - let ex - try { - new Set([]).union({size}) - } catch (e) { - ex = e - } - assert(ex instanceof klass) - assert(typeof ex.message, "string") - assert(ex.message.includes(".size")) - } - } - expectException(RangeError, [-1, -(Number.MAX_SAFE_INTEGER+1), -Infinity]) - expectException(TypeError, [NaN]) - const legal = [ - 0, -0, 1, 2, - Number.MAX_SAFE_INTEGER + 1, - Number.MAX_SAFE_INTEGER + 2, - Number.MAX_SAFE_INTEGER + 3, - Infinity - ] - for (const size of legal) { - new Set([]).union({ - size, - has() { return false }, - keys() { return [].values() }, - }) + testWeakMap(); + // Force to free cyclicKey. + std.gc(); + // Here will cause sigsegv because [cyclicKey] and [valueOfCyclicKey] in [weak1] was free, + // but weak2's map record was not removed, and it's key refers [valueOfCyclicKey] which is free. + weak2.get({}); + std.gc(); +} + +function test_weak_ref() +{ + var w1, w2, o, i; + + for(i = 0; i < 2; i++) { + if (i == 0) + o = { }; + else + o = Symbol("x"); + w1 = new WeakRef(o); + assert(w1.deref(), o); + w2 = new WeakRef(o); + assert(w2.deref(), o); + + o = null; + assert(w1.deref(), undefined); + assert(w2.deref(), undefined); + std.gc(); + assert(w1.deref(), undefined); + assert(w2.deref(), undefined); } } -function test_weak_set() +function test_finalization_registry() { - var a, e; - a = new WeakSet(); - for (const k of [null, 42, "no", Symbol.for("forbidden")]) { - e = undefined; - try { - a.add(k); - } catch (_e) { - e = _e; - } - assert(!!e); - assert(e.message, "invalid value used as WeakSet key"); + { + let expected = {}; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + os.setTimeout(() => { + assert(actual, expected); + }, 0); } + { + let expected = 42; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + os.setTimeout(() => { + assert(actual, expected); + }, 0); + } + std.gc(); } function test_generator() @@ -1060,109 +1052,114 @@ function test_generator() assert(v.value === 6 && v.done === true); } -function test_proxy_iter() +function rope_concat(n, dir) { - const p = new Proxy({}, { - getOwnPropertyDescriptor() { - return {configurable: true, enumerable: true, value: 42}; - }, - ownKeys() { - return ["x", "y"]; - }, - }); - const a = []; - for (const x in p) a.push(x); - assert(a[0], "x"); - assert(a[1], "y"); + var i, s; + s = ""; + if (dir > 0) { + for(i = 0; i < n; i++) + s += String.fromCharCode(i & 0xffff); + } else { + for(i = n - 1; i >= 0; i--) + s = String.fromCharCode(i & 0xffff) + s; + } + + for(i = 0; i < n; i++) { + /* test before the assert to go faster */ + if (s.charCodeAt(i) != (i & 0xffff)) { + assert(s.charCodeAt(i), i & 0xffff); + } + } } -/* CVE-2023-31922 */ -function test_proxy_is_array() +function test_rope() { - for (var r = new Proxy([], {}), y = 0; y < 331072; y++) - r = new Proxy(r, {}); - - try { - /* Without ASAN */ - assert(Array.isArray(r)); - } catch(e) { - /* With ASAN expect RangeError "Maximum call stack size exceeded" to be raised */ - if (e instanceof RangeError) { - assert(e.message, "Maximum call stack size exceeded", "Stack overflow error was not raised") - } else { - throw e; - } - } + rope_concat(100000, 1); + rope_concat(100000, -1); } -function test_finalization_registry() +function eval_error(eval_str, expected_error, level) { - { - let expected = {}; - let actual; - let finrec = new FinalizationRegistry(v => { actual = v }); - finrec.register({}, expected); - queueMicrotask(() => { - assert(actual, expected); - }); + var err = false; + var expected_pos, tab; + + tab = get_string_pos(eval_str); + + try { + eval(tab[0]); + } catch(e) { + err = true; + if (!(e instanceof expected_error)) { + throw_error("unexpected exception type"); + return; + } + check_error_pos(e, expected_error, tab[1], tab[2], level); } - { - let expected = 42; - let actual; - let finrec = new FinalizationRegistry(v => { actual = v }); - finrec.register({}, expected); - queueMicrotask(() => { - assert(actual, expected); - }); + if (!err) { + throw_error("expected exception"); } } -function test_cur_pc() +var poisoned_number = { + valueOf: function() { throw Error("poisoned number") }, +}; + +function test_line_column_numbers() { - var a = []; - Object.defineProperty(a, '1', { - get: function() { throw Error("a[1]_get"); }, - set: function(x) { throw Error("a[1]_set"); } - }); - assertThrows(Error, function() { return a[1]; }); - assertThrows(Error, function() { a[1] = 1; }); - assertThrows(Error, function() { return [...a]; }); - assertThrows(Error, function() { return ({...b} = a); }); - - var o = {}; - Object.defineProperty(o, 'x', { - get: function() { throw Error("o.x_get"); }, - set: function(x) { throw Error("o.x_set"); } - }); - o.valueOf = function() { throw Error("o.valueOf"); }; - assertThrows(Error, function() { return +o; }); - assertThrows(Error, function() { return -o; }); - assertThrows(Error, function() { return o+1; }); - assertThrows(Error, function() { return o-1; }); - assertThrows(Error, function() { return o*1; }); - assertThrows(Error, function() { return o/1; }); - assertThrows(Error, function() { return o%1; }); - assertThrows(Error, function() { return o**1; }); - assertThrows(Error, function() { return o<<1; }); - assertThrows(Error, function() { return o>>1; }); - assertThrows(Error, function() { return o>>>1; }); - assertThrows(Error, function() { return o&1; }); - assertThrows(Error, function() { return o|1; }); - assertThrows(Error, function() { return o^1; }); - assertThrows(Error, function() { return o<1; }); - assertThrows(Error, function() { return o==1; }); - assertThrows(Error, function() { return o++; }); - assertThrows(Error, function() { return o--; }); - assertThrows(Error, function() { return ++o; }); - assertThrows(Error, function() { return --o; }); - assertThrows(Error, function() { return ~o; }); - - Object.defineProperty(globalThis, 'xxx', { - get: function() { throw Error("xxx_get"); }, - set: function(x) { throw Error("xxx_set"); } - }); - assertThrows(Error, function() { return xxx; }); - assertThrows(Error, function() { xxx = 1; }); + var f, e, tab; + + /* The '@' character provides the expected position of the + error. It is removed before evaluating the string. */ + + /* parsing */ + eval_error("\n 123 @a ", SyntaxError); + eval_error("\n @/* ", SyntaxError); + eval_error("function f @a", SyntaxError); + /* currently regexp syntax errors point to the start of the regexp */ + eval_error("\n @/aaa]/u", SyntaxError); + + /* function definitions */ + + tab = get_string_pos("\n @function f() { }; f;"); + e = eval(tab[0]); + assert(e.lineNumber, tab[1]); + assert(e.columnNumber, tab[2]); + + /* errors */ + tab = get_string_pos('\n Error@("hello");'); + e = eval(tab[0]); + check_error_pos(e, Error, tab[1], tab[2]); + + eval_error('\n throw Error@("hello");', Error); + + /* operators */ + eval_error('\n 1 + 2 @* poisoned_number;', Error, 1); + eval_error('\n 1 + "café" @* poisoned_number;', Error, 1); + eval_error('\n 1 + 2 @** poisoned_number;', Error, 1); + eval_error('\n 2 * @+ poisoned_number;', Error, 1); + eval_error('\n 2 * @- poisoned_number;', Error, 1); + eval_error('\n 2 * @~ poisoned_number;', Error, 1); + eval_error('\n 2 * @++ poisoned_number;', Error, 1); + eval_error('\n 2 * @-- poisoned_number;', Error, 1); + eval_error('\n 2 * poisoned_number @++;', Error, 1); + eval_error('\n 2 * poisoned_number @--;', Error, 1); + + /* accessors */ + eval_error('\n 1 + null@[0];', TypeError); + eval_error('\n 1 + null @. abcd;', TypeError); + eval_error('\n 1 + null @( 1234 );', TypeError); + eval_error('var obj = { get a() { throw Error("test"); } }\n 1 + obj @. a;', + Error, 1); + eval_error('var obj = { set a(b) { throw Error("test"); } }\n obj @. a = 1;', + Error, 1); + + /* variables reference */ + eval_error('\n 1 + @not_def', ReferenceError, 0); + + /* assignments */ + eval_error('1 + (@not_def = 1)', ReferenceError, 0); + eval_error('1 + (@not_def += 2)', ReferenceError, 0); + eval_error('var a;\n 1 + (a @+= poisoned_number);', Error, 1); } test(); @@ -1180,16 +1177,9 @@ test_regexp(); test_symbol(); test_map(); test_weak_map(); -test_set(); -test_weak_set(); -test_generator(); -test_proxy_iter(); -test_proxy_is_array(); +test_weak_map_cycles(); +test_weak_ref(); test_finalization_registry(); -test_exception_source_pos(); -test_function_source_pos(); -test_exception_prepare_stack(); -test_exception_stack_size_limit(); -test_exception_capture_stack_trace(); -test_exception_capture_stack_trace_filter(); -test_cur_pc(); +test_generator(); +test_rope(); +test_line_column_numbers(); diff --git a/quickjs-ng/tests/test_closure.js b/quickjs/tests/test_closure.js similarity index 83% rename from quickjs-ng/tests/test_closure.js rename to quickjs/tests/test_closure.js index 4d63879..f5d4160 100644 --- a/quickjs-ng/tests/test_closure.js +++ b/quickjs/tests/test_closure.js @@ -1,5 +1,3 @@ -// This test cannot use imports because it needs to run in non-strict mode. - function assert(actual, expected, message) { if (arguments.length == 1) expected = true; @@ -17,6 +15,9 @@ function assert(actual, expected, message) { (message ? " (" + message + ")" : "")); } +// load more elaborate version of assert if available +try { __loadScript("test_assert.js"); } catch(e) {} + /*----------------*/ var log_str = ""; @@ -134,9 +135,9 @@ function test_arrow_function() assert(a.length, 2); assert(a[0] === 1 && a[1] === 2); - assert(f2.call("this_val"), "this_val"); - assert(f3.call("this_val"), "this_val"); - assert(new f4(), f4); + assert(f2.call("this_val") === "this_val"); + assert(f3.call("this_val") === "this_val"); + assert(new f4() === f4); var o1 = { f() { return this; } }; var o2 = { f() { @@ -144,7 +145,7 @@ function test_arrow_function() } }; o2.__proto__ = o1; - assert(o2.f(), o2); + assert(o2.f() === o2); } function test_with() @@ -152,20 +153,20 @@ function test_with() var o1 = { x: "o1", y: "o1" }; var x = "local"; eval('var z="var_obj";'); - assert(z, "var_obj"); + assert(z === "var_obj"); with (o1) { - assert(x, "o1"); - assert(eval("x"), "o1"); + assert(x === "o1"); + assert(eval("x") === "o1"); var f = function () { o2 = { x: "o2" }; with (o2) { - assert(x, "o2"); - assert(y, "o1"); - assert(z, "var_obj"); - assert(eval("x"), "o2"); - assert(eval("y"), "o1"); - assert(eval("z"), "var_obj"); - assert(eval('eval("x")'), "o2"); + assert(x === "o2"); + assert(y === "o1"); + assert(z === "var_obj"); + assert(eval("x") === "o2"); + assert(eval("y") === "o1"); + assert(eval("z") === "var_obj"); + assert(eval('eval("x")') === "o2"); } }; f(); @@ -181,7 +182,7 @@ function test_eval_closure() eval("tab.push(function g1() { return i; })"); } for(let i = 0; i < 3; i++) { - assert(tab[i](), i); + assert(tab[i]() === i); } tab = []; @@ -192,7 +193,7 @@ function test_eval_closure() f(); } for(let i = 0; i < 3; i++) { - assert(tab[i](), i); + assert(tab[i]() === i); } } diff --git a/quickjs-ng/tests/test_cyclic_import.js b/quickjs/tests/test_cyclic_import.js similarity index 100% rename from quickjs-ng/tests/test_cyclic_import.js rename to quickjs/tests/test_cyclic_import.js diff --git a/quickjs-ng/tests/test_language.js b/quickjs/tests/test_language.js similarity index 62% rename from quickjs-ng/tests/test_language.js rename to quickjs/tests/test_language.js index dbb4947..4fa16c8 100644 --- a/quickjs-ng/tests/test_language.js +++ b/quickjs/tests/test_language.js @@ -1,14 +1,8 @@ -// This test cannot use imports because it needs to run in non-strict mode. - function assert(actual, expected, message) { if (arguments.length == 1) expected = true; - if (actual === expected) - return; - - if (typeof actual == 'number' && isNaN(actual) - && typeof expected == 'number' && isNaN(expected)) + if (Object.is(actual, expected)) return; if (actual !== null && expected !== null @@ -16,35 +10,30 @@ function assert(actual, expected, message) { && actual.toString() === expected.toString()) return; - var msg = message ? " (" + message + ")" : ""; throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + msg); + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); } -function assert_throws(expected_error, func, message) +function assert_throws(expected_error, func) { var err = false; - var msg = message ? " (" + message + ")" : ""; try { - switch (typeof func) { - case 'string': - eval(func); - break; - case 'function': - func(); - break; - } + func(); } catch(e) { err = true; if (!(e instanceof expected_error)) { - throw Error(`expected ${expected_error.name}, got ${e.name}${msg}`); + throw Error("unexpected exception type"); } } if (!err) { - throw Error(`expected ${expected_error.name}${msg}`); + throw Error("expected exception"); } } +// load more elaborate version of assert if available +try { __loadScript("test_assert.js"); } catch(e) {} + /*----------------*/ function test_op1() @@ -118,20 +107,20 @@ function test_op1() function test_cvt() { - assert((NaN | 0), 0); - assert((Infinity | 0), 0); - assert(((-Infinity) | 0), 0); - assert(("12345" | 0), 12345); - assert(("0x12345" | 0), 0x12345); - assert(((4294967296 * 3 - 4) | 0), -4); - - assert(("12345" >>> 0), 12345); - assert(("0x12345" >>> 0), 0x12345); - assert((NaN >>> 0), 0); - assert((Infinity >>> 0), 0); - assert(((-Infinity) >>> 0), 0); - assert(((4294967296 * 3 - 4) >>> 0), (4294967296 - 4)); - assert((19686109595169230000).toString(), "19686109595169230000"); + assert((NaN | 0) === 0); + assert((Infinity | 0) === 0); + assert(((-Infinity) | 0) === 0); + assert(("12345" | 0) === 12345); + assert(("0x12345" | 0) === 0x12345); + assert(((4294967296 * 3 - 4) | 0) === -4); + + assert(("12345" >>> 0) === 12345); + assert(("0x12345" >>> 0) === 0x12345); + assert((NaN >>> 0) === 0); + assert((Infinity >>> 0) === 0); + assert(((-Infinity) >>> 0) === 0); + assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4)); + assert((19686109595169230000).toString() === "19686109595169230000"); } function test_eq() @@ -316,50 +305,43 @@ function test_class() } } - assert(C.F(), -1); + assert(C.F() === -1); assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y"); o = new C(); - assert(o.f(), 1); - assert(o.x, 10); + assert(o.f() === 1); + assert(o.x === 10); - assert(D.F(), -1); - assert(D.G(), -2); - assert(D.H(), -1); + assert(D.F() === -1); + assert(D.G() === -2); + assert(D.H() === -1); o = new D(); - assert(o.f(), 1); - assert(o.g(), 2); - assert(o.x, 10); - assert(o.z, 20); - assert(o.h(), 1); + assert(o.f() === 1); + assert(o.g() === 2); + assert(o.x === 10); + assert(o.z === 20); + assert(o.h() === 1); /* test class name scope */ var E1 = class E { static F() { return E; } }; - assert(E1, E1.F()); + assert(E1 === E1.F()); class S { static x = 42; static y = S.x; static z = this.x; } - assert(S.x, 42); - assert(S.y, 42); - assert(S.z, 42); - + assert(S.x === 42); + assert(S.y === 42); + assert(S.z === 42); + class P { - get; - set; - async; get = () => "123"; - set = () => "456"; - async = () => "789"; static() { return 42; } } - assert(new P().get(), "123"); - assert(new P().set(), "456"); - assert(new P().async(), "789"); - assert(new P().static(), 42); + assert(new P().get() === "123"); + assert(new P().static() === 42); }; function test_template() @@ -389,7 +371,7 @@ function test_object_literal() var x = 0, get = 1, set = 2; async = 3; a = { get: 2, set: 3, async: 4, get a(){ return this.get} }; assert(JSON.stringify(a), '{"get":2,"set":3,"async":4,"a":2}'); - assert(a.a, 2); + assert(a.a === 2); a = { x, get, set, async }; assert(JSON.stringify(a), '{"x":0,"get":1,"set":2,"async":3}'); @@ -399,10 +381,10 @@ function test_regexp_skip() { var a, b; [a, b = /abc\(/] = [1]; - assert(a, 1); + assert(a === 1); [a, b =/abc\(/] = [2]; - assert(a, 2); + assert(a === 2); } function test_labels() @@ -416,6 +398,24 @@ function test_labels() while (0) x: { break x; }; } +function test_labels2() +{ + while (1) label: break + var i = 0 + while (i < 3) label: { + if (i > 0) + break + i++ + } + assert(i, 1) + for (;;) label: break + for (i = 0; i < 3; i++) label: { + if (i > 0) + break + } + assert(i, 1) +} + function test_destructuring() { function * g () { return 0; }; @@ -446,10 +446,12 @@ function test_argument_scope() var f; var c = "global"; - f = function(a = eval("var arguments")) {}; - // for some reason v8 does not throw an exception here - if (typeof require === 'undefined') + (function() { + "use strict"; + // XXX: node only throws in strict mode + f = function(a = eval("var arguments")) {}; assert_throws(SyntaxError, f); + })(); f = function(a = eval("1"), b = arguments[0]) { return b; }; assert(f(12), 12); @@ -564,105 +566,35 @@ function test_function_expr_name() assert_throws(TypeError, f); } -function test_expr(expr, err) { - if (err) - assert_throws(err, expr, `for ${expr}`); - else - assert(1, eval(expr), `for ${expr}`); -} - -function test_name(name, err) -{ - test_expr(`(function() { return typeof ${name} ? 1 : 1; })()`); - test_expr(`(function() { var ${name}; ${name} = 1; return ${name}; })()`); - test_expr(`(function() { let ${name}; ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined); - test_expr(`(function() { const ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined); - test_expr(`(function(${name}) { ${name} = 1; return ${name}; })()`); - test_expr(`(function({${name}}) { ${name} = 1; return ${name}; })({})`); - test_expr(`(function ${name}() { return ${name} ? 1 : 0; })()`); - test_expr(`"use strict"; (function() { return typeof ${name} ? 1 : 1; })()`, err); - test_expr(`"use strict"; (function() { if (0) ${name} = 1; return 1; })()`, err); - test_expr(`"use strict"; (function() { var x; if (0) x = ${name}; return 1; })()`, err); - test_expr(`"use strict"; (function() { var ${name}; return 1; })()`, err); - test_expr(`"use strict"; (function() { let ${name}; return 1; })()`, err); - test_expr(`"use strict"; (function() { const ${name} = 1; return 1; })()`, err); - test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return 1; })()`, err); - test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return ${name}; })()`, err); - test_expr(`"use strict"; (function(${name}) { return 1; })()`, err); - test_expr(`"use strict"; (function({${name}}) { return 1; })({})`, err); - test_expr(`"use strict"; (function ${name}() { return 1; })()`, err); - test_expr(`(function() { "use strict"; return typeof ${name} ? 1 : 1; })()`, err); - test_expr(`(function() { "use strict"; if (0) ${name} = 1; return 1; })()`, err); - test_expr(`(function() { "use strict"; var x; if (0) x = ${name}; return 1; })()`, err); - test_expr(`(function() { "use strict"; var ${name}; return 1; })()`, err); - test_expr(`(function() { "use strict"; let ${name}; return 1; })()`, err); - test_expr(`(function() { "use strict"; const ${name} = 1; return 1; })()`, err); - test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return 1; })()`, err); - test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return ${name}; })()`, err); - test_expr(`(function(${name}) { "use strict"; return 1; })()`, err); - test_expr(`(function({${name}}) { "use strict"; return 1; })({})`, SyntaxError); - test_expr(`(function ${name}() { "use strict"; return 1; })()`, err); -} - -function test_reserved_names() -{ - test_name('await'); - test_name('yield', SyntaxError); - test_name('implements', SyntaxError); - test_name('interface', SyntaxError); - test_name('let', SyntaxError); - test_name('package', SyntaxError); - test_name('private', SyntaxError); - test_name('protected', SyntaxError); - test_name('public', SyntaxError); - test_name('static', SyntaxError); -} - -function test_number_literals() +function test_parse_semicolon() { - assert(0.1.a, undefined); - assert(0x1.a, undefined); - assert(0b1.a, undefined); - assert(01.a, undefined); - assert(0o1.a, undefined); - test_expr('0.a', SyntaxError); - assert(parseInt("0_1"), 0); - assert(parseInt("1_0"), 1); - assert(parseInt("0_1", 8), 0); - assert(parseInt("1_0", 8), 1); - assert(parseFloat("0_1"), 0); - assert(parseFloat("1_0"), 1); - assert(1_0, 10); - assert(parseInt("Infinity"), NaN); - assert(parseFloat("Infinity"), Infinity); - assert(parseFloat("Infinity1"), Infinity); - assert(parseFloat("Infinity_"), Infinity); - assert(parseFloat("Infinity."), Infinity); - test_expr('0_0', SyntaxError); - test_expr('00_0', SyntaxError); - test_expr('01_0', SyntaxError); - test_expr('08_0', SyntaxError); - test_expr('09_0', SyntaxError); + /* 'yield' or 'await' may not be considered as a token if the + previous ';' is missing */ + function *f() + { + function func() { + } + yield 1; + var h = x => x + 1 + yield 2; + } + async function g() + { + function func() { + } + await 1; + var h = x => x + 1 + await 2; + } } -function test_syntax() +function test_parse_arrow_function() { - assert_throws(SyntaxError, "do"); - assert_throws(SyntaxError, "do;"); - assert_throws(SyntaxError, "do{}"); - assert_throws(SyntaxError, "if"); - assert_throws(SyntaxError, "if\n"); - assert_throws(SyntaxError, "if 1"); - assert_throws(SyntaxError, "if \0"); - assert_throws(SyntaxError, "if ;"); - assert_throws(SyntaxError, "if 'abc'"); - assert_throws(SyntaxError, "if `abc`"); - assert_throws(SyntaxError, "if /abc/"); - assert_throws(SyntaxError, "if abc"); - assert_throws(SyntaxError, "if abc\u0064"); - assert_throws(SyntaxError, "if abc\\u0064"); - assert_throws(SyntaxError, "if \u0123"); - assert_throws(SyntaxError, "if \\u0123"); + assert(typeof eval("() => {}\n() => {}"), "function"); + assert(eval("() => {}\n+1"), 1); + assert(typeof eval("x => {}\n() => {}"), "function"); + assert(typeof eval("async () => {}\n() => {}"), "function"); + assert(typeof eval("async x => {}\n() => {}"), "function"); } /* optional chaining tests not present in test262 */ @@ -690,26 +622,10 @@ function test_optional_chaining() assert((a?.["b"])().c, 42); } -function test_parse_semicolon() +function test_unicode_ident() { - /* 'yield' or 'await' may not be considered as a token if the - previous ';' is missing */ - function *f() - { - function func() { - } - yield 1; - var h = x => x + 1 - yield 2; - } - async function g() - { - function func() { - } - await 1; - var h = x => x + 1 - await 2; - } + var õ = 3; + assert(typeof õ, "undefined"); } test_op1(); @@ -726,13 +642,13 @@ test_template_skip(); test_object_literal(); test_regexp_skip(); test_labels(); +test_labels2(); test_destructuring(); test_spread(); test_function_length(); test_argument_scope(); test_function_expr_name(); -test_reserved_names(); -test_number_literals(); -test_syntax(); -test_optional_chaining(); test_parse_semicolon(); +test_optional_chaining(); +test_parse_arrow_function(); +test_unicode_ident(); diff --git a/quickjs-ng/tests/test_loop.js b/quickjs/tests/test_loop.js similarity index 86% rename from quickjs-ng/tests/test_loop.js rename to quickjs/tests/test_loop.js index 97fc2f6..8f1934d 100644 --- a/quickjs-ng/tests/test_loop.js +++ b/quickjs/tests/test_loop.js @@ -1,5 +1,3 @@ -// This test cannot use imports because it needs to run in non-strict mode. - function assert(actual, expected, message) { if (arguments.length == 1) expected = true; @@ -17,6 +15,9 @@ function assert(actual, expected, message) { (message ? " (" + message + ")" : "")); } +// load more elaborate version of assert if available +try { __loadScript("test_assert.js"); } catch(e) {} + /*----------------*/ function test_while() @@ -28,7 +29,7 @@ function test_while() c++; i++; } - assert(c, 3); + assert(c === 3); } function test_while_break() @@ -148,7 +149,7 @@ function test_for_in() function test_for_in2() { - var i; + var i, tab; tab = []; for(i in {x:1, y: 2, z:3}) { if (i === "y") @@ -166,6 +167,29 @@ function test_for_in2() assert(tab.toString() == "x,y"); } +function test_for_in_proxy() { + let removed_key = ""; + let target = {} + let proxy = new Proxy(target, { + ownKeys: function() { + return ["a", "b", "c"]; + }, + getOwnPropertyDescriptor: function(target, key) { + if (removed_key != "" && key == removed_key) + return undefined; + else + return { enumerable: true, configurable: true, value: this[key] }; + } + }); + let str = ""; + for(let o in proxy) { + str += " " + o; + if (o == "a") + removed_key = "b"; + } + assert(str == " a c"); +} + function test_for_break() { var i, c; @@ -347,6 +371,16 @@ function test_try_catch8() assert(s === "xafyaf"); } +function test_cyclic_labels() +{ + /* just check that it compiles without a crash */ + for (;;) { + l: break l; + l: break l; + l: break l; + } +} + test_while(); test_while_break(); test_do_while(); @@ -356,6 +390,7 @@ test_switch1(); test_switch2(); test_for_in(); test_for_in2(); +test_for_in_proxy(); test_try_catch1(); test_try_catch2(); diff --git a/quickjs-ng/tests/test_std.js b/quickjs/tests/test_std.js similarity index 52% rename from quickjs-ng/tests/test_std.js rename to quickjs/tests/test_std.js index 2b24f64..3debe40 100644 --- a/quickjs-ng/tests/test_std.js +++ b/quickjs/tests/test_std.js @@ -1,10 +1,28 @@ -import * as std from "qjs:std"; -import * as os from "qjs:os"; -import { assert } from "./assert.js"; +#! (shebang test) +import * as std from "std"; +import * as os from "os"; -const isWin = os.platform === 'win32'; -const isCygwin = os.platform === 'cygwin'; +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + if (Object.is(actual, expected)) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +// load more elaborate version of assert if available +try { std.loadScript("test_assert.js"); } catch(e) {} + +/*----------------*/ function test_printf() { @@ -19,31 +37,27 @@ function test_printf() function test_file1() { - var f, len, str, size, buf, ret, i, str1, ab; + var f, len, str, size, buf, ret, i, str1; f = std.tmpfile(); str = "hello world\n"; f.puts(str); - f.seek(0, std.SEEK_SET); - ab = f.readAsArrayBuffer(); - assert([...new Uint8Array(ab)], str.split("").map(c => c.charCodeAt(0))); - f.seek(0, std.SEEK_SET); str1 = f.readAsString(); - assert(str1, str); + assert(str1 === str); f.seek(0, std.SEEK_END); size = f.tell(); - assert(size, str.length); + assert(size === str.length); f.seek(0, std.SEEK_SET); buf = new Uint8Array(size); ret = f.read(buf.buffer, 0, size); - assert(ret, size); + assert(ret === size); for(i = 0; i < size; i++) - assert(buf[i], str.charCodeAt(i)); + assert(buf[i] === str.charCodeAt(i)); f.close(); } @@ -58,9 +72,9 @@ function test_file2() f.putByte(str.charCodeAt(i)); f.seek(0, std.SEEK_SET); for(i = 0; i < size; i++) { - assert(str.charCodeAt(i), f.getByte()); + assert(str.charCodeAt(i) === f.getByte()); } - assert(f.getByte(), -1); + assert(f.getByte() === -1); f.close(); } @@ -81,11 +95,11 @@ function test_getline() line = f.getline(); if (line === null) break; - assert(line, lines[line_count]); + assert(line == lines[line_count]); line_count++; } assert(f.eof()); - assert(line_count, lines.length); + assert(line_count === lines.length); f.close(); } @@ -93,30 +107,17 @@ function test_getline() function test_popen() { var str, f, fname = "tmp_file.txt"; - var ta, content = "hello world"; - var cmd = isWin ? "type" : "cat"; + var content = "hello world"; - ta = new Uint8Array([...content].map(c => c.charCodeAt(0))); - std.writeFile(fname, ta); - assert(std.loadFile(fname), content); - std.writeFile(fname, ta.buffer); - assert(std.loadFile(fname), content); - std.writeFile(fname, content); - assert(std.loadFile(fname), content); + f = std.open(fname, "w"); + f.puts(content); + f.close(); - // popen pipe is unidirectional so mode should - // be either read or write but not both - let caught = false; - try { - std.popen(cmd, "rw"); - } catch (e) { - assert(/invalid file mode/.test(e.message)); - caught = true; - } - assert(caught); + /* test loadFile */ + assert(std.loadFile(fname), content); - /* execute shell command */ - f = std.popen(cmd + " " + fname, "r"); + /* execute the 'cat' shell command */ + f = std.popen("cat " + fname, "r"); str = f.readAsString(); f.close(); @@ -125,12 +126,39 @@ function test_popen() os.remove(fname); } +function test_ext_json() +{ + var expected, input, obj; + expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"b":"abc\\u000bd","s":"str"}'; + input = `{ "x":false, /*comments are allowed */ + "y":true, // also a comment + z2:null, // unquoted property names + "a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal + "b": "ab\ +c\\vd", // multi-line strings, '\v' escape + "s":'str',} // trailing comma in objects and arrays, single quoted string + `; + obj = std.parseExtJSON(input); + assert(JSON.stringify(obj), expected); + + obj = std.parseExtJSON('[Infinity, +Infinity, -Infinity, NaN, +NaN, -NaN, .1, -.2]'); + assert(obj[0], Infinity); + assert(obj[1], Infinity); + assert(obj[2], -Infinity); + assert(obj[3], NaN); + assert(obj[4], NaN); + assert(obj[5], NaN); + assert(obj[6], 0.1); + assert(obj[7], -0.2); +} + function test_os() { var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; - // XXX(bnoordhuis) disabled because stdio is not a tty on CI - //assert(os.isatty(0)); + const stdinIsTTY = !os.exec(["/bin/sh", "-c", "test -t 0"], { usePath: false }); + + assert(os.isatty(0), stdinIsTTY, `isatty(STDIN)`); fdir = "test_tmp_dir"; fname = "tmp_file.txt"; @@ -142,7 +170,7 @@ function test_os() os.remove(fdir); err = os.mkdir(fdir, 0o755); - assert(err, 0); + assert(err === 0); fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); assert(fd >= 0); @@ -150,29 +178,26 @@ function test_os() buf = new Uint8Array(10); for(i = 0; i < buf.length; i++) buf[i] = i; - assert(os.write(fd, buf.buffer, 0, buf.length), buf.length); + assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); - assert(os.seek(fd, 0, std.SEEK_SET), 0); + assert(os.seek(fd, 0, std.SEEK_SET) === 0); buf2 = new Uint8Array(buf.length); - assert(os.read(fd, buf2.buffer, 0, buf2.length), buf2.length); + assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); for(i = 0; i < buf.length; i++) assert(buf[i] == buf2[i]); if (typeof BigInt !== "undefined") { assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6)); - assert(os.read(fd, buf2.buffer, 0, 1), 1); + assert(os.read(fd, buf2.buffer, 0, 1) === 1); assert(buf[6] == buf2[0]); } - assert(os.close(fd), 0); + assert(os.close(fd) === 0); [files, err] = os.readdir(fdir); assert(err, 0); - assert(files.length >= 3); - assert(files.includes(fname)); - assert(files.includes(".")); - assert(files.includes("..")); + assert(files.indexOf(fname) >= 0); fdate = 10000; @@ -184,20 +209,18 @@ function test_os() assert(st.mode & os.S_IFMT, os.S_IFREG); assert(st.mtime, fdate); - if (!isWin) { - err = os.symlink(fname, link_path); - assert(err, 0); + err = os.symlink(fname, link_path); + assert(err === 0); - [st, err] = os.lstat(link_path); - assert(err, 0); - assert(st.mode & os.S_IFMT, os.S_IFLNK); + [st, err] = os.lstat(link_path); + assert(err, 0); + assert(st.mode & os.S_IFMT, os.S_IFLNK); - [buf, err] = os.readlink(link_path); - assert(err, 0); - assert(buf, fname); + [buf, err] = os.readlink(link_path); + assert(err, 0); + assert(buf, fname); - assert(os.remove(link_path) === 0); - } + assert(os.remove(link_path) === 0); [buf, err] = os.getcwd(); assert(err, 0); @@ -247,23 +270,11 @@ function test_os_exec() os.kill(pid, os.SIGTERM); [ret, status] = os.waitpid(pid, 0); assert(ret, pid); - // Flaky on cygwin for unclear reasons, see - // https://github.com/quickjs-ng/quickjs/issues/184 - if (!isCygwin) { - assert(status & 0x7f, os.SIGTERM); - } -} - -function test_interval() -{ - var t = os.setInterval(f, 1); - function f() { - if (++f.count === 3) os.clearInterval(t); - } - f.count = 0; + assert(status !== 0, true, `expect nonzero exit code (got ${status})`); + assert(status & 0x7f, os.SIGTERM); } -function test_timeout() +function test_timer() { var th, i; @@ -275,30 +286,40 @@ function test_timeout() os.clearTimeout(th[i]); } -function test_timeout_order() +/* test closure variable handling when freeing asynchronous + function */ +function test_async_gc() { - var s = ""; - os.setTimeout(a, 0); - os.setTimeout(b, 100); - os.setTimeout(d, 700); - function a() { s += "a"; os.setTimeout(c, 300); } - function b() { s += "b"; } - function c() { s += "c"; } - function d() { assert(s, "abc"); } // not "acb" + (async function run () { + let obj = {} + + let done = () => { + obj + std.gc(); + } + + Promise.resolve().then(done) + + const p = new Promise(() => {}) + + await p + })(); } -function test_stdio_close() +/* check that the promise async rejection handler is not invoked when + the rejection is handled not too late after the promise + rejection. */ +function test_async_promise_rejection() { - for (const f of [std.in, std.out, std.err]) { - let caught = false; - try { - f.close(); - } catch (e) { - assert(/cannot close stdio/.test(e.message)); - caught = true; - } - assert(caught); - } + var counter = 0; + var p1, p2, p3; + p1 = Promise.reject(); + p2 = Promise.reject(); + p3 = Promise.resolve(); + p1.catch(() => counter++); + p2.catch(() => counter++); + p3.then(() => counter++) + os.setTimeout(() => { assert(counter, 3) }, 10); } test_printf(); @@ -307,8 +328,9 @@ test_file2(); test_getline(); test_popen(); test_os(); -!isWin && test_os_exec(); -test_interval(); -test_timeout(); -test_timeout_order(); -test_stdio_close(); +test_os_exec(); +test_timer(); +test_ext_json(); +test_async_gc(); +test_async_promise_rejection(); + diff --git a/quickjs-ng/tests/test_worker.js b/quickjs/tests/test_worker.js similarity index 64% rename from quickjs-ng/tests/test_worker.js rename to quickjs/tests/test_worker.js index d1660ce..4b52bf8 100644 --- a/quickjs-ng/tests/test_worker.js +++ b/quickjs/tests/test_worker.js @@ -1,5 +1,23 @@ -import * as os from "qjs:os"; -import { assert } from "./assert.js"; +/* os.Worker API test */ +import * as std from "std"; +import * as os from "os"; + +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} var worker; @@ -40,4 +58,5 @@ function test_worker() }; } + test_worker(); diff --git a/quickjs-ng/tests/test_worker_module.js b/quickjs/tests/test_worker_module.js similarity index 84% rename from quickjs-ng/tests/test_worker_module.js rename to quickjs/tests/test_worker_module.js index 7280c69..ddf8e40 100644 --- a/quickjs-ng/tests/test_worker_module.js +++ b/quickjs/tests/test_worker_module.js @@ -1,5 +1,6 @@ /* Worker code for test_worker.js */ -import * as os from "qjs:os"; +import * as std from "std"; +import * as os from "os"; var parent = os.Worker.parent; @@ -9,6 +10,7 @@ function handle_msg(e) { switch(ev.type) { case "abort": parent.postMessage({ type: "done" }); + parent.onmessage = null; /* terminate the worker */ break; case "sab": /* modify the SharedArrayBuffer */ diff --git a/quickjs/unicode_download.sh b/quickjs/unicode_download.sh new file mode 100755 index 0000000..ef8b30d --- /dev/null +++ b/quickjs/unicode_download.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +version="16.0.0" +emoji_version="16.0" +url="ftp://ftp.unicode.org/Public" + +files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ +SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \ +UnicodeData.txt DerivedCoreProperties.txt NormalizationTest.txt Scripts.txt \ +PropertyValueAliases.txt" + +mkdir -p unicode + +for f in $files; do + g="${url}/${version}/ucd/${f}" + wget $g -O unicode/$f +done + +wget "${url}/${version}/ucd/emoji/emoji-data.txt" -O unicode/emoji-data.txt + +wget "${url}/emoji/${emoji_version}/emoji-sequences.txt" -O unicode/emoji-sequences.txt +wget "${url}/emoji/${emoji_version}/emoji-zwj-sequences.txt" -O unicode/emoji-zwj-sequences.txt diff --git a/quickjs-ng/unicode_gen.c b/quickjs/unicode_gen.c similarity index 78% rename from quickjs-ng/unicode_gen.c rename to quickjs/unicode_gen.c index cb46fbc..c793ba1 100644 --- a/quickjs-ng/unicode_gen.c +++ b/quickjs/unicode_gen.c @@ -33,6 +33,11 @@ #include "cutils.h" +uint32_t total_tables; +uint32_t total_table_bytes; +uint32_t total_index; +uint32_t total_index_bytes; + /* define it to be able to test unicode.c */ //#define USE_TEST /* profile tests */ @@ -151,6 +156,153 @@ char *get_line(char *buf, int buf_size, FILE *f) return buf; } +typedef struct REString { + struct REString *next; + uint32_t hash; + uint32_t len; + uint32_t flags; + uint32_t buf[]; +} REString; + +typedef struct { + uint32_t n_strings; + uint32_t hash_size; + int hash_bits; + REString **hash_table; +} REStringList; + +static uint32_t re_string_hash(int len, const uint32_t *buf) +{ + int i; + uint32_t h; + h = 1; + for(i = 0; i < len; i++) + h = h * 263 + buf[i]; + return h * 0x61C88647; +} + +static void re_string_list_init(REStringList *s) +{ + s->n_strings = 0; + s->hash_size = 0; + s->hash_bits = 0; + s->hash_table = NULL; +} + +static __maybe_unused void re_string_list_free(REStringList *s) +{ + REString *p, *p_next; + int i; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + free(p); + } + } + free(s->hash_table); +} + +static void lre_print_char(int c, BOOL is_range) +{ + if (c == '\'' || c == '\\' || + (is_range && (c == '-' || c == ']'))) { + printf("\\%c", c); + } else if (c >= ' ' && c <= 126) { + printf("%c", c); + } else { + printf("\\u{%04x}", c); + } +} + +static __maybe_unused void re_string_list_dump(const char *str, const REStringList *s) +{ + REString *p; + int i, j, k; + + printf("%s:\n", str); + + j = 0; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p->next) { + printf(" %d/%d: '", j, s->n_strings); + for(k = 0; k < p->len; k++) { + lre_print_char(p->buf[k], FALSE); + } + printf("'\n"); + j++; + } + } +} + +static REString *re_string_find2(REStringList *s, int len, const uint32_t *buf, + uint32_t h0, BOOL add_flag) +{ + uint32_t h = 0; /* avoid warning */ + REString *p; + if (s->n_strings != 0) { + h = h0 >> (32 - s->hash_bits); + for(p = s->hash_table[h]; p != NULL; p = p->next) { + if (p->hash == h0 && p->len == len && + !memcmp(p->buf, buf, len * sizeof(buf[0]))) { + return p; + } + } + } + /* not found */ + if (!add_flag) + return NULL; + /* increase the size of the hash table if needed */ + if (unlikely((s->n_strings + 1) > s->hash_size)) { + REString **new_hash_table, *p_next; + int new_hash_bits, i; + uint32_t new_hash_size; + new_hash_bits = max_int(s->hash_bits + 1, 4); + new_hash_size = 1 << new_hash_bits; + new_hash_table = malloc(sizeof(new_hash_table[0]) * new_hash_size); + if (!new_hash_table) + return NULL; + memset(new_hash_table, 0, sizeof(new_hash_table[0]) * new_hash_size); + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + h = p->hash >> (32 - new_hash_bits); + p->next = new_hash_table[h]; + new_hash_table[h] = p; + } + } + free(s->hash_table); + s->hash_bits = new_hash_bits; + s->hash_size = new_hash_size; + s->hash_table = new_hash_table; + h = h0 >> (32 - s->hash_bits); + } + + p = malloc(sizeof(REString) + len * sizeof(buf[0])); + if (!p) + return NULL; + p->next = s->hash_table[h]; + s->hash_table[h] = p; + s->n_strings++; + p->hash = h0; + p->len = len; + p->flags = 0; + memcpy(p->buf, buf, sizeof(buf[0]) * len); + return p; +} + +static REString *re_string_find(REStringList *s, int len, const uint32_t *buf, + BOOL add_flag) +{ + uint32_t h0; + h0 = re_string_hash(len, buf); + return re_string_find2(s, len, buf, h0, add_flag); +} + +static void re_string_add(REStringList *s, int len, const uint32_t *buf) +{ + re_string_find(s, len, buf, TRUE); +} + #define UNICODE_GENERAL_CATEGORY typedef enum { @@ -220,6 +372,23 @@ static const char *unicode_prop_short_name[] = { #undef UNICODE_PROP_LIST +#define UNICODE_SEQUENCE_PROP_LIST + +typedef enum { +#define DEF(id) SEQUENCE_PROP_ ## id, +#include "unicode_gen_def.h" +#undef DEF + SEQUENCE_PROP_COUNT, +} UnicodeSequencePropEnum1; + +static const char *unicode_sequence_prop_name[] = { +#define DEF(id) #id, +#include "unicode_gen_def.h" +#undef DEF +}; + +#undef UNICODE_SEQUENCE_PROP_LIST + typedef struct { /* case conv */ uint8_t u_len; @@ -242,7 +411,15 @@ typedef struct { int *decomp_data; } CCInfo; +typedef struct { + int count; + int size; + int *tab; +} UnicodeSequenceProperties; + CCInfo *unicode_db; +REStringList rgi_emoji_zwj_sequence; +DynBuf rgi_emoji_tag_sequence; int find_name(const char **tab, int tab_len, const char *name) { @@ -268,7 +445,7 @@ int find_name(const char **tab, int tab_len, const char *name) return -1; } -static int get_prop(uint32_t c, int prop_idx) +static BOOL get_prop(uint32_t c, int prop_idx) { return (unicode_db[c].prop_bitmap_tab[prop_idx >> 5] >> (prop_idx & 0x1f)) & 1; } @@ -382,6 +559,20 @@ void parse_unicode_data(const char *filename) break; add_char(&ci->decomp_data, &size, &ci->decomp_len, strtoul(p, (char **)&p, 16)); } +#if 0 + { + int i; + static int count, d_count; + + printf("%05x: %c", code, ci->is_compat ? 'C': ' '); + for(i = 0; i < ci->decomp_len; i++) + printf(" %05x", ci->decomp_data[i]); + printf("\n"); + count++; + d_count += ci->decomp_len; + // printf("%d %d\n", count, d_count); + } +#endif } p = get_field(line, 9); @@ -567,7 +758,7 @@ void parse_composition_exclusions(const char *filename) continue; c0 = strtoul(p, (char **)&p, 16); assert(c0 > 0 && c0 <= CHARCODE_MAX); - unicode_db[c0].is_excluded = true; + unicode_db[c0].is_excluded = TRUE; } fclose(f); } @@ -606,8 +797,7 @@ void parse_derived_core_properties(const char *filename) p++; p += strspn(p, " \t"); q = buf; - static const char ignore[] = "\t #;"; // includes \0 - while (!memchr(ignore, *p, sizeof(ignore))) { + while (*p != '\0' && *p != ' ' && *p != '#' && *p != '\t' && *p != ';') { if ((q - buf) < sizeof(buf) - 1) *q++ = *p; p++; @@ -733,6 +923,147 @@ void parse_prop_list(const char *filename) fclose(f); } +#define SEQ_MAX_LEN 16 + +static BOOL is_emoji_modifier(uint32_t c) +{ + return (c >= 0x1f3fb && c <= 0x1f3ff); +} + +static void add_sequence_prop(int idx, int seq_len, int *seq) +{ + int i; + + assert(idx < SEQUENCE_PROP_COUNT); + switch(idx) { + case SEQUENCE_PROP_Basic_Emoji: + /* convert to 2 properties lists */ + if (seq_len == 1) { + set_prop(seq[0], PROP_Basic_Emoji1, 1); + } else if (seq_len == 2 && seq[1] == 0xfe0f) { + set_prop(seq[0], PROP_Basic_Emoji2, 1); + } else { + abort(); + } + break; + case SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence: + assert(seq_len == 2); + assert(is_emoji_modifier(seq[1])); + assert(get_prop(seq[0], PROP_Emoji_Modifier_Base)); + set_prop(seq[0], PROP_RGI_Emoji_Modifier_Sequence, 1); + break; + case SEQUENCE_PROP_RGI_Emoji_Flag_Sequence: + { + int code; + assert(seq_len == 2); + assert(seq[0] >= 0x1F1E6 && seq[0] <= 0x1F1FF); + assert(seq[1] >= 0x1F1E6 && seq[1] <= 0x1F1FF); + code = (seq[0] - 0x1F1E6) * 26 + (seq[1] - 0x1F1E6); + /* XXX: would be more compact with a simple bitmap -> 676 bits */ + set_prop(code, PROP_RGI_Emoji_Flag_Sequence, 1); + } + break; + case SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence: + re_string_add(&rgi_emoji_zwj_sequence, seq_len, (uint32_t *)seq); + break; + case SEQUENCE_PROP_RGI_Emoji_Tag_Sequence: + { + assert(seq_len >= 3); + assert(seq[0] == 0x1F3F4); + assert(seq[seq_len - 1] == 0xE007F); + for(i = 1; i < seq_len - 1; i++) { + assert(seq[i] >= 0xe0001 && seq[i] <= 0xe007e); + dbuf_putc(&rgi_emoji_tag_sequence, seq[i] - 0xe0000); + } + dbuf_putc(&rgi_emoji_tag_sequence, 0); + } + break; + case SEQUENCE_PROP_Emoji_Keycap_Sequence: + assert(seq_len == 3); + assert(seq[1] == 0xfe0f); + assert(seq[2] == 0x20e3); + set_prop(seq[0], PROP_Emoji_Keycap_Sequence, 1); + break; + default: + assert(0); + } +} + +void parse_sequence_prop_list(const char *filename) +{ + FILE *f; + char line[4096], *p, buf[256], *q, *p_start; + uint32_t c0, c1, c; + int idx, seq_len; + int seq[SEQ_MAX_LEN]; + + f = fopen(filename, "rb"); + if (!f) { + perror(filename); + exit(1); + } + + for(;;) { + if (!get_line(line, sizeof(line), f)) + break; + p = line; + while (isspace(*p)) + p++; + if (*p == '#' || *p == '@' || *p == '\0') + continue; + p_start = p; + + /* find the sequence property name */ + p = strchr(p, ';'); + if (!p) + continue; + p++; + p += strspn(p, " \t"); + q = buf; + while (*p != '\0' && *p != ' ' && *p != '#' && *p != '\t' && *p != ';') { + if ((q - buf) < sizeof(buf) - 1) + *q++ = *p; + p++; + } + *q = '\0'; + idx = find_name(unicode_sequence_prop_name, + countof(unicode_sequence_prop_name), buf); + if (idx < 0) { + fprintf(stderr, "Property not found: %s\n", buf); + exit(1); + } + + p = p_start; + c0 = strtoul(p, (char **)&p, 16); + assert(c0 <= CHARCODE_MAX); + + if (*p == '.' && p[1] == '.') { + p += 2; + c1 = strtoul(p, (char **)&p, 16); + assert(c1 <= CHARCODE_MAX); + for(c = c0; c <= c1; c++) { + seq[0] = c; + add_sequence_prop(idx, 1, seq); + } + } else { + seq_len = 0; + seq[seq_len++] = c0; + for(;;) { + while (isspace(*p)) + p++; + if (*p == ';' || *p == '\0') + break; + c0 = strtoul(p, (char **)&p, 16); + assert(c0 <= CHARCODE_MAX); + assert(seq_len < countof(seq)); + seq[seq_len++] = c0; + } + add_sequence_prop(idx, seq_len, seq); + } + } + fclose(f); +} + void parse_scripts(const char *filename) { FILE *f; @@ -887,7 +1218,7 @@ void dump_unicode_data(CCInfo *tab) } } -bool is_complicated_case(const CCInfo *ci) +BOOL is_complicated_case(const CCInfo *ci) { return (ci->u_len > 1 || ci->l_len > 1 || (ci->u_len > 0 && ci->l_len > 0) || @@ -1234,6 +1565,12 @@ void build_conv_table(CCInfo *tab) continue; assert(te - conv_table < countof(conv_table)); find_run_type(te, tab, code); +#if 0 + if (te->type == RUN_TYPE_TODO) { + printf("TODO: "); + dump_cc_info(ci, code); + } +#endif assert(te->len <= 127); code += te->len - 1; te++; @@ -1327,7 +1664,9 @@ void dump_case_conv_table(FILE *f) uint32_t v; const TableEntry *te; - fprintf(f, "static const uint32_t case_conv_table1[%u] = {", conv_table_len); + total_tables++; + total_table_bytes += conv_table_len * sizeof(uint32_t); + fprintf(f, "static const uint32_t case_conv_table1[%d] = {", conv_table_len); for(i = 0; i < conv_table_len; i++) { if (i % 4 == 0) fprintf(f, "\n "); @@ -1340,7 +1679,9 @@ void dump_case_conv_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint8_t case_conv_table2[%u] = {", conv_table_len); + total_tables++; + total_table_bytes += conv_table_len; + fprintf(f, "static const uint8_t case_conv_table2[%d] = {", conv_table_len); for(i = 0; i < conv_table_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -1349,7 +1690,9 @@ void dump_case_conv_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint16_t case_conv_ext[%u] = {", ext_data_len); + total_tables++; + total_table_bytes += ext_data_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t case_conv_ext[%d] = {", ext_data_len); for(i = 0; i < ext_data_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -1428,7 +1771,7 @@ void dump_str(const char *str, const int *buf, int len) void compute_internal_props(void) { int i; - bool has_ul; + BOOL has_ul; for(i = 0; i <= CHARCODE_MAX; i++) { CCInfo *ci = &unicode_db[i]; @@ -1451,12 +1794,27 @@ void compute_internal_props(void) /* XXX: reduce table size (438 bytes) */ set_prop(i, PROP_Changes_When_NFKC_Casefolded1, get_prop(i, PROP_Changes_When_NFKC_Casefolded) ^ (ci->f_len != 0)); +#if 0 + /* TEST */ +#define M(x) (1U << GCAT_ ## x) + { + int b; + b = ((M(Mn) | M(Cf) | M(Lm) | M(Sk)) >> + unicode_db[i].general_category) & 1; + set_prop(i, PROP_Cased1, + get_prop(i, PROP_Case_Ignorable) ^ b); + } +#undef M +#endif } } void dump_byte_table(FILE *f, const char *cname, const uint8_t *tab, int len) { int i; + + total_tables++; + total_table_bytes += len; fprintf(f, "static const uint8_t %s[%d] = {", cname, len); for(i = 0; i < len; i++) { if (i % 8 == 0) @@ -1466,9 +1824,26 @@ void dump_byte_table(FILE *f, const char *cname, const uint8_t *tab, int len) fprintf(f, "\n};\n\n"); } +void dump_index_table(FILE *f, const char *cname, const uint8_t *tab, int len) +{ + int i, code, offset; + + total_index++; + total_index_bytes += len; + fprintf(f, "static const uint8_t %s[%d] = {\n", cname, len); + for(i = 0; i < len; i += 3) { + code = tab[i] + (tab[i+1] << 8) + ((tab[i+2] & 0x1f) << 16); + offset = ((i / 3) + 1) * 32 + (tab[i+2] >> 5); + fprintf(f, " 0x%02x, 0x%02x, 0x%02x,", tab[i], tab[i+1], tab[i+2]); + fprintf(f, " // %6.5X at %d%s\n", code, offset, + i == len - 3 ? " (upper bound)" : ""); + } + fprintf(f, "};\n\n"); +} + #define PROP_BLOCK_LEN 32 -void build_prop_table(FILE *f, int prop_index, bool add_index) +void build_prop_table(FILE *f, const char *name, int prop_index, BOOL add_index) { int i, j, n, v, offset, code; DynBuf dbuf_s, *dbuf = &dbuf_s; @@ -1520,6 +1895,14 @@ void build_prop_table(FILE *f, int prop_index, bool add_index) block_end_pos += PROP_BLOCK_LEN; } + /* Compressed byte encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ v = buf[i]; code += v + 1; bit ^= 1; @@ -1560,7 +1943,7 @@ void build_prop_table(FILE *f, int prop_index, bool add_index) dump_byte_table(f, cname, dbuf->buf, dbuf->size); if (add_index) { snprintf(cname, sizeof(cname), "unicode_prop_%s_index", unicode_prop_name[prop_index]); - dump_byte_table(f, cname, dbuf2->buf, dbuf2->size); + dump_index_table(f, cname, dbuf2->buf, dbuf2->size); } dbuf_free(dbuf); @@ -1570,11 +1953,10 @@ void build_prop_table(FILE *f, int prop_index, bool add_index) void build_flags_tables(FILE *f) { - build_prop_table(f, PROP_Cased1, true); - build_prop_table(f, PROP_Case_Ignorable, true); - build_prop_table(f, PROP_ID_Start, true); - build_prop_table(f, PROP_ID_Continue1, true); - build_prop_table(f, PROP_White_Space, true); + build_prop_table(f, "Cased1", PROP_Cased1, TRUE); + build_prop_table(f, "Case_Ignorable", PROP_Case_Ignorable, TRUE); + build_prop_table(f, "ID_Start", PROP_ID_Start, TRUE); + build_prop_table(f, "ID_Continue1", PROP_ID_Continue1, TRUE); } void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len, @@ -1585,7 +1967,7 @@ void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len, maxw = 0; for(i = 0; i < len; i++) { w = strlen(tab_name[i]); - if (tab_short_name[i][0] != '\0') { + if (tab_short_name && tab_short_name[i][0] != '\0') { w += 1 + strlen(tab_short_name[i]); } if (maxw < w) @@ -1597,7 +1979,7 @@ void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len, for(i = 0; i < len; i++) { fprintf(f, " \""); w = fprintf(f, "%s", tab_name[i]); - if (tab_short_name[i][0] != '\0') { + if (tab_short_name && tab_short_name[i][0] != '\0') { w += fprintf(f, ",%s", tab_short_name[i]); } fprintf(f, "\"%*s\"\\0\"\n", 1 + maxw - w, ""); @@ -1609,7 +1991,9 @@ void build_general_category_table(FILE *f) { int i, v, j, n, n1; DynBuf dbuf_s, *dbuf = &dbuf_s; +#ifdef DUMP_TABLE_SIZE int cw_count, cw_len_count[4], cw_start; +#endif fprintf(f, "typedef enum {\n"); for(i = 0; i < GCAT_COUNT; i++) @@ -1623,9 +2007,11 @@ void build_general_category_table(FILE *f) dbuf_init(dbuf); +#ifdef DUMP_TABLE_SIZE cw_count = 0; for(i = 0; i < 4; i++) cw_len_count[i] = 0; +#endif for(i = 0; i <= CHARCODE_MAX;) { v = unicode_db[i].general_category; j = i + 1; @@ -1644,9 +2030,11 @@ void build_general_category_table(FILE *f) } } // printf("%05x %05x %d\n", i, n, v); - cw_count++; n--; +#ifdef DUMP_TABLE_SIZE + cw_count++; cw_start = dbuf->size; +#endif if (n < 7) { dbuf_putc(dbuf, (n << 5) | v); } else if (n < 7 + 128) { @@ -1668,12 +2056,13 @@ void build_general_category_table(FILE *f) dbuf_putc(dbuf, n1 >> 8); dbuf_putc(dbuf, n1); } +#ifdef DUMP_TABLE_SIZE cw_len_count[dbuf->size - cw_start - 1]++; +#endif i += n + 1; } #ifdef DUMP_TABLE_SIZE - printf("general category: %d entries [", - cw_count); + printf("general category: %d entries [", cw_count); for(i = 0; i < 4; i++) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); @@ -1688,7 +2077,9 @@ void build_script_table(FILE *f) { int i, v, j, n, n1, type; DynBuf dbuf_s, *dbuf = &dbuf_s; +#ifdef DUMP_TABLE_SIZE int cw_count, cw_len_count[4], cw_start; +#endif fprintf(f, "typedef enum {\n"); for(i = 0; i < SCRIPT_COUNT; i++) @@ -1696,15 +2087,16 @@ void build_script_table(FILE *f) fprintf(f, " UNICODE_SCRIPT_COUNT,\n"); fprintf(f, "} UnicodeScriptEnum;\n\n"); - i = 1; dump_name_table(f, "unicode_script_name_table", - unicode_script_name + i, SCRIPT_COUNT - i, - unicode_script_short_name + i); + unicode_script_name, SCRIPT_COUNT, + unicode_script_short_name); dbuf_init(dbuf); +#ifdef DUMP_TABLE_SIZE cw_count = 0; for(i = 0; i < 4; i++) cw_len_count[i] = 0; +#endif for(i = 0; i <= CHARCODE_MAX;) { v = unicode_db[i].script; j = i + 1; @@ -1714,9 +2106,11 @@ void build_script_table(FILE *f) if (v == 0 && j == (CHARCODE_MAX + 1)) break; // printf("%05x %05x %d\n", i, n, v); - cw_count++; n--; +#ifdef DUMP_TABLE_SIZE + cw_count++; cw_start = dbuf->size; +#endif if (v == 0) type = 0; else @@ -1738,12 +2132,13 @@ void build_script_table(FILE *f) if (type != 0) dbuf_putc(dbuf, v); +#ifdef DUMP_TABLE_SIZE cw_len_count[dbuf->size - cw_start - 1]++; +#endif i += n + 1; } -#if defined(DUMP_TABLE_SIZE) - printf("script: %d entries [", - cw_count); +#ifdef DUMP_TABLE_SIZE + printf("script: %d entries [", cw_count); for(i = 0; i < 4; i++) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); @@ -1758,10 +2153,11 @@ void build_script_ext_table(FILE *f) { int i, j, n, n1, script_ext_len; DynBuf dbuf_s, *dbuf = &dbuf_s; - int cw_count; +#if defined(DUMP_TABLE_SIZE) + int cw_count = 0; +#endif dbuf_init(dbuf); - cw_count = 0; for(i = 0; i <= CHARCODE_MAX;) { script_ext_len = unicode_db[i].script_ext_len; j = i + 1; @@ -1772,7 +2168,9 @@ void build_script_ext_table(FILE *f) j++; } n = j - i; +#if defined(DUMP_TABLE_SIZE) cw_count++; +#endif n--; if (n < 128) { dbuf_putc(dbuf, n); @@ -1794,8 +2192,7 @@ void build_script_ext_table(FILE *f) i += n + 1; } #ifdef DUMP_TABLE_SIZE - printf("script_ext: %d entries", - cw_count); + printf("script_ext: %d entries", cw_count); printf(", length=%d bytes\n", (int)dbuf->size); #endif @@ -1814,11 +2211,10 @@ void build_prop_list_table(FILE *f) for(i = 0; i < PROP_TABLE_COUNT; i++) { if (i == PROP_ID_Start || i == PROP_Case_Ignorable || - i == PROP_ID_Continue1 || - i == PROP_White_Space) { + i == PROP_ID_Continue1) { /* already generated */ } else { - build_prop_table(f, i, false); + build_prop_table(f, unicode_prop_name[i], i, FALSE); } } @@ -1846,6 +2242,218 @@ void build_prop_list_table(FILE *f) fprintf(f, "};\n\n"); } +static BOOL is_emoji_hair_color(uint32_t c) +{ + return (c >= 0x1F9B0 && c <= 0x1F9B3); +} + +#define EMOJI_MOD_NONE 0 +#define EMOJI_MOD_TYPE1 1 +#define EMOJI_MOD_TYPE2 2 +#define EMOJI_MOD_TYPE2D 3 + +static BOOL mark_zwj_string(REStringList *sl, uint32_t *buf, int len, int mod_type, int *mod_pos, + int hc_pos, BOOL mark_flag) +{ + REString *p; + int i, n_mod, i0, i1, hc_count, j; + +#if 0 + if (mark_flag) + printf("mod_type=%d\n", mod_type); +#endif + + switch(mod_type) { + case EMOJI_MOD_NONE: + n_mod = 1; + break; + case EMOJI_MOD_TYPE1: + n_mod = 5; + break; + case EMOJI_MOD_TYPE2: + n_mod = 25; + break; + case EMOJI_MOD_TYPE2D: + n_mod = 20; + break; + default: + assert(0); + } + if (hc_pos >= 0) + hc_count = 4; + else + hc_count = 1; + /* check that all the related strings are present */ + for(j = 0; j < hc_count; j++) { + for(i = 0; i < n_mod; i++) { + switch(mod_type) { + case EMOJI_MOD_NONE: + break; + case EMOJI_MOD_TYPE1: + buf[mod_pos[0]] = 0x1f3fb + i; + break; + case EMOJI_MOD_TYPE2: + case EMOJI_MOD_TYPE2D: + i0 = i / 5; + i1 = i % 5; + /* avoid identical values */ + if (mod_type == EMOJI_MOD_TYPE2D && i0 >= i1) + i0++; + buf[mod_pos[0]] = 0x1f3fb + i0; + buf[mod_pos[1]] = 0x1f3fb + i1; + break; + default: + assert(0); + } + + if (hc_pos >= 0) + buf[hc_pos] = 0x1F9B0 + j; + + p = re_string_find(sl, len, buf, FALSE); + if (!p) + return FALSE; + if (mark_flag) + p->flags |= 1; + } + } + return TRUE; +} + +static void zwj_encode_string(DynBuf *dbuf, const uint32_t *buf, int len, int mod_type, int *mod_pos, + int hc_pos) +{ + int i, j; + int c, code; + uint32_t buf1[SEQ_MAX_LEN]; + + j = 0; + for(i = 0; i < len;) { + c = buf[i++]; + if (c >= 0x2000 && c <= 0x2fff) { + code = c - 0x2000; + } else if (c >= 0x1f000 && c <= 0x1ffff) { + code = c - 0x1f000 + 0x1000; + } else { + assert(0); + } + if (i < len && is_emoji_modifier(buf[i])) { + /* modifier */ + code |= (mod_type << 13); + i++; + } + if (i < len && buf[i] == 0xfe0f) { + /* presentation selector present */ + code |= 0x8000; + i++; + } + if (i < len) { + /* zero width join */ + assert(buf[i] == 0x200d); + i++; + } + buf1[j++] = code; + } + dbuf_putc(dbuf, j); + for(i = 0; i < j; i++) { + dbuf_putc(dbuf, buf1[i]); + dbuf_putc(dbuf, buf1[i] >> 8); + } +} + +static void build_rgi_emoji_zwj_sequence(FILE *f, REStringList *sl) +{ + int mod_pos[2], mod_count, hair_color_pos, j, h; + REString *p; + uint32_t buf[SEQ_MAX_LEN]; + DynBuf dbuf; + +#if 0 + { + for(h = 0; h < sl->hash_size; h++) { + for(p = sl->hash_table[h]; p != NULL; p = p->next) { + for(j = 0; j < p->len; j++) + printf(" %04x", p->buf[j]); + printf("\n"); + } + } + exit(0); + } +#endif + // printf("rgi_emoji_zwj_sequence: n=%d\n", sl->n_strings); + + dbuf_init(&dbuf); + + /* avoid duplicating strings with emoji modifiers or hair colors */ + for(h = 0; h < sl->hash_size; h++) { + for(p = sl->hash_table[h]; p != NULL; p = p->next) { + if (p->flags) /* already examined */ + continue; + mod_count = 0; + hair_color_pos = -1; + for(j = 0; j < p->len; j++) { + if (is_emoji_modifier(p->buf[j])) { + assert(mod_count < 2); + mod_pos[mod_count++] = j; + } else if (is_emoji_hair_color(p->buf[j])) { + hair_color_pos = j; + } + buf[j] = p->buf[j]; + } + + if (mod_count != 0 || hair_color_pos >= 0) { + int mod_type; + if (mod_count == 0) + mod_type = EMOJI_MOD_NONE; + else if (mod_count == 1) + mod_type = EMOJI_MOD_TYPE1; + else + mod_type = EMOJI_MOD_TYPE2; + + if (mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, FALSE)) { + mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, TRUE); + } else if (mod_type == EMOJI_MOD_TYPE2) { + mod_type = EMOJI_MOD_TYPE2D; + if (mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, FALSE)) { + mark_zwj_string(sl, buf, p->len, mod_type, mod_pos, hair_color_pos, TRUE); + } else { + dump_str("not_found", (int *)p->buf, p->len); + goto keep; + } + } + if (hair_color_pos >= 0) + buf[hair_color_pos] = 0x1f9b0; + /* encode the string */ + zwj_encode_string(&dbuf, buf, p->len, mod_type, mod_pos, hair_color_pos); + } else { + keep: + zwj_encode_string(&dbuf, buf, p->len, EMOJI_MOD_NONE, NULL, -1); + } + } + } + + /* Encode */ + dump_byte_table(f, "unicode_rgi_emoji_zwj_sequence", dbuf.buf, dbuf.size); + + dbuf_free(&dbuf); +} + +void build_sequence_prop_list_table(FILE *f) +{ + int i; + fprintf(f, "typedef enum {\n"); + for(i = 0; i < SEQUENCE_PROP_COUNT; i++) + fprintf(f, " UNICODE_SEQUENCE_PROP_%s,\n", unicode_sequence_prop_name[i]); + fprintf(f, " UNICODE_SEQUENCE_PROP_COUNT,\n"); + fprintf(f, "} UnicodeSequencePropertyEnum;\n\n"); + + dump_name_table(f, "unicode_sequence_prop_name_table", + unicode_sequence_prop_name, SEQUENCE_PROP_COUNT, NULL); + + dump_byte_table(f, "unicode_rgi_emoji_tag_sequence", rgi_emoji_tag_sequence.buf, rgi_emoji_tag_sequence.size); + + build_rgi_emoji_zwj_sequence(f, &rgi_emoji_zwj_sequence); +} + #ifdef USE_TEST int check_conv(uint32_t *res, uint32_t c, int conv_type) { @@ -1912,10 +2520,10 @@ static int64_t get_time_ns(void) void check_flags(void) { int c; - bool flag_ref, flag; + BOOL flag_ref, flag; for(c = 0; c <= CHARCODE_MAX; c++) { flag_ref = get_prop(c, PROP_Cased); - flag = lre_is_cased(c); + flag = !!lre_is_cased(c); if (flag != flag_ref) { printf("ERROR: c=%05x cased=%d ref=%d\n", c, flag, flag_ref); @@ -1923,7 +2531,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_Case_Ignorable); - flag = lre_is_case_ignorable(c); + flag = !!lre_is_case_ignorable(c); if (flag != flag_ref) { printf("ERROR: c=%05x case_ignorable=%d ref=%d\n", c, flag, flag_ref); @@ -1931,7 +2539,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_ID_Start); - flag = lre_is_id_start(c); + flag = !!lre_is_id_start(c); if (flag != flag_ref) { printf("ERROR: c=%05x id_start=%d ref=%d\n", c, flag, flag_ref); @@ -1939,7 +2547,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_ID_Continue); - flag = lre_is_id_continue(c); + flag = !!lre_is_id_continue(c); if (flag != flag_ref) { printf("ERROR: c=%05x id_cont=%d ref=%d\n", c, flag, flag_ref); @@ -1953,7 +2561,7 @@ void check_flags(void) count = 0; for(c = 0x20; c <= 0xffff; c++) { flag_ref = get_prop(c, PROP_ID_Start); - flag = lre_is_id_start(c); + flag = !!lre_is_id_start(c); assert(flag == flag_ref); count++; } @@ -1970,17 +2578,23 @@ void check_flags(void) void build_cc_table(FILE *f) { - int i, cc, n, cc_table_len, type, n1; + // Compress combining class table + // see: https://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values + int i, cc, n, type, n1, block_end_pos; DynBuf dbuf_s, *dbuf = &dbuf_s; DynBuf dbuf1_s, *dbuf1 = &dbuf1_s; - int cw_len_tab[3], cw_start, block_end_pos; +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) + int cw_len_tab[3], cw_start, cc_table_len; +#endif uint32_t v; dbuf_init(dbuf); dbuf_init(dbuf1); +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cc_table_len = 0; for(i = 0; i < countof(cw_len_tab); i++) cw_len_tab[i] = 0; +#endif block_end_pos = CC_BLOCK_LEN; for(i = 0; i <= CHARCODE_MAX;) { cc = unicode_db[i].combining_class; @@ -2021,7 +2635,16 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf1, v >> 16); block_end_pos += CC_BLOCK_LEN; } +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cw_start = dbuf->size; +#endif + /* Compressed run length encoding: + - 2 high order bits are combining class type + - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte + - 00..2F: range length (add 1) + - 30..37: 3-bit range-length + 1 extra byte + - 38..3F: 3-bit range-length + 2 extra byte + */ if (n1 < 48) { dbuf_putc(dbuf, n1 | (type << 6)); } else if (n1 < 48 + (1 << 11)) { @@ -2035,10 +2658,12 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf, n1 >> 8); dbuf_putc(dbuf, n1); } +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cw_len_tab[dbuf->size - cw_start - 1]++; + cc_table_len++; +#endif if (type == 0 || type == 1) dbuf_putc(dbuf, cc); - cc_table_len++; i += n; } @@ -2049,7 +2674,7 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf1, v >> 16); dump_byte_table(f, "unicode_cc_table", dbuf->buf, dbuf->size); - dump_byte_table(f, "unicode_cc_index", dbuf1->buf, dbuf1->size); + dump_index_table(f, "unicode_cc_index", dbuf1->buf, dbuf1->size); #if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) printf("CC table: size=%d (%d entries) [", @@ -2220,29 +2845,29 @@ int get_short_code(int c) } } -static bool is_short(int code) +static BOOL is_short(int code) { return get_short_code(code) >= 0; } -static bool is_short_tab(const int *tab, int len) +static BOOL is_short_tab(const int *tab, int len) { int i; for(i = 0; i < len; i++) { if (!is_short(tab[i])) - return false; + return FALSE; } - return true; + return TRUE; } -static bool is_16bit(const int *tab, int len) +static BOOL is_16bit(const int *tab, int len) { int i; for(i = 0; i < len; i++) { if (tab[i] > 0xffff) - return false; + return FALSE; } - return true; + return TRUE; } static uint32_t to_lower_simple(uint32_t c) @@ -2487,10 +3112,10 @@ void find_decomp_run(DecompEntry *tab_de, int i) } if (l == 2) { - bool is_16bit; + BOOL is_16bit; n = 0; - is_16bit = false; + is_16bit = FALSE; for(;;) { if (!((i + n + 1) <= CHARCODE_MAX && n + 2 <= len_max)) break; @@ -2500,7 +3125,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) is_short(ci1->decomp_data[1]))) break; if (!is_16bit && !is_short(ci1->decomp_data[0])) - is_16bit = true; + is_16bit = TRUE; ci2 = &unicode_db[i + n + 1]; if (!(ci2->decomp_len == l && ci2->is_compat == ci->is_compat && @@ -2663,6 +3288,20 @@ void add_decomp_data(uint8_t *data_buf, int *pidx, DecompEntry *de) *pidx = idx; } +#if 0 +void dump_large_char(void) +{ + int i, j; + for(i = 0; i <= CHARCODE_MAX; i++) { + CCInfo *ci = &unicode_db[i]; + for(j = 0; j < ci->decomp_len; j++) { + if (ci->decomp_data[j] > 0xffff) + printf("%05x\n", ci->decomp_data[j]); + } + } +} +#endif + void build_compose_table(FILE *f, const DecompEntry *tab_de); void build_decompose_table(FILE *f) @@ -2716,8 +3355,9 @@ void build_decompose_table(FILE *f) } #endif - fprintf(f, "static const uint32_t unicode_decomp_table1[%u] = {", - array_len); + total_tables++; + total_table_bytes += array_len * sizeof(uint32_t); + fprintf(f, "static const uint32_t unicode_decomp_table1[%d] = {", array_len); count = 0; for(i = 0; i <= code_max; i++) { de = &tab_de[i]; @@ -2735,8 +3375,9 @@ void build_decompose_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint16_t unicode_decomp_table2[%u] = {", - array_len); + total_tables++; + total_table_bytes += array_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t unicode_decomp_table2[%d] = {", array_len); count = 0; for(i = 0; i <= code_max; i++) { de = &tab_de[i]; @@ -2749,8 +3390,9 @@ void build_decompose_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint8_t unicode_decomp_data[%u] = {", - data_len); + total_tables++; + total_table_bytes += data_len; + fprintf(f, "static const uint8_t unicode_decomp_data[%d] = {", data_len); for(i = 0; i < data_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -2831,8 +3473,19 @@ void build_compose_table(FILE *f, const DecompEntry *tab_de) } qsort(tab_ce, tab_ce_len, sizeof(*tab_ce), ce_cmp); - fprintf(f, "static const uint16_t unicode_comp_table[%u] = {", - tab_ce_len); +#if 0 + { + printf("tab_ce_len=%d\n", tab_ce_len); + for(i = 0; i < tab_ce_len; i++) { + ce = &tab_ce[i]; + printf("%05x %05x %05x\n", ce->c[0], ce->c[1], ce->p); + } + } +#endif + + total_tables++; + total_table_bytes += tab_ce_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t unicode_comp_table[%u] = {", tab_ce_len); for(i = 0; i < tab_ce_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -3007,24 +3660,28 @@ void normalization_test(const char *filename) } #endif -int main(int argc, char **argv) +int main(int argc, char *argv[]) { const char *unicode_db_path, *outfilename; char filename[1024]; - - if (argc < 2) { - printf("usage: %s unicode_db_path [output_file]\n" - "\n" - "If no output_file is given, a self test is done using the current unicode library\n", - argv[0]); - exit(1); + int arg = 1; + + if (arg >= argc || (!strcmp(argv[arg], "-h") || !strcmp(argv[arg], "--help"))) { + printf("usage: %s PATH [OUTPUT]\n" + " PATH path to the Unicode database directory\n" + " OUTPUT name of the output file. If omitted, a self test is performed\n" + " using the files from the Unicode library\n" + , argv[0]); + return 1; } - unicode_db_path = argv[1]; + unicode_db_path = argv[arg++]; outfilename = NULL; - if (argc >= 3) - outfilename = argv[2]; + if (arg < argc) + outfilename = argv[arg++]; unicode_db = mallocz(sizeof(unicode_db[0]) * (CHARCODE_MAX + 1)); + re_string_list_init(&rgi_emoji_zwj_sequence); + dbuf_init(&rgi_emoji_tag_sequence); snprintf(filename, sizeof(filename), "%s/UnicodeData.txt", unicode_db_path); @@ -3059,6 +3716,14 @@ int main(int argc, char **argv) unicode_db_path); parse_prop_list(filename); + snprintf(filename, sizeof(filename), "%s/emoji-sequences.txt", + unicode_db_path); + parse_sequence_prop_list(filename); + + snprintf(filename, sizeof(filename), "%s/emoji-zwj-sequences.txt", + unicode_db_path); + parse_sequence_prop_list(filename); + // dump_unicode_data(unicode_db); build_conv_table(unicode_db); @@ -3096,13 +3761,19 @@ int main(int argc, char **argv) dump_case_conv_table(fo); compute_internal_props(); build_flags_tables(fo); + fprintf(fo, "#ifdef CONFIG_ALL_UNICODE\n\n"); build_cc_table(fo); build_decompose_table(fo); build_general_category_table(fo); build_script_table(fo); build_script_ext_table(fo); build_prop_list_table(fo); + build_sequence_prop_list_table(fo); + fprintf(fo, "#endif /* CONFIG_ALL_UNICODE */\n"); + fprintf(fo, "/* %u tables / %u bytes, %u index / %u bytes */\n", + total_tables, total_table_bytes, total_index, total_index_bytes); fclose(fo); } + re_string_list_free(&rgi_emoji_zwj_sequence); return 0; } diff --git a/quickjs-ng/unicode_gen_def.h b/quickjs/unicode_gen_def.h similarity index 95% rename from quickjs-ng/unicode_gen_def.h rename to quickjs/unicode_gen_def.h index 913d173..95c369f 100644 --- a/quickjs-ng/unicode_gen_def.h +++ b/quickjs/unicode_gen_def.h @@ -82,10 +82,10 @@ DEF(Egyptian_Hieroglyphs, "Egyp") DEF(Elbasan, "Elba") DEF(Elymaic, "Elym") DEF(Ethiopic, "Ethi") +DEF(Garay, "Gara") DEF(Georgian, "Geor") DEF(Glagolitic, "Glag") DEF(Gothic, "Goth") -DEF(Garay, "Gara") DEF(Grantha, "Gran") DEF(Greek, "Grek") DEF(Gujarati, "Gujr") @@ -234,6 +234,11 @@ DEF(XID_Continue1, "") DEF(Changes_When_Titlecased1, "") DEF(Changes_When_Casefolded1, "") DEF(Changes_When_NFKC_Casefolded1, "") +DEF(Basic_Emoji1, "") +DEF(Basic_Emoji2, "") +DEF(RGI_Emoji_Modifier_Sequence, "") +DEF(RGI_Emoji_Flag_Sequence, "") +DEF(Emoji_Keycap_Sequence, "") /* Prop list exported to JS */ DEF(ASCII_Hex_Digit, "AHex") @@ -290,6 +295,7 @@ DEF(Grapheme_Extend, "Gr_Ext") DEF(ID_Continue, "IDC") DEF(ID_Compat_Math_Start, "") DEF(ID_Compat_Math_Continue, "") +DEF(InCB, "") DEF(Lowercase, "Lower") DEF(Math, "") DEF(Uppercase, "Upper") @@ -299,7 +305,14 @@ DEF(XID_Start, "XIDS") /* internal tables with index */ DEF(Cased1, "") -/* unused by us */ -DEF(InCB, "") +#endif +#ifdef UNICODE_SEQUENCE_PROP_LIST +DEF(Basic_Emoji) +DEF(Emoji_Keycap_Sequence) +DEF(RGI_Emoji_Modifier_Sequence) +DEF(RGI_Emoji_Flag_Sequence) +DEF(RGI_Emoji_Tag_Sequence) +DEF(RGI_Emoji_ZWJ_Sequence) +DEF(RGI_Emoji) #endif diff --git a/quickjs/win32-gettimeofday.c b/quickjs/win32-gettimeofday.c new file mode 100644 index 0000000..ae2e0e4 --- /dev/null +++ b/quickjs/win32-gettimeofday.c @@ -0,0 +1,126 @@ +/* + * gettimeofday.c + * Win32 gettimeofday() replacement + * + * src/port/gettimeofday.c + * + * Copyright (c) 2003 SRA, Inc. + * Copyright (c) 2003 SKC, Inc. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose, without fee, and without a + * written agreement is hereby granted, provided that the above + * copyright notice and this paragraph and the following two + * paragraphs appear in all copies. + * + * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, + * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING + * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS + * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS + * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, + * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#if defined(_MSC_VER) + +#if !defined(NOMINMAX) + #define NOMINMAX // For windows.h +#endif +#include + +/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */ +static const unsigned __int64 epoch = 116444736000000000ULL; + +/* + * FILETIME represents the number of 100-nanosecond intervals since + * January 1, 1601 (UTC). + */ +#define FILETIME_UNITS_PER_SEC 10000000L +#define FILETIME_UNITS_PER_USEC 10 + +/* + * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a + * signature, so we can just store a pointer to whichever we find. This + * is the pointer's type. + */ +typedef VOID(WINAPI * PgGetSystemTimeFn) (LPFILETIME); + +/* One-time initializer function, must match that signature. */ +static void WINAPI init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime); + +/* Storage for the function we pick at runtime */ +static PgGetSystemTimeFn pg_get_system_time = &init_gettimeofday; + +/* + * One time initializer. Determine whether GetSystemTimePreciseAsFileTime + * is available and if so, plan to use it; if not, fall back to + * GetSystemTimeAsFileTime. + */ +static void WINAPI +init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime) +{ + /* + * Because it's guaranteed that kernel32.dll will be linked into our + * address space already, we don't need to LoadLibrary it and worry about + * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper. + * + * We'll just look up the address of GetSystemTimePreciseAsFileTime if + * present. + * + * While we could look up the Windows version and skip this on Windows + * versions below Windows 8 / Windows Server 2012 there isn't much point, + * and determining the windows version is its self somewhat Windows + * version and development SDK specific... + */ + pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), + "GetSystemTimePreciseAsFileTime"); + if (pg_get_system_time == NULL) + { + /* + * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if + * the function isn't present. No other error should occur. + * + * We can't report an error here because this might be running in + * frontend code; and even if we're in the backend, it's too early to + * elog(...) if we get some unexpected error. Also, it's not a + * serious problem, so just silently fall back to + * GetSystemTimeAsFileTime irrespective of why the failure occurred. + */ + pg_get_system_time = &GetSystemTimeAsFileTime; + } + + (*pg_get_system_time) (lpSystemTimeAsFileTime); +} + +/* + * timezone information is stored outside the kernel so tzp isn't used anymore. + * + * Note: this function is not for Win32 high precision timing purposes. See + * elapsed_time(). + */ +int +gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + FILETIME file_time; + ULARGE_INTEGER ularge; + + if (tp) { + (*pg_get_system_time) (&file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC); + tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC) + / FILETIME_UNITS_PER_USEC); + } + + return 0; +} + +#endif // defined(_MSC_VER)