diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..11b2e2c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,403 @@ +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) + +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(-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-array-bounds) +xcheck_add_c_compiler_flag(-Wno-format-truncation) +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(/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() + +# 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") + add_compile_options(-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: CONFIG_TSAN is currently incompatible with the other sanitizers but we +# don't explicitly check for that because who knows what the future will bring? +# CONFIG_MSAN only works with clang at the time of writing; also not checked +# for the same reason +xoption(BUILD_EXAMPLES "Build examples" OFF) +xoption(BUILD_STATIC_QJS_EXE "Build a static qjs executable" OFF) +xoption(BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF) +xoption(BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF) +xoption(CONFIG_ASAN "Enable AddressSanitizer (ASan)" OFF) +xoption(CONFIG_MSAN "Enable MemorySanitizer (MSan)" OFF) +xoption(CONFIG_TSAN "Enable ThreadSanitizer (TSan)" OFF) +xoption(CONFIG_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF) + +if(CONFIG_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(CONFIG_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(CONFIG_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(CONFIG_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(BUILD_QJS_LIBC "Build standard library modules as part of the library" OFF) +macro(add_qjs_libc_if_needed target) + if(NOT BUILD_QJS_LIBC) + target_sources(${target} PRIVATE quickjs-libc.c) + endif() +endmacro() + +set(qjs_sources + cutils.c + libbf.c + libregexp.c + libunicode.c + quickjs.c +) + +if(BUILD_QJS_LIBC) + list(APPEND qjs_sources quickjs-libc.c) +endif() +list(APPEND qjs_defines _GNU_SOURCE) +if(WIN32) + list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602) +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) +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) +set_target_properties(qjs_exe PROPERTIES + OUTPUT_NAME "qjs" +) +target_compile_definitions(qjs_exe PRIVATE ${qjs_defines}) +target_link_libraries(qjs_exe qjs) +if(BUILD_STATIC_QJS_EXE OR MINGW) + target_link_options(qjs_exe PRIVATE -static) + if(MINGW) + target_link_options(qjs_exe PRIVATE -static-libgcc) + endif() +endif() +if(NOT WIN32) + set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE) +endif() +if(BUILD_CLI_WITH_MIMALLOC OR BUILD_CLI_WITH_STATIC_MIMALLOC) + find_package(mimalloc REQUIRED) + # Upstream mimalloc doesn't provide a way to know if both libraries are supported. + if(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() + +# 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(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() + +add_executable(test_conv + tests/test_conv.c +) + +# Install target +# + +if(NOT IOS) + file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION) + string(REGEX MATCHALL "([0-9])" QJS_VERSION "${quickjs_h}") + list(GET QJS_VERSION 0 QJS_VERSION_MAJOR) + list(GET QJS_VERSION 1 QJS_VERSION_MINOR) + list(GET QJS_VERSION 2 QJS_VERSION_PATCH) + 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(BUILD_QJS_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/Changelog b/Changelog deleted file mode 100644 index 944d96a..0000000 --- a/Changelog +++ /dev/null @@ -1,175 +0,0 @@ -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.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/LICENSE b/LICENSE index b8f687d..dd7835e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,8 @@ QuickJS Javascript Engine (DoneJS Edition) -Copyright (c) 2024 Sneed Group +Copyright (c) 2025 Sneed Group +Copyright (c) 2023 Ben Noordhuis +Copyright (c) 2023 Saúl Ibarra Corretgé Copyright (c) 2017-2021 Fabrice Bellard Copyright (c) 2017-2021 Charlie Gordon diff --git a/Makefile b/Makefile index 57cdd7e..ed60cb5 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ # # QuickJS Javascript Engine -# +# # Copyright (c) 2017-2021 Fabrice Bellard # Copyright (c) 2017-2021 Charlie Gordon +# Copyright (c) 2023 Ben Noordhuis +# Copyright (c) 2023 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 @@ -22,466 +24,103 @@ # 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 +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 -# Windows cross compilation from Linux -#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 for some utilities -#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 -# include the code for BigFloat/BigDecimal, math mode and faster large integers -CONFIG_BIGNUM=y - -OBJDIR=.obj - -ifdef CONFIG_DARWIN -# use clang instead of gcc -CONFIG_CLANG=y -CONFIG_DEFAULT_AR=y +ifeq ($(JOBS),) +JOBS := $(shell nproc) +endif +ifeq ($(JOBS),) +JOBS := 4 endif -ifdef CONFIG_WIN32 - ifdef CONFIG_M32 - CROSS_PREFIX?=i686-w64-mingw32- - else - CROSS_PREFIX?=x86_64-w64-mingw32- - endif - EXE=.exe -else - CROSS_PREFIX?= - EXE= -endif +all: $(QJS) -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 -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 - ifdef CONFIG_LTO - AR=$(CROSS_PREFIX)gcc-ar - else - AR=$(CROSS_PREFIX)ar - endif -endif -STRIP=$(CROSS_PREFIX)strip -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_BIGNUM -DEFINES+=-DCONFIG_BIGNUM -endif -ifdef CONFIG_WIN32 -DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior -endif +fuzz: + clang -g -O1 -fsanitize=address,undefined,fuzzer -o fuzz fuzz.c + ./fuzz -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_WIN32 -LDEXPORT= -else -LDEXPORT=-rdynamic -endif +$(BUILD_DIR): + cmake -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX) -ifndef CONFIG_COSMO -ifndef CONFIG_DARWIN -CONFIG_SHARED_LIBS=y # building shared libraries is supported -endif -endif +$(QJS): $(BUILD_DIR) + cmake --build $(BUILD_DIR) -j $(JOBS) -PROGS=qjs$(EXE) qjsc$(EXE) run-test262 -ifneq ($(CROSS_PREFIX),) -QJSC_CC=gcc -QJSC=./host-qjsc -PROGS+=$(QJSC) -else -QJSC_CC=$(CC) -QJSC=./qjsc$(EXE) -endif -ifndef CONFIG_WIN32 -PROGS+=qjscalc -endif -ifdef CONFIG_M32 -PROGS+=qjs32 qjs32_s -endif -PROGS+=libquickjs.a -ifdef CONFIG_LTO -PROGS+=libquickjs.lto.a -endif +$(QJSC): $(BUILD_DIR) + cmake --build $(BUILD_DIR) --target qjsc -j $(JOBS) -# examples -ifeq ($(CROSS_PREFIX),) -PROGS+=examples/hello -ifndef CONFIG_ASAN -PROGS+=examples/hello_module -endif -ifdef CONFIG_SHARED_LIBS -PROGS+=examples/test_fib examples/fib.so examples/point.so -endif -endif +$(BUILD_DIR)/test_conv: $(BUILD_DIR) tests/test_conv.c + cmake --build $(BUILD_DIR) --target test_conv -all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS) - -QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o - -QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS) -ifdef CONFIG_BIGNUM -QJS_OBJS+=$(OBJDIR)/qjscalc.o -endif - -HOST_LIBS=-lm -ldl -lpthread -LIBS=-lm -ifndef CONFIG_WIN32 -LIBS+=-ldl -lpthread -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) - -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) - -qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS)) - $(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) - -qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS)) - $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) - @size $@ - -qjscalc: qjs - ln -sf $< $@ - -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 - -repl.c: $(QJSC) repl.js - $(QJSC) -c -o $@ -m repl.js - -qjscalc.c: $(QJSC) qjscalc.js - $(QJSC) -fbignum -c -o $@ qjscalc.js - -ifneq ($(wildcard unicode/UnicodeData.txt),) -$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \ - $(OBJDIR)/libunicode.nolto.o: libunicode-table.h - -libunicode-table.h: unicode_gen - ./unicode_gen unicode $@ -endif - -run-test262: $(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) - -run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) - $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) - -# object suffix order: nolto, [m32|m32s] - -$(OBJDIR)/%.o: %.c | $(OBJDIR) - $(CC) $(CFLAGS_OPT) -c -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)/%.m32.o: %.c | $(OBJDIR) - $(CC) -m32 $(CFLAGS_OPT) -c -o $@ $< - -$(OBJDIR)/%.m32s.o: %.c | $(OBJDIR) - $(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $< - -$(OBJDIR)/%.debug.o: %.c | $(OBJDIR) - $(CC) $(CFLAGS_DEBUG) -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 +install: $(QJS) $(QJSC) + cmake --build $(BUILD_DIR) --target install clean: - rm -f repl.c qjscalc.c out.c - rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS) - rm -f hello.c test_fib.c - rm -f examples/*.so tests/*.so - rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug - rm -rf run-test262-debug run-test262-32 + cmake --build $(BUILD_DIR) --target clean -install: all - mkdir -p "$(DESTDIR)$(PREFIX)/bin" - $(STRIP) qjs qjsc - install -m755 qjs qjsc "$(DESTDIR)$(PREFIX)/bin" - ln -sf qjs "$(DESTDIR)$(PREFIX)/bin/qjscalc" - 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" +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 -############################################################################### -# examples +debug: + BUILD_TYPE=Debug $(MAKE) -# 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 -fno-bigint +distclean: + @rm -rf $(BUILD_DIR) -hello.c: $(QJSC) $(HELLO_SRCS) - $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) +stats: $(QJS) + $(QJS) -qd -ifdef CONFIG_M32 -examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS)) - $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -else -examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -endif +# 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 $< -# example of static JS compilation with modules -HELLO_MODULE_SRCS=examples/hello_module.js -HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -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) +# 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 $< -# use of an external C module (static compilation) +test: $(QJS) + $(RUN262) -c tests.conf -test_fib.c: $(QJSC) examples/test_fib.js - $(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js +testconv: $(BUILD_DIR)/test_conv + $(BUILD_DIR)/test_conv -examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +test262: $(QJS) + $(RUN262) -m -c test262.conf -a -examples/fib.so: $(OBJDIR)/examples/fib.pic.o - $(CC) $(LDFLAGS) -shared -o $@ $^ +test262-fast: $(QJS) + $(RUN262) -m -c test262.conf -c test262-fast.conf -a -examples/point.so: $(OBJDIR)/examples/point.pic.o - $(CC) $(LDFLAGS) -shared -o $@ $^ +test262-update: $(QJS) + $(RUN262) -u -c test262.conf -a -t 1 -############################################################################### -# documentation +test262-check: $(QJS) + $(RUN262) -m -c test262.conf -E -a -DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html +microbench: $(QJS) + $(QJS) tests/microbench.js -build_doc: $(DOCS) +unicode_gen: $(BUILD_DIR) + cmake --build $(BUILD_DIR) --target unicode_gen -clean_doc: - rm -f $(DOCS) +libunicode-table.h: unicode_gen + $(BUILD_DIR)/unicode_gen unicode $@ -doc/%.pdf: doc/%.texi - texi2pdf --clean -o $@ -q $< - -doc/%.html.pre: doc/%.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 -ifdef CONFIG_M32 -test: qjs32 -endif - -test: qjs - ./qjs tests/test_closure.js - ./qjs tests/test_language.js - ./qjs tests/test_builtin.js - ./qjs tests/test_loop.js - ./qjs tests/test_std.js - ./qjs tests/test_worker.js -ifdef CONFIG_SHARED_LIBS -ifdef CONFIG_BIGNUM - ./qjs --bignum tests/test_bjson.js -else - ./qjs tests/test_bjson.js -endif - ./qjs examples/test_point.js -endif -ifdef CONFIG_BIGNUM - ./qjs --bignum tests/test_op_overloading.js - ./qjs --bignum tests/test_bignum.js - ./qjs --qjscalc tests/test_qjscalc.js -endif -ifdef CONFIG_M32 - ./qjs32 tests/test_closure.js - ./qjs32 tests/test_language.js - ./qjs32 tests/test_builtin.js - ./qjs32 tests/test_loop.js - ./qjs32 tests/test_std.js - ./qjs32 tests/test_worker.js -ifdef CONFIG_BIGNUM - ./qjs32 --bignum tests/test_op_overloading.js - ./qjs32 --bignum tests/test_bignum.js - ./qjs32 --qjscalc tests/test_qjscalc.js -endif -endif - -stats: qjs qjs32 - ./qjs -qd - ./qjs32 -qd - -microbench: qjs - ./qjs tests/microbench.js - -microbench-32: qjs32 - ./qjs32 tests/microbench.js - -# ES5 tests (obsolete) -test2o: run-test262 - time ./run-test262 -m -c test262o.conf - -test2o-32: run-test262-32 - time ./run-test262-32 -m -c test262o.conf - -test2o-update: run-test262 - ./run-test262 -u -c test262o.conf - -# Test262 tests -test2-default: run-test262 - time ./run-test262 -m -c test262.conf - -test2: run-test262 - time ./run-test262 -m -c test262.conf -a - -test2-32: run-test262-32 - time ./run-test262-32 -m -c test262.conf -a - -test2-update: run-test262 - ./run-test262 -u -c test262.conf -a - -test2-check: run-test262 - time ./run-test262 -m -c test262.conf -E -a - -testall: all test microbench test2o test2 - -testall-32: all test-32 microbench-32 test2o-32 test2-32 - -testall-complete: testall testall-32 - -bench-v8: qjs - make -C tests/bench-v8 - ./qjs -d tests/bench-v8/combined.js - -tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o - $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) - --include $(wildcard $(OBJDIR)/*.d) +.PHONY: all ctest cxxtest debug fuzz install clean codegen distclean stats test test262 test262-update test262-check microbench unicode_gen $(QJS) $(QJSC) diff --git a/README.md b/README.md index 4955d7d..e4b0e34 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,24 @@ -# QuickJS (DoneJS edition) +# ⚡️ QuickJS - A mighty JavaScript engine -An *unofficial* fork of QuickJS that contains polyfills and modifications to the source code to make it more like something such as NodeJS or De*no*. +## Overview -# FAQ +QuickJS is a small and embeddable JavaScript engine. It aims to support the latest +[ECMAScript] specification. -## Documentation Location +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. -The main documentation is in "doc/quickjs.pdf" for the PDF version or "doc/quickjs.html" for the HTML one. +## Getting started +Head over to the [project website] for instructions on how to get started and more +documentation. -## Location of Polyfills +## Authors -The polyfills are located in the "qjs.c" file. +[@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/TODO b/TODO deleted file mode 100644 index bbd1a45..0000000 --- a/TODO +++ /dev/null @@ -1,67 +0,0 @@ -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: -- 64-bit atoms in 64-bit mode ? -- 64-bit small bigint in 64-bit mode ? -- reuse stack slots for disjoint scopes, if strip -- add heuristic to avoid some cycles in closures -- small String (0-2 charcodes) with immediate storage -- perform static string concatenation at compile time -- optimize string concatenation with ropes or miniropes? -- 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? -- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references -- 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) - -Result: 10/76947 errors, 1497 excluded, 8117 skipped -Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb diff --git a/VERSION b/VERSION deleted file mode 100644 index e89de35..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -2024-01-13 diff --git a/compat/test-closefrom.c b/compat/test-closefrom.c deleted file mode 100644 index 1324e97..0000000 --- a/compat/test-closefrom.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main(void) { - closefrom(3); - return 0; -} diff --git a/ctest.c b/ctest.c new file mode 100644 index 0000000..eeb03e8 --- /dev/null +++ b/ctest.c @@ -0,0 +1,17 @@ +// 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/cutils.c b/cutils.c index a02fb76..8dc27dd 100644 --- a/cutils.c +++ b/cutils.c @@ -1,6 +1,6 @@ /* * C utilities - * + * * Copyright (c) 2017 Fabrice Bellard * Copyright (c) 2018 Charlie Gordon * @@ -22,14 +22,26 @@ * 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 #include "cutils.h" -void pstrcpy(char *buf, int buf_size, const char *str) +#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; @@ -47,16 +59,16 @@ void pstrcpy(char *buf, int buf_size, const char *str) } /* strcat and truncate. */ -char *pstrcat(char *buf, int buf_size, const char *s) +char *js__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); + js__pstrcpy(buf + len, buf_size - len, s); return buf; } -int strstart(const char *str, const char *val, const char **ptr) +int js__strstart(const char *str, const char *val, const char **ptr) { const char *p, *q; p = str; @@ -72,7 +84,7 @@ int strstart(const char *str, const char *val, const char **ptr) return 1; } -int has_suffix(const char *str, const char *suffix) +int js__has_suffix(const char *str, const char *suffix) { size_t len = strlen(str); size_t slen = strlen(suffix); @@ -122,7 +134,7 @@ int dbuf_realloc(DynBuf *s, size_t new_size) return 0; } -int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) +int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len) { size_t end; end = offset + len; @@ -134,14 +146,16 @@ int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) return 0; } -int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) +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; } - memcpy(s->buf + s->size, data, len); - s->size += len; + if (len > 0) { + memcpy(s->buf + s->size, data, len); + s->size += len; + } return 0; } @@ -172,11 +186,11 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, va_list ap; char buf[128]; int len; - + va_start(ap, fmt); len = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); - if (len < sizeof(buf)) { + if (len < (int)sizeof(buf)) { /* fast case */ return dbuf_put(s, (uint8_t *)buf, len); } else { @@ -201,56 +215,85 @@ void dbuf_free(DynBuf *s) 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; +/*--- UTF-8 utility functions --*/ - 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; +/* 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; } -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) +/* 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) { - int l, c, b, i; + 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) { @@ -258,76 +301,538 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) 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; + 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: 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; + 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: 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; + 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: - return -1; + // invalid lead byte + break; } - /* 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; + return 0xFFFD; } -#if 0 +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; +} -#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) +/* 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) { - return rqsort_cmp(p1, p2, rqsort_arg); + 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; } -/* 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) +/* 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) { - rqsort_arg = arg; - rqsort_cmp = cmp; - qsort(base, nmemb, size, rqsort_cmp2); + 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; +} + +/*--- integer to string conversions --*/ + +/* All conversion functions: + - require a destination array `buf` of sufficient length + - write the string representation at the beginning of `buf` + - null terminate the string + - return the string length + */ + +/* 2 <= base <= 36 */ +char const digits36[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' +}; + + +#define USE_SPECIAL_RADIX_10 1 // special case base 10 radix conversions +#define USE_SINGLE_CASE_FAST 1 // special case single digit numbers + +/* using u32toa_shift variant */ + +#define gen_digit(buf, c) if (is_be()) \ + buf = (buf >> 8) | ((uint64_t)(c) << ((sizeof(buf) - 1) * 8)); \ + else \ + buf = (buf << 8) | (c) + +static size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n) +{ + size_t len = 1; + uint64_t buf = 0; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + gen_digit(buf, '0' + quo); + len++; + } + gen_digit(buf, '0' + n); + memcpy(dest, &buf, sizeof buf); + return len; +} + +static size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len) +{ + size_t i; + dest += len; + dest[7] = '\0'; + for (i = 7; i-- > 1;) { + uint32_t quo = n % 10; + n /= 10; + dest[i] = (char)('0' + quo); + } + dest[i] = (char)('0' + n); + return len + 7; +} + +size_t u32toa(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE_FAST /* 10% */ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } #endif +#define TEN_POW_7 10000000 + if (n >= TEN_POW_7) { + uint32_t quo = n / TEN_POW_7; + n %= TEN_POW_7; + size_t len = u7toa_shift(buf, quo); + return u07toa_shift(buf, n, len); + } + return u7toa_shift(buf, n); +} -#else +size_t u64toa(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa(buf, n); + + size_t len; + if (n >= TEN_POW_7) { + uint64_t n1 = n / TEN_POW_7; + n %= TEN_POW_7; + if (n1 >= TEN_POW_7) { + uint32_t quo = n1 / TEN_POW_7; + n1 %= TEN_POW_7; + len = u7toa_shift(buf, quo); + len = u07toa_shift(buf, n1, len); + } else { + len = u7toa_shift(buf, n1); + } + return u07toa_shift(buf, n, len); + } + return u7toa_shift(buf, n); +} + +size_t i32toa(char buf[minimum_length(12)], int32_t n) +{ + if (likely(n >= 0)) + return u32toa(buf, n); + + buf[0] = '-'; + return 1 + u32toa(buf + 1, -(uint32_t)n); +} + +size_t i64toa(char buf[minimum_length(22)], int64_t n) +{ + if (likely(n >= 0)) + return u64toa(buf, n); + + buf[0] = '-'; + return 1 + u64toa(buf + 1, -(uint64_t)n); +} + +/* using u32toa_radix_length variant */ + +static uint8_t const radix_shift[64] = { + 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 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, +}; + +size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ + int shift; + +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u32toa(buf, n); +#endif + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } + shift = radix_shift[base & 63]; + if (shift) { + uint32_t mask = (1 << shift) - 1; + size_t len = (32 - clz32(n) + shift - 1) / shift; + size_t last = n & mask; + char *end = buf + len; + n >>= shift; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n & mask; + n >>= shift; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } else { + size_t len = 2; + size_t last = n % base; + n /= base; + uint32_t nbase = base; + while (n >= nbase) { + nbase *= base; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n % base; + n /= base; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } +} + +size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + int shift; + +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u64toa(buf, n); +#endif + shift = radix_shift[base & 63]; + if (shift) { + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } + uint64_t mask = (1 << shift) - 1; + size_t len = (64 - clz64(n) + shift - 1) / shift; + size_t last = n & mask; + char *end = buf + len; + n >>= shift; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n & mask; + n >>= shift; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } else { + if (likely(n < 0x100000000)) + return u32toa_radix(buf, n, base); + size_t last = n % base; + n /= base; + uint64_t nbase = base; + size_t len = 2; + while (n >= nbase) { + nbase *= base; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n % base; + n /= base; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } +} + +size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned int base) +{ + if (likely(n >= 0)) + return u32toa_radix(buf, n, base); + + buf[0] = '-'; + return 1 + u32toa_radix(buf + 1, -(uint32_t)n, base); +} + +size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base) +{ + if (likely(n >= 0)) + return u64toa_radix(buf, n, base); + + buf[0] = '-'; + return 1 + u64toa_radix(buf + 1, -(uint64_t)n, base); +} + +#undef gen_digit +#undef TEN_POW_7 +#undef USE_SPECIAL_RADIX_10 +#undef USE_SINGLE_CASE_FAST + +/*---- 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); @@ -628,4 +1133,285 @@ void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) } } +/*---- 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; +} + +/*--- Cross-platform threading APIs. ----*/ + +#if !defined(EMSCRIPTEN) && !defined(__wasi__) + +#if defined(_WIN32) +typedef void (*js__once_cb)(void); + +typedef struct { + js__once_cb callback; +} js__once_data_t; + +static BOOL WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) { + js__once_data_t *data = param; + + data->callback(); + + return TRUE; +} + +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; +} + +#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; +} + +#endif + +#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */ + +#ifdef __GNUC__ +#pragma GCC visibility pop #endif diff --git a/cutils.h b/cutils.h index 8399d61..ea22834 100644 --- a/cutils.h +++ b/cutils.h @@ -1,6 +1,6 @@ /* * C utilities - * + * * Copyright (c) 2017 Fabrice Bellard * Copyright (c) 2018 Charlie Gordon * @@ -26,31 +26,95 @@ #define CUTILS_H #include +#include #include +#include -/* set if CPU is big endian */ -#undef WORDS_BIGENDIAN +#ifdef __cplusplus +extern "C" { +#endif -#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)) +#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__) +#include +#elif defined(__FreeBSD__) +#include +#elif defined(_WIN32) +#include +#endif +#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__) +#include +#include +#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__) +# 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) +# include +static void *__builtin_frame_address(unsigned int level) { + return (void *)((char*)_AddressOfReturnAddress() - sizeof(int *) - level * sizeof(int *)); +} +#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 + +// https://stackoverflow.com/a/6849629 +#undef FORMAT_STRING +#if _MSC_VER >= 1400 +# include +# if _MSC_VER > 1400 +# define FORMAT_STRING(p) _Printf_format_string_ p +# else +# define FORMAT_STRING(p) __format_string p +# endif /* FORMAT_STRING */ +#else +# define FORMAT_STRING(p) p +#endif /* _MSC_VER */ + +#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 #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) +#define minimum_length(n) n +#else +#define minimum_length(n) static n +#endif typedef int BOOL; @@ -61,10 +125,18 @@ enum { }; #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); -int has_suffix(const char *str, const char *suffix); +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); + +static inline uint8_t is_be(void) { + union { + uint16_t a; + uint8_t b; + } u = { 0x100 }; + return u.b; +} static inline int max_int(int a, int b) { @@ -117,82 +189,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) @@ -210,28 +313,117 @@ static inline void put_u8(uint8_t *tab, uint8_t val) *tab = val; } +#ifndef bswap16 static inline uint16_t bswap16(uint16_t x) { return (x >> 8) | (x << 8); } +#endif +#ifndef bswap32 static inline uint32_t bswap32(uint32_t v) { return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24); } +#endif +#ifndef bswap64 static inline uint64_t bswap64(uint64_t v) { - return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) | - ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) | - ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) | - ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) | - ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) | - ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) | - ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | + return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) | + ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) | + ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) | + ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) | + ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) | + ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) | + ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8)); } +#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); @@ -248,8 +440,8 @@ typedef struct 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 uint8_t *data, size_t len); -int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); +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_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); @@ -266,7 +458,7 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val) return dbuf_put(s, (uint8_t *)&val, 8); } int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, - const char *fmt, ...); + FORMAT_STRING(const char *fmt), ...); void dbuf_free(DynBuf *s); static inline BOOL dbuf_error(DynBuf *s) { return s->error; @@ -276,10 +468,56 @@ static inline void dbuf_set_error(DynBuf *s) s->error = TRUE; } -#define UTF8_CHAR_LEN_MAX 6 +/*---- UTF-8 and UTF-16 handling ----*/ -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); +#define UTF8_CHAR_LEN_MAX 4 + +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) +{ + return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF +} + +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) +{ + return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF +} + +static inline uint32_t get_hi_surrogate(uint32_t c) +{ + return (c >> 10) - (0x10000 >> 10) + 0xD800; +} + +static inline uint32_t get_lo_surrogate(uint32_t c) +{ + return (c & 0x3FF) | 0xDC00; +} + +static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo) +{ + return 65536 + 1024 * (hi & 1023) + (lo & 1023); +} static inline int from_hex(int c) { @@ -293,8 +531,78 @@ 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; +} + +extern char const digits36[36]; +size_t u32toa(char buf[minimum_length(11)], uint32_t n); +size_t i32toa(char buf[minimum_length(12)], int32_t n); +size_t u64toa(char buf[minimum_length(21)], uint64_t n); +size_t i64toa(char buf[minimum_length(22)], int64_t n); +size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned int base); +size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned base); +size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned int base); +size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base); + void rqsort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *, void *), void *arg); +int64_t js__gettimeofday_us(void); +uint64_t js__hrtime_ns(void); + +static inline size_t js__malloc_usable_size(const void *ptr) +{ +#if defined(__APPLE__) + return malloc_size(ptr); +#elif defined(_WIN32) + return _msize((void *)ptr); +#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__) + return malloc_usable_size((void *)ptr); +#else + return 0; +#endif +} + +/* Cross-platform threading APIs. */ + +#if !defined(EMSCRIPTEN) && !defined(__wasi__) + +#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; +#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; +#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); + +#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */ + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + #endif /* CUTILS_H */ diff --git a/cxxtest.cc b/cxxtest.cc new file mode 100644 index 0000000..b615100 --- /dev/null +++ b/cxxtest.cc @@ -0,0 +1,2 @@ +// note: file is not actually compiled, only checked for C++ syntax errors +#include "ctest.c" diff --git a/dirent_compat.h b/dirent_compat.h new file mode 100644 index 0000000..077674e --- /dev/null +++ b/dirent_compat.h @@ -0,0 +1,1166 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir (const char *dirname); +static _WDIR *_wopendir (const wchar_t *dirname); + +static struct dirent *readdir (DIR *dirp); +static struct _wdirent *_wreaddir (_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir (DIR *dirp); +static int _wclosedir (_WDIR *dirp); + +static void rewinddir (DIR* dirp); +static void _wrewinddir (_WDIR* dirp); + +static int scandir (const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort (const struct dirent **a, const struct dirent **b); + +static int versionsort (const struct dirent **a, const struct dirent **b); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + DWORD n; +#else + /* WinRT */ + size_t n; +#endif + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (!dirp) { + return NULL; + } + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); +#else + /* WinRT */ + n = wcslen (dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt == NULL) { + goto exit_closedir; + } + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n <= 0) { + goto exit_closedir; + } +#else + /* WinRT */ + wcsncpy_s (dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first (dirp)) { + goto exit_closedir; + } + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir (dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) _wreaddir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct _wdirent); + + /* Set result address */ + *result = entry; + + } else { + + /* Return NULL to indicate end of directory */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Release search pattern */ + free (dirp->patt); + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + DWORD error; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + /* Set error code */ + error = GetLastError (); + switch (error) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno (EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno (ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno (ENOENT); + } + + } + return datap; +} + +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (!dirp) { + return NULL; + } + { + int error; + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (error) { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + goto exit_free; + } + + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (!dirp->wdirp) { + goto exit_free; + } + + } + + /* Success */ + return dirp; + + /* Failure */ +exit_free: + free (dirp); + return NULL; +} + +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) readdir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + DWORD attr; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct dirent); + + } else { + + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + + } + + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir (dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + + /* Allocate first pointer table or enlarge existing table */ + p = realloc (files, sizeof (void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; + } + + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc (sizeof (struct dirent)); + if (tmp == NULL) { + /* Cannot allocate temporary directory entry */ + result = -1; + break; + } + } + + /* Read directory entry to temporary area */ + if (readdir_r (dir, tmp, &entry) == /*OK*/0) { + + /* Did we get an entry? */ + if (entry != NULL) { + int pass; + + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter (tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } + + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + + /* Keep up with the number of files */ + result++; + } + + } else { + + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort (files, size, sizeof (void*), + (int (*) (const void*, const void*)) compare); + break; + + } + + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; + } + + } + + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } + + /* Release temporary directory entry */ + free (tmp); + + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free (files[i]); + } + free (files); + files = NULL; + } + + /* Close directory stream */ + if (dir) { + closedir (dir); + } + + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; + } + return result; +} + +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll ((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort (a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resulting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ \ No newline at end of file diff --git a/doc/jsbignum.html b/doc/jsbignum.html deleted file mode 100644 index ab31612..0000000 --- a/doc/jsbignum.html +++ /dev/null @@ -1,734 +0,0 @@ - - - - -Javascript Bignum Extensions - - - - - - - - - - - - - - - -

Javascript Bignum Extensions

- - -

Table of Contents

- - - - - -

1 Introduction

- -

The Bignum extensions add the following features to the Javascript -language while being 100% backward compatible: -

-
    -
  • Operator overloading with a dispatch logic inspired from the proposal available at https://github.com/tc39/proposal-operator-overloading/. - -
  • Arbitrarily large floating point numbers (BigFloat) in base 2 using the IEEE 754 semantics. - -
  • Arbitrarily large floating point numbers (BigDecimal) in base 10 based on the proposal available at -https://github.com/littledan/proposal-bigdecimal. - -
  • math mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (%) is defined as the Euclidian -remainder. ^ is an alias to the power operator -(**). ^^ is used as the exclusive or operator. - -
- -

The extensions are independent from each other except the math -mode which relies on BigFloat and operator overloading. -

- -

2 Operator overloading

- -

Operator overloading is inspired from the proposal available at -https://github.com/tc39/proposal-operator-overloading/. It -implements the same dispatch logic but finds the operator sets by -looking at the Symbol.operatorSet property in the objects. The -changes were done in order to simplify the implementation. -

-

More precisely, the following modifications were made: -

-
    -
  • with operators from is not supported. Operator overloading is always enabled. - -
  • The dispatch is not based on a static [[OperatorSet]] field in all instances. Instead, a dynamic lookup of the Symbol.operatorSet property is done. This property is typically added in the prototype of each object. - -
  • Operators.create(...dictionaries) is used to create a new OperatorSet object. The Operators function is supported as an helper to be closer to the TC39 proposal. - -
  • [] cannot be overloaded. - -
  • In math mode, the BigInt division and power operators can be overloaded with Operators.updateBigIntOperators(dictionary). - -
- - -

3 BigInt extensions

- -

A few properties are added to the BigInt object: -

-
-
tdiv(a, b)
-

Return trunc(a/b). b = 0 raises a RangeError -exception. -

-
-
fdiv(a, b)
-

Return \lfloor a/b \rfloor. b = 0 raises a RangeError -exception. -

-
-
cdiv(a, b)
-

Return \lceil a/b \rceil. b = 0 raises a RangeError -exception. -

-
-
ediv(a, b)
-

Return sgn(b) \lfloor a/{|b|} \rfloor (Euclidian -division). b = 0 raises a RangeError exception. -

-
-
tdivrem(a, b)
-
fdivrem(a, b)
-
cdivrem(a, b)
-
edivrem(a, b)
-

Return an array of two elements. The first element is the quotient, -the second is the remainder. The same rounding is done as the -corresponding division operation. -

-
-
sqrt(a)
-

Return \lfloor \sqrt(a) \rfloor. A RangeError exception is -raised if a < 0. -

-
-
sqrtrem(a)
-

Return an array of two elements. The first element is \lfloor -\sqrt{a} \rfloor. The second element is a-\lfloor \sqrt{a} -\rfloor^2. A RangeError exception is raised if a < 0. -

-
-
floorLog2(a)
-

Return -1 if a \leq 0 otherwise return \lfloor \log2(a) \rfloor. -

-
-
ctz(a)
-

Return the number of trailing zeros in the two’s complement binary representation of a. Return -1 if a=0. -

-
-
- - -

4 BigFloat

- - -

4.1 Introduction

- -

This extension adds the BigFloat primitive type. The -BigFloat type represents floating point numbers in base 2 -with the IEEE 754 semantics. A floating -point number is represented as a sign, mantissa and exponent. The -special values NaN, +/-Infinity, +0 and -0 -are supported. The mantissa and exponent can have any bit length with -an implementation specific minimum and maximum. -

- -

4.2 Floating point rounding

- -

Each floating point operation operates with infinite precision and -then rounds the result according to the specified floating point -environment (BigFloatEnv object). The status flags of the -environment are also set according to the result of the operation. -

-

If no floating point environment is provided, the global floating -point environment is used. -

-

The rounding mode of the global floating point environment is always -RNDN (“round to nearest with ties to even”)1. The status flags of the global environment cannot be -read2. The precision of the global environment is -BigFloatEnv.prec. The number of exponent bits of the global -environment is BigFloatEnv.expBits. The global environment -subnormal flag is set to true. -

-

For example, prec = 53 and expBits = 11 exactly give -the same precision as the IEEE 754 64 bit floating point format. The -default precision is prec = 113 and expBits = 15 (IEEE -754 128 bit floating point format). -

-

The global floating point environment can only be modified temporarily -when calling a function (see BigFloatEnv.setPrec). Hence a -function can change the global floating point environment for its -callees but not for its caller. -

- -

4.3 Operators

- -

The builtin operators are extended so that a BigFloat is returned if -at least one operand is a BigFloat. The computations are always done -with infinite precision and rounded according to the global floating -point environment. -

-

typeof applied on a BigFloat returns bigfloat. -

-

BigFloat can be compared with all the other numeric types and the -result follows the expected mathematical relations. -

-

However, since BigFloat and Number are different types they are never -equal when using the strict comparison operators (e.g. 0.0 === -0.0l is false). -

- -

4.4 BigFloat literals

- -

BigFloat literals are floating point numbers with a trailing l -suffix. BigFloat literals have an infinite precision. They are rounded -according to the global floating point environment when they are -evaluated.3 -

- -

4.5 Builtin Object changes

- - -

4.5.1 BigFloat function

- -

The BigFloat function cannot be invoked as a constructor. When -invoked as a function: the parameter is converted to a primitive -type. If the result is a numeric type, it is converted to BigFloat -without rounding. If the result is a string, it is converted to -BigFloat using the precision of the global floating point environment. -

-

BigFloat properties: -

-
-
LN2
-
PI
-

Getter. Return the value of the corresponding mathematical constant -rounded to nearest, ties to even with the current global -precision. The constant values are cached for small precisions. -

-
-
MIN_VALUE
-
MAX_VALUE
-
EPSILON
-

Getter. Return the minimum, maximum and epsilon BigFloat values -(same definition as the corresponding Number constants). -

-
-
fpRound(a[, e])
-

Round the floating point number a according to the floating -point environment e or the global environment if e is -undefined. -

-
-
parseFloat(a[, radix[, e]])
-

Parse the string a as a floating point number in radix -radix. The radix is 0 (default) or from 2 to 36. The radix 0 -means radix 10 unless there is a hexadecimal or binary prefix. The -result is rounded according to the floating point environment e -or the global environment if e is undefined. -

-
-
isFinite(a)
-

Return true if a is a finite bigfloat. -

-
-
isNaN(a)
-

Return true if a is a NaN bigfloat. -

-
-
add(a, b[, e])
-
sub(a, b[, e])
-
mul(a, b[, e])
-
div(a, b[, e])
-

Perform the specified floating point operation and round the floating -point number a according to the floating point environment -e or the global environment if e is undefined. If -e is specified, the floating point status flags are updated. -

-
-
floor(x)
-
ceil(x)
-
round(x)
-
trunc(x)
-

Round to an integer. No additional rounding is performed. -

-
-
abs(x)
-

Return the absolute value of x. No additional rounding is performed. -

-
-
fmod(x, y[, e])
-
remainder(x, y[, e])
-

Floating point remainder. The quotient is truncated to zero (fmod) or -to the nearest integer with ties to even (remainder). e is an -optional floating point environment. -

-
-
sqrt(x[, e])
-

Square root. Return a rounded floating point number. e is an -optional floating point environment. -

-
-
sin(x[, e])
-
cos(x[, e])
-
tan(x[, e])
-
asin(x[, e])
-
acos(x[, e])
-
atan(x[, e])
-
atan2(x, y[, e])
-
exp(x[, e])
-
log(x[, e])
-
pow(x, y[, e])
-

Transcendental operations. Return a rounded floating point -number. e is an optional floating point environment. -

-
-
- - -

4.5.2 BigFloat.prototype

- -

The following properties are modified: -

-
-
valueOf()
-

Return the bigfloat primitive value corresponding to this. -

-
-
toString(radix)
-
-

For floating point numbers: -

-
    -
  • If the radix is a power of two, the conversion is done with infinite -precision. -
  • Otherwise, the number is rounded to nearest with ties to even using -the global precision. It is then converted to string using the minimum -number of digits so that its conversion back to a floating point using -the global precision and round to nearest gives the same number. - -
- -

The exponent letter is e for base 10, p for bases 2, 8, -16 with a binary exponent and @ for the other bases. -

-
-
toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
-
toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
-
toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
-

Same semantics as the corresponding Number functions with -BigFloats. There is no limit on the accepted precision p. The -rounding mode and radix can be optionally specified. The radix must be -between 2 and 36. -

-
-
- - -

4.5.3 BigFloatEnv constructor

- -

The BigFloatEnv([p, [,rndMode]] constructor cannot be invoked as a -function. The floating point environment contains: -

-
    -
  • the mantissa precision in bits - -
  • the exponent size in bits assuming an IEEE 754 representation; - -
  • the subnormal flag (if true, subnormal floating point numbers can -be generated by the floating point operations). - -
  • the rounding mode - -
  • the floating point status. The status flags can only be set by the floating point operations. They can be reset with BigFloatEnv.prototype.clearStatus() or with the various status flag setters. - -
- -

new BigFloatEnv([p, [,rndMode]] creates a new floating point -environment. The status flags are reset. If no parameter is given the -precision, exponent bits and subnormal flags are copied from the -global floating point environment. Otherwise, the precision is set to -p, the number of exponent bits is set to expBitsMax and the -subnormal flags is set to false. If rndMode is -undefined, the rounding mode is set to RNDN. -

-

BigFloatEnv properties: -

-
-
prec
-

Getter. Return the precision in bits of the global floating point -environment. The initial value is 113. -

-
-
expBits
-

Getter. Return the exponent size in bits of the global floating point -environment assuming an IEEE 754 representation. The initial value is -15. -

-
-
setPrec(f, p[, e])
-

Set the precision of the global floating point environment to p -and the exponent size to e then call the function -f. Then the Float precision and exponent size are reset to -their precious value and the return value of f is returned (or -an exception is raised if f raised an exception). If e -is undefined it is set to BigFloatEnv.expBitsMax. -

-
-
precMin
-

Read-only integer. Return the minimum allowed precision. Must be at least 2. -

-
-
precMax
-

Read-only integer. Return the maximum allowed precision. Must be at least 113. -

-
-
expBitsMin
-

Read-only integer. Return the minimum allowed exponent size in -bits. Must be at least 3. -

-
-
expBitsMax
-

Read-only integer. Return the maximum allowed exponent size in -bits. Must be at least 15. -

-
-
RNDN
-

Read-only integer. Round to nearest, with ties to even rounding mode. -

-
-
RNDZ
-

Read-only integer. Round to zero rounding mode. -

-
-
RNDD
-

Read-only integer. Round to -Infinity rounding mode. -

-
-
RNDU
-

Read-only integer. Round to +Infinity rounding mode. -

-
-
RNDNA
-

Read-only integer. Round to nearest, with ties away from zero rounding mode. -

-
-
RNDA
-

Read-only integer. Round away from zero rounding mode. -

-
-
RNDF4
-

Read-only integer. Faithful rounding mode. The result is -non-deterministically rounded to -Infinity or +Infinity. This rounding -mode usually gives a faster and deterministic running time for the -floating point operations. -

-
-
- -

BigFloatEnv.prototype properties: -

-
-
prec
-

Getter and setter (Integer). Return or set the precision in bits. -

-
-
expBits
-

Getter and setter (Integer). Return or set the exponent size in bits -assuming an IEEE 754 representation. -

-
-
rndMode
-

Getter and setter (Integer). Return or set the rounding mode. -

-
-
subnormal
-

Getter and setter (Boolean). subnormal flag. It is false when -expBits = expBitsMax. -

-
-
clearStatus()
-

Clear the status flags. -

-
-
invalidOperation
-
divideByZero
-
overflow
-
underflow
-
inexact
-

Getter and setter (Boolean). Status flags. -

-
-
- - -

5 BigDecimal

- -

This extension adds the BigDecimal primitive type. The -BigDecimal type represents floating point numbers in base -10. It is inspired from the proposal available at -https://github.com/littledan/proposal-bigdecimal. -

-

The BigDecimal floating point numbers are always normalized and -finite. There is no concept of -0, Infinity or -NaN. By default, all the computations are done with infinite -precision. -

- -

5.1 Operators

- -

The following builtin operators support BigDecimal: -

-
-
+
-
-
-
*
-

Both operands must be BigDecimal. The result is computed with infinite -precision. -

-
%
-

Both operands must be BigDecimal. The result is computed with infinite -precision. A range error is throws in case of division by zero. -

-
-
/
-

Both operands must be BigDecimal. A range error is throws in case of -division by zero or if the result cannot be represented with infinite -precision (use BigDecimal.div to specify the rounding). -

-
-
**
-

Both operands must be BigDecimal. The exponent must be a positive -integer. The result is computed with infinite precision. -

-
-
===
-

When one of the operand is a BigDecimal, return true if both operands -are a BigDecimal and if they are equal. -

-
-
==
-
!=
-
<=
-
>=
-
<
-
>
-
-

Numerical comparison. When one of the operand is not a BigDecimal, it is -converted to BigDecimal by using ToString(). Hence comparisons between -Number and BigDecimal do not use the exact mathematical value of the -Number value. -

-
-
- - -

5.2 BigDecimal literals

- -

BigDecimal literals are decimal floating point numbers with a trailing -m suffix. -

- -

5.3 Builtin Object changes

- - -

5.3.1 The BigDecimal function.

- -

It returns 0m if no parameter is provided. Otherwise the first -parameter is converted to a bigdecimal by using ToString(). Hence -Number values are not converted to their exact numerical value as -BigDecimal. -

- -

5.3.2 Properties of the BigDecimal object

- -
-
add(a, b[, e])
-
sub(a, b[, e])
-
mul(a, b[, e])
-
div(a, b[, e])
-
mod(a, b[, e])
-
sqrt(a, e)
-
round(a, e)
-

Perform the specified floating point operation and round the floating -point result according to the rounding object e. If the -rounding object is not present, the operation is executed with -infinite precision. -

-

For div, a RangeError exception is thrown in case of -division by zero or if the result cannot be represented with infinite -precision if no rounding object is present. -

-

For sqrt, a range error is thrown if a is less than -zero. -

-

The rounding object must contain the following properties: -roundingMode is a string specifying the rounding mode -("floor", "ceiling", "down", "up", -"half-even", "half-up"). Either -maximumSignificantDigits or maximumFractionDigits must -be present to specify respectively the number of significant digits -(must be >= 1) or the number of digits after the decimal point (must -be >= 0). -

-
-
- - -

5.3.3 Properties of the BigDecimal.prototype object

- -
-
valueOf()
-

Return the bigdecimal primitive value corresponding to this. -

-
-
toString()
-

Convert this to a string with infinite precision in base 10. -

-
-
toPrecision(p, rnd_mode = "half-up")
-
toFixed(p, rnd_mode = "half-up")
-
toExponential(p, rnd_mode = "half-up")
-

Convert the BigDecimal this to string with the specified -precision p. There is no limit on the accepted precision -p. The rounding mode can be optionally -specified. toPrecision outputs either in decimal fixed notation -or in decimal exponential notation with a p digits of -precision. toExponential outputs in decimal exponential -notation with p digits after the decimal point. toFixed -outputs in decimal notation with p digits after the decimal -point. -

-
-
- - -

6 Math mode

- -

A new math mode is enabled with the "use math" -directive. It propagates the same way as the strict mode. It is -designed so that arbitrarily large integers and floating point numbers -are available by default. In order to minimize the number of changes -in the Javascript semantics, integers are represented either as Number -or BigInt depending on their magnitude. Floating point numbers are -always represented as BigFloat. -

-

The following changes are made to the Javascript semantics: -

-
    -
  • Floating point literals (i.e. number with a decimal point or an exponent) are BigFloat by default (i.e. a l suffix is implied). Hence typeof 1.0 === "bigfloat". - -
  • Integer literals (i.e. numbers without a decimal point or an exponent) with or without the n suffix are BigInt if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to 2**53-1. Hence typeof 1 === "number ", typeof 1n === "number" but typeof 9007199254740992 === "bigint" . - -
  • All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt. - -
  • The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result. - -
  • The ^ operator is an alias to the power operator (**). - -
  • The power operator (both ^ and **) grammar is modified so that -2^2 is allowed and yields -4. - -
  • The logical xor operator is still available with the ^^ operator. - -
  • The modulo operator (%) returns the Euclidian remainder (always positive) instead of the truncated remainder. - -
  • The integer division operator can be overloaded with Operators.updateBigIntOperators(dictionary). - -
  • The integer power operator with a non zero negative exponent can be overloaded with Operators.updateBigIntOperators(dictionary). - -
- -
-
-

Footnotes

- -

(1)

-

The -rationale is that the rounding mode changes must always be -explicit.

-

(2)

-

The rationale is to avoid side effects for the built-in -operators.

-

(3)

-

Base 10 floating point literals cannot usually be -exactly represented as base 2 floating point number. In order to -ensure that the literal is represented accurately with the current -precision, it must be evaluated at runtime.

-

(4)

-

Could be removed in case a deterministic behavior for floating point operations is required.

-
-
- - - - - diff --git a/doc/jsbignum.pdf b/doc/jsbignum.pdf deleted file mode 100644 index 442a8c0..0000000 Binary files a/doc/jsbignum.pdf and /dev/null differ diff --git a/doc/jsbignum.texi b/doc/jsbignum.texi deleted file mode 100644 index 079d920..0000000 --- a/doc/jsbignum.texi +++ /dev/null @@ -1,589 +0,0 @@ -\input texinfo - -@iftex -@afourpaper -@headings double -@end iftex - -@titlepage -@afourpaper -@sp 7 -@center @titlefont{Javascript Bignum Extensions} -@sp 3 -@center Version 2020-01-11 -@sp 3 -@center Author: Fabrice Bellard -@end titlepage - -@setfilename jsbignum.info -@settitle Javascript Bignum Extensions - -@contents - -@chapter Introduction - -The Bignum extensions add the following features to the Javascript -language while being 100% backward compatible: - -@itemize - -@item Operator overloading with a dispatch logic inspired from the proposal available at @url{https://github.com/tc39/proposal-operator-overloading/}. - -@item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics. - -@item Arbitrarily large floating point numbers (@code{BigDecimal}) in base 10 based on the proposal available at -@url{https://github.com/littledan/proposal-bigdecimal}. - -@item @code{math} mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (@code{%}) is defined as the Euclidian -remainder. @code{^} is an alias to the power operator -(@code{**}). @code{^^} is used as the exclusive or operator. - -@end itemize - -The extensions are independent from each other except the @code{math} -mode which relies on BigFloat and operator overloading. - -@chapter Operator overloading - -Operator overloading is inspired from the proposal available at -@url{https://github.com/tc39/proposal-operator-overloading/}. It -implements the same dispatch logic but finds the operator sets by -looking at the @code{Symbol.operatorSet} property in the objects. The -changes were done in order to simplify the implementation. - -More precisely, the following modifications were made: - -@itemize - -@item @code{with operators from} is not supported. Operator overloading is always enabled. - -@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object. - -@item @code{Operators.create(...dictionaries)} is used to create a new OperatorSet object. The @code{Operators} function is supported as an helper to be closer to the TC39 proposal. - -@item @code{[]} cannot be overloaded. - -@item In math mode, the BigInt division and power operators can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}. - -@end itemize - -@chapter BigInt extensions - -A few properties are added to the BigInt object: - -@table @code - -@item tdiv(a, b) -Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError -exception. - -@item fdiv(a, b) -Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError -exception. - -@item cdiv(a, b) -Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError -exception. - -@item ediv(a, b) -Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian -division). @code{b = 0} raises a RangeError exception. - -@item tdivrem(a, b) -@item fdivrem(a, b) -@item cdivrem(a, b) -@item edivrem(a, b) -Return an array of two elements. The first element is the quotient, -the second is the remainder. The same rounding is done as the -corresponding division operation. - -@item sqrt(a) -Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is -raised if @math{a < 0}. - -@item sqrtrem(a) -Return an array of two elements. The first element is @math{\lfloor -\sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a} -\rfloor^2}. A RangeError exception is raised if @math{a < 0}. - -@item floorLog2(a) -Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}. - -@item ctz(a) -Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}. - -@end table - -@chapter BigFloat - -@section Introduction - -This extension adds the @code{BigFloat} primitive type. The -@code{BigFloat} type represents floating point numbers in base 2 -with the IEEE 754 semantics. A floating -point number is represented as a sign, mantissa and exponent. The -special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0} -are supported. The mantissa and exponent can have any bit length with -an implementation specific minimum and maximum. - -@section Floating point rounding - -Each floating point operation operates with infinite precision and -then rounds the result according to the specified floating point -environment (@code{BigFloatEnv} object). The status flags of the -environment are also set according to the result of the operation. - -If no floating point environment is provided, the global floating -point environment is used. - -The rounding mode of the global floating point environment is always -@code{RNDN} (``round to nearest with ties to even'')@footnote{The -rationale is that the rounding mode changes must always be -explicit.}. The status flags of the global environment cannot be -read@footnote{The rationale is to avoid side effects for the built-in -operators.}. The precision of the global environment is -@code{BigFloatEnv.prec}. The number of exponent bits of the global -environment is @code{BigFloatEnv.expBits}. The global environment -subnormal flag is set to @code{true}. - -For example, @code{prec = 53} and @code{ expBits = 11} exactly give -the same precision as the IEEE 754 64 bit floating point format. The -default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE -754 128 bit floating point format). - -The global floating point environment can only be modified temporarily -when calling a function (see @code{BigFloatEnv.setPrec}). Hence a -function can change the global floating point environment for its -callees but not for its caller. - -@section Operators - -The builtin operators are extended so that a BigFloat is returned if -at least one operand is a BigFloat. The computations are always done -with infinite precision and rounded according to the global floating -point environment. - -@code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}. - -BigFloat can be compared with all the other numeric types and the -result follows the expected mathematical relations. - -However, since BigFloat and Number are different types they are never -equal when using the strict comparison operators (e.g. @code{0.0 === -0.0l} is false). - -@section BigFloat literals - -BigFloat literals are floating point numbers with a trailing @code{l} -suffix. BigFloat literals have an infinite precision. They are rounded -according to the global floating point environment when they are -evaluated.@footnote{Base 10 floating point literals cannot usually be -exactly represented as base 2 floating point number. In order to -ensure that the literal is represented accurately with the current -precision, it must be evaluated at runtime.} - -@section Builtin Object changes - -@subsection @code{BigFloat} function - -The @code{BigFloat} function cannot be invoked as a constructor. When -invoked as a function: the parameter is converted to a primitive -type. If the result is a numeric type, it is converted to BigFloat -without rounding. If the result is a string, it is converted to -BigFloat using the precision of the global floating point environment. - -@code{BigFloat} properties: - -@table @code - -@item LN2 -@item PI -Getter. Return the value of the corresponding mathematical constant -rounded to nearest, ties to even with the current global -precision. The constant values are cached for small precisions. - -@item MIN_VALUE -@item MAX_VALUE -@item EPSILON -Getter. Return the minimum, maximum and epsilon @code{BigFloat} values -(same definition as the corresponding @code{Number} constants). - -@item fpRound(a[, e]) -Round the floating point number @code{a} according to the floating -point environment @code{e} or the global environment if @code{e} is -undefined. - -@item parseFloat(a[, radix[, e]]) -Parse the string @code{a} as a floating point number in radix -@code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0 -means radix 10 unless there is a hexadecimal or binary prefix. The -result is rounded according to the floating point environment @code{e} -or the global environment if @code{e} is undefined. - -@item isFinite(a) -Return true if @code{a} is a finite bigfloat. - -@item isNaN(a) -Return true if @code{a} is a NaN bigfloat. - -@item add(a, b[, e]) -@item sub(a, b[, e]) -@item mul(a, b[, e]) -@item div(a, b[, e]) -Perform the specified floating point operation and round the floating -point number @code{a} according to the floating point environment -@code{e} or the global environment if @code{e} is undefined. If -@code{e} is specified, the floating point status flags are updated. - -@item floor(x) -@item ceil(x) -@item round(x) -@item trunc(x) -Round to an integer. No additional rounding is performed. - -@item abs(x) -Return the absolute value of x. No additional rounding is performed. - -@item fmod(x, y[, e]) -@item remainder(x, y[, e]) -Floating point remainder. The quotient is truncated to zero (fmod) or -to the nearest integer with ties to even (remainder). @code{e} is an -optional floating point environment. - -@item sqrt(x[, e]) -Square root. Return a rounded floating point number. @code{e} is an -optional floating point environment. - -@item sin(x[, e]) -@item cos(x[, e]) -@item tan(x[, e]) -@item asin(x[, e]) -@item acos(x[, e]) -@item atan(x[, e]) -@item atan2(x, y[, e]) -@item exp(x[, e]) -@item log(x[, e]) -@item pow(x, y[, e]) -Transcendental operations. Return a rounded floating point -number. @code{e} is an optional floating point environment. - -@end table - -@subsection @code{BigFloat.prototype} - -The following properties are modified: - -@table @code -@item valueOf() -Return the bigfloat primitive value corresponding to @code{this}. - -@item toString(radix) - -For floating point numbers: - -@itemize -@item -If the radix is a power of two, the conversion is done with infinite -precision. -@item -Otherwise, the number is rounded to nearest with ties to even using -the global precision. It is then converted to string using the minimum -number of digits so that its conversion back to a floating point using -the global precision and round to nearest gives the same number. - -@end itemize - -The exponent letter is @code{e} for base 10, @code{p} for bases 2, 8, -16 with a binary exponent and @code{@@} for the other bases. - -@item toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10) -@item toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10) -@item toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10) -Same semantics as the corresponding @code{Number} functions with -BigFloats. There is no limit on the accepted precision @code{p}. The -rounding mode and radix can be optionally specified. The radix must be -between 2 and 36. - -@end table - -@subsection @code{BigFloatEnv} constructor - -The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a -function. The floating point environment contains: - -@itemize -@item the mantissa precision in bits - -@item the exponent size in bits assuming an IEEE 754 representation; - -@item the subnormal flag (if true, subnormal floating point numbers can -be generated by the floating point operations). - -@item the rounding mode - -@item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters. - -@end itemize - -@code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point -environment. The status flags are reset. If no parameter is given the -precision, exponent bits and subnormal flags are copied from the -global floating point environment. Otherwise, the precision is set to -@code{p}, the number of exponent bits is set to @code{expBitsMax} and the -subnormal flags is set to @code{false}. If @code{rndMode} is -@code{undefined}, the rounding mode is set to @code{RNDN}. - -@code{BigFloatEnv} properties: - -@table @code - -@item prec -Getter. Return the precision in bits of the global floating point -environment. The initial value is @code{113}. - -@item expBits -Getter. Return the exponent size in bits of the global floating point -environment assuming an IEEE 754 representation. The initial value is -@code{15}. - -@item setPrec(f, p[, e]) -Set the precision of the global floating point environment to @code{p} -and the exponent size to @code{e} then call the function -@code{f}. Then the Float precision and exponent size are reset to -their precious value and the return value of @code{f} is returned (or -an exception is raised if @code{f} raised an exception). If @code{e} -is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}. - -@item precMin -Read-only integer. Return the minimum allowed precision. Must be at least 2. - -@item precMax -Read-only integer. Return the maximum allowed precision. Must be at least 113. - -@item expBitsMin -Read-only integer. Return the minimum allowed exponent size in -bits. Must be at least 3. - -@item expBitsMax -Read-only integer. Return the maximum allowed exponent size in -bits. Must be at least 15. - -@item RNDN -Read-only integer. Round to nearest, with ties to even rounding mode. - -@item RNDZ -Read-only integer. Round to zero rounding mode. - -@item RNDD -Read-only integer. Round to -Infinity rounding mode. - -@item RNDU -Read-only integer. Round to +Infinity rounding mode. - -@item RNDNA -Read-only integer. Round to nearest, with ties away from zero rounding mode. - -@item RNDA -Read-only integer. Round away from zero rounding mode. - -@item RNDF@footnote{Could be removed in case a deterministic behavior for floating point operations is required.} -Read-only integer. Faithful rounding mode. The result is -non-deterministically rounded to -Infinity or +Infinity. This rounding -mode usually gives a faster and deterministic running time for the -floating point operations. - -@end table - -@code{BigFloatEnv.prototype} properties: - -@table @code - -@item prec -Getter and setter (Integer). Return or set the precision in bits. - -@item expBits -Getter and setter (Integer). Return or set the exponent size in bits -assuming an IEEE 754 representation. - -@item rndMode -Getter and setter (Integer). Return or set the rounding mode. - -@item subnormal -Getter and setter (Boolean). subnormal flag. It is false when -@code{expBits = expBitsMax}. - -@item clearStatus() -Clear the status flags. - -@item invalidOperation -@item divideByZero -@item overflow -@item underflow -@item inexact -Getter and setter (Boolean). Status flags. - -@end table - -@chapter BigDecimal - -This extension adds the @code{BigDecimal} primitive type. The -@code{BigDecimal} type represents floating point numbers in base -10. It is inspired from the proposal available at -@url{https://github.com/littledan/proposal-bigdecimal}. - -The @code{BigDecimal} floating point numbers are always normalized and -finite. There is no concept of @code{-0}, @code{Infinity} or -@code{NaN}. By default, all the computations are done with infinite -precision. - -@section Operators - -The following builtin operators support BigDecimal: - -@table @code - -@item + -@item - -@item * -Both operands must be BigDecimal. The result is computed with infinite -precision. -@item % -Both operands must be BigDecimal. The result is computed with infinite -precision. A range error is throws in case of division by zero. - -@item / -Both operands must be BigDecimal. A range error is throws in case of -division by zero or if the result cannot be represented with infinite -precision (use @code{BigDecimal.div} to specify the rounding). - -@item ** -Both operands must be BigDecimal. The exponent must be a positive -integer. The result is computed with infinite precision. - -@item === -When one of the operand is a BigDecimal, return true if both operands -are a BigDecimal and if they are equal. - -@item == -@item != -@item <= -@item >= -@item < -@item > - -Numerical comparison. When one of the operand is not a BigDecimal, it is -converted to BigDecimal by using ToString(). Hence comparisons between -Number and BigDecimal do not use the exact mathematical value of the -Number value. - -@end table - -@section BigDecimal literals - -BigDecimal literals are decimal floating point numbers with a trailing -@code{m} suffix. - -@section Builtin Object changes - -@subsection The @code{BigDecimal} function. - -It returns @code{0m} if no parameter is provided. Otherwise the first -parameter is converted to a bigdecimal by using ToString(). Hence -Number values are not converted to their exact numerical value as -BigDecimal. - -@subsection Properties of the @code{BigDecimal} object - -@table @code - -@item add(a, b[, e]) -@item sub(a, b[, e]) -@item mul(a, b[, e]) -@item div(a, b[, e]) -@item mod(a, b[, e]) -@item sqrt(a, e) -@item round(a, e) -Perform the specified floating point operation and round the floating -point result according to the rounding object @code{e}. If the -rounding object is not present, the operation is executed with -infinite precision. - -For @code{div}, a @code{RangeError} exception is thrown in case of -division by zero or if the result cannot be represented with infinite -precision if no rounding object is present. - -For @code{sqrt}, a range error is thrown if @code{a} is less than -zero. - -The rounding object must contain the following properties: -@code{roundingMode} is a string specifying the rounding mode -(@code{"floor"}, @code{"ceiling"}, @code{"down"}, @code{"up"}, -@code{"half-even"}, @code{"half-up"}). Either -@code{maximumSignificantDigits} or @code{maximumFractionDigits} must -be present to specify respectively the number of significant digits -(must be >= 1) or the number of digits after the decimal point (must -be >= 0). - -@end table - -@subsection Properties of the @code{BigDecimal.prototype} object - -@table @code -@item valueOf() -Return the bigdecimal primitive value corresponding to @code{this}. - -@item toString() -Convert @code{this} to a string with infinite precision in base 10. - -@item toPrecision(p, rnd_mode = "half-up") -@item toFixed(p, rnd_mode = "half-up") -@item toExponential(p, rnd_mode = "half-up") -Convert the BigDecimal @code{this} to string with the specified -precision @code{p}. There is no limit on the accepted precision -@code{p}. The rounding mode can be optionally -specified. @code{toPrecision} outputs either in decimal fixed notation -or in decimal exponential notation with a @code{p} digits of -precision. @code{toExponential} outputs in decimal exponential -notation with @code{p} digits after the decimal point. @code{toFixed} -outputs in decimal notation with @code{p} digits after the decimal -point. - -@end table - -@chapter Math mode - -A new @emph{math mode} is enabled with the @code{"use math"} -directive. It propagates the same way as the @emph{strict mode}. It is -designed so that arbitrarily large integers and floating point numbers -are available by default. In order to minimize the number of changes -in the Javascript semantics, integers are represented either as Number -or BigInt depending on their magnitude. Floating point numbers are -always represented as BigFloat. - -The following changes are made to the Javascript semantics: - -@itemize - -@item Floating point literals (i.e. number with a decimal point or an exponent) are @code{BigFloat} by default (i.e. a @code{l} suffix is implied). Hence @code{typeof 1.0 === "bigfloat"}. - -@item Integer literals (i.e. numbers without a decimal point or an exponent) with or without the @code{n} suffix are @code{BigInt} if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to @code{2**53-1}. Hence @code{typeof 1 === "number "}, @code{typeof 1n === "number"} but @code{typeof 9007199254740992 === "bigint" }. - -@item All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt. - -@item The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result. - -@item The @code{^} operator is an alias to the power operator (@code{**}). - -@item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}. - -@item The logical xor operator is still available with the @code{^^} operator. - -@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder. - -@item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}. - -@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}. - -@end itemize - -@bye diff --git a/doc/quickjs.html b/doc/quickjs.html deleted file mode 100644 index 1ac9c54..0000000 --- a/doc/quickjs.html +++ /dev/null @@ -1,1410 +0,0 @@ - - - - -QuickJS Javascript Engine - - - - - - - - - - - - - - - -

QuickJS Javascript Engine

- - -

Table of Contents

- - - - - -

1 Introduction

- -

QuickJS is a small and embeddable Javascript engine. It supports most of the -ES2023 specification -1 -including modules, asynchronous generators, proxies and BigInt. -

-

It supports mathematical extensions such as big decimal float float -numbers (BigDecimal), big binary floating point numbers (BigFloat), -and operator overloading. -

- -

1.1 Main Features

- -
    -
  • Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple “hello world” program. - -
  • Fast interpreter with very low startup time: runs the 77000 tests of the ECMAScript Test Suite2 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. - -
  • Almost complete ES2023 support including modules, asynchronous -generators and full Annex B support (legacy web compatibility). Some -features from the upcoming ES2024 specification -3 are also supported. - -
  • Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2023 features. - -
  • Compile Javascript sources to executables with no external dependency. - -
  • Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal. - -
  • Mathematical extensions: BigDecimal, BigFloat, operator overloading, bigint mode, math mode. - -
  • Command line interpreter with contextual colorization and completion implemented in Javascript. - -
  • Small built-in standard library with C library wrappers. - -
- - -

2 Usage

- - -

2.1 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 Makefile if you wish to select specific -options then run make. -

-

You can type make install as root if you wish to install the binaries and support files to -/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 --latomics in the Makefile LIBS variable or disable -CONFIG_ATOMICS in quickjs.c. -

- -

2.2 Quick start

- -

qjs is the command line interpreter (Read-Eval-Print Loop). You can pass -Javascript files and/or expressions as arguments to execute them: -

-
-
./qjs examples/hello.js
-
- -

qjsc is the command line compiler: -

-
-
./qjsc -o hello examples/hello.js
-./hello
-
- -

generates a hello executable with no external dependency. -

- -

2.3 Command line options

- - -

2.3.1 qjs interpreter

- -
usage: qjs [options] [file [args]]
-
-

Options are: -

-
-h
-
--help
-

List options. -

-
-
-e EXPR
-
--eval EXPR
-

Evaluate EXPR. -

-
-
-i
-
--interactive
-

Go to interactive mode (it is not the default when files are provided on the command line). -

-
-
-m
-
--module
-

Load as ES6 module (default=autodetect). A module is autodetected if -the filename extension is .mjs or if the first keyword of the -source is import. -

-
-
--script
-

Load as ES6 script (default=autodetect). -

-
-
--bignum
-

Enable the bignum extensions: BigDecimal object, BigFloat object and -the "use math" directive. -

-
-
-I file
-
--include file
-

Include an additional file. -

-
-
- -

Advanced options are: -

-
-
--std
-

Make the std and os modules available to the loaded -script even if it is not a module. -

-
-
-d
-
--dump
-

Dump the memory usage stats. -

-
-
-q
-
--quit
-

just instantiate the interpreter and quit. -

-
-
- - -

2.3.2 qjsc compiler

- -
usage: qjsc [options] [files]
-
-

Options are: -

-
-c
-

Only output bytecode in a C file. The default is to output an executable file. -

-
-e
-

Output main() and bytecode in a C file. The default is to output an -executable file. -

-
-o output
-

Set the output filename (default = out.c or a.out). -

-
-
-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 and its dependencies. This option -is needed when your code uses the import keyword or the -os.Worker constructor because the compiler cannot statically -find the name of the dynamically loaded modules. -

-
-
-M module_name[,cname]
-

Add initialization code for an external C module. See the -c_module example. -

-
-
-x
-

Byte swapped output (only used for cross compilation). -

-
-
-flto
-

Use link time optimization. The compilation is slower but the -executable is smaller and faster. This option is automatically set -when the -fno-x options are used. -

-
-
-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint]
-

Disable selected language features to produce a smaller executable file. -

-
-
-fbignum
-

Enable the bignum extensions: BigDecimal object, BigFloat object and -the "use math" directive. -

-
-
- - -

2.4 qjscalc application

- -

The qjscalc application is a superset of the qjs -command line interpreter implementing a Javascript calculator with -arbitrarily large integer and floating point numbers, fractions, -complex numbers, polynomials and matrices. The source code is in -qjscalc.js. More documentation and a web version are available at -http://numcalc.com. -

- -

2.5 Built-in tests

- -

Run make test to run the few built-in tests included in the -QuickJS archive. -

- -

2.6 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: -

-
-
git clone https://github.com/tc39/test262.git test262
-cd test262
-patch -p1 < ../tests/test262.patch
-cd ..
-
- -

The patch adds the implementation specific 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 -

-
make test2
-
- -

The configuration files test262.conf -(resp. test262o.conf for the old ES5.1 tests4)) -contain the options to run the various tests. Tests can be excluded -based on features or filename. -

-

The file 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 -u option -to update the current list of errors (or make test2-update). -

-

The file 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 ./run-test262 -c test262.conf -f filename.js to -run a single test. Use the syntax ./run-test262 -c test262.conf -N to start testing at test number N. -

-

For more information, run ./run-test262 to see the command line -options of the test262 runner. -

-

run-test262 accepts the -N option to be invoked from -test262-harness5 -thru 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). -

- -

3 Specifications

- - -

3.1 Language support

- - -

3.1.1 ES2023 support

- -

The ES2023 specification is almost fully supported including the Annex -B (legacy web compatibility) and the Unicode related features. -

-

The following features are not supported yet: -

-
    -
  • Tail calls6 - -
  • WeakRef and FinalizationRegistry objects - -
  • Symbols as WeakMap keys - -
- - -

3.1.2 ECMA402

- -

ECMA402 (Internationalization API) is not supported. -

- -

3.1.3 Extensions

- -
    -
  • The directive "use strip" indicates that the debug information (including the source code of the functions) should not be retained to save memory. As "use strict", the directive can be global to a script or local to a function. - -
  • The first line of a script beginning with #! is ignored. - -
- - -

3.1.4 Mathematical extensions

- -

The mathematical extensions are fully backward compatible with -standard Javascript. See jsbignum.pdf for more information. -

-
    -
  • BigDecimal support: arbitrary large floating point numbers in base 10. - -
  • BigFloat support: arbitrary large floating point numbers in base 2. - -
  • Operator overloading. - -
  • The directive "use bigint" enables the bigint mode where integers are BigInt by default. - -
  • The directive "use math" enables the math mode where the division and power operators on integers produce fractions. Floating point literals are BigFloat by default and integers are BigInt by default. - -
- - -

3.2 Modules

- -

ES6 modules are fully supported. The default name resolution is the -following: -

-
    -
  • Module names with a leading . or .. are relative -to the current module path. - -
  • Module names without a leading . or .. are system -modules, such as std or os. - -
  • Module names ending with .so are native modules using the -QuickJS C API. - -
- - -

3.3 Standard library

- -

The standard library is included by default in the command line -interpreter. It contains the two modules std and os and -a few global objects. -

- -

3.3.1 Global objects

- -
-
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(). -

-
-
- - -

3.3.2 std module

- -

The std module provides wrappers to the libc stdlib.h -and stdio.h and a few other utilities. -

-

Available exports: -

-
-
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. -

-
- -
-
loadScript(filename)
-

Evaluate the file filename as a script (global eval). -

-
-
loadFile(filename)
-

Load the file filename and return it as a string assuming UTF-8 -encoding. Return null in case of I/O error. -

-
-
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 occured. -

-
-
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 occured. -

-
-
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 occured. -

-
-
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 occured. -

-
-
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. -

-
-
SEEK_SET
-
SEEK_CUR
-
SEEK_END
-

Constants for seek(). -

-
-
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. -

-
-
- -
-
parseExtJSON(str)
-
-

Parse str using a superset of JSON.parse. The - following extensions are accepted: -

-
    -
  • Single line and multiline comments -
  • unquoted properties (ASCII-only Javascript identifiers) -
  • trailing comma in array and object definitions -
  • single quoted strings -
  • \f and \v are accepted as space characters -
  • leading plus in numbers -
  • octal (0o prefix) and hexadecimal (0x prefix) numbers -
-
-
- -

FILE prototype: -

-
-
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. -

-
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. -

-
-
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 up 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. -

-
- - -

3.3.3 os module

- -

The os module provides Operating System specific functions: -

-
    -
  • low level file access -
  • signals -
  • timers -
  • asynchronous I/O -
  • workers (threads) -
- -

The OS functions usually return 0 if OK or an OS specific negative -error code. -

-

Available exports: -

-
-
open(filename, flags, mode = 0o666)
-

Open a file. Return a handle or < 0 if error. -

-
-
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. -

-
-
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. -

-
-
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. -

-
-
- -
-
getpid()
-

Return the current process ID. -

-
-
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: -

-
await os.sleepAsync(500);
-
- -
-
now()
-

Return a timestamp in milliseconds with more precision than -Date.now(). The time origin is unspecified and is normally not -impacted by system clock adjustments. -

-
-
setTimeout(func, delay)
-

Call the function func after delay ms. Return a handle -to the timer. -

-
-
clearTimeout(handle)
-

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 the -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. -

-

Current limitations: Map and Set are not supported - yet. -

-
-
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. -

-
-
- -
-
- - -

3.4 QuickJS C API

- -

The C API was designed to be simple and efficient. The C API is -defined in the header quickjs.h. -

- -

3.4.1 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. -

- -

3.4.2 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. -

- -

3.4.3 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 JSValues as parameters -(so they don’t need to free them) and return a newly allocated (=live) -JSValue. -

- -

3.4.4 Exceptions

- -

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(). -

- -

3.4.5 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. That’s why there is no option to output the bytecode to a -binary file in qjsc. -

- -

3.4.6 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 globally allocated (i.e. for all runtimes). 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. -

- -

3.4.7 C Modules

- -

Native ES6 modules are supported and can be dynamically or statically -linked. Look at the test_bjson and bjson.so -examples. The standard library quickjs-libc.c is also a good example -of a native module. -

- -

3.4.8 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(). -

- -

3.4.9 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. -

- -

4 Internals

- - -

4.1 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. -

- -

4.2 Executable generation

- - -

4.2.1 qjsc compiler

- -

The qjsc compiler generates C sources from Javascript files. By -default the C sources are compiled with the system compiler -(gcc or 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 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 eval or the regular expressions. The -code removal relies on the Link Time Optimization of the system -compiler. -

- -

4.2.2 Binary JSON

- -

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 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 test_bjson.js -example is only used to test the binary object format functions. -

- -

4.3 Runtime

- - -

4.3.1 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. -

- -

4.3.2 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. -

- -

4.3.3 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. -

- -

4.3.4 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. -

- -

4.3.5 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. -

- -

4.3.6 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. -

- -

4.3.7 Function call

- -

The engine is optimized so that function calls are fast. The system -stack holds the Javascript parameters and local variables. -

- -

4.4 RegExp

- -

A specific regular expression engine was developed. It is both small -and efficient and supports all the ES2023 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. -

- -

4.5 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). -

- -

4.6 BigInt, BigFloat, BigDecimal

- -

BigInt, BigFloat and BigDecimal are implemented with the libbf -library7. It weights about 90 -KiB (x86 code) and provides arbitrary precision IEEE 754 floating -point operations and transcendental functions with exact rounding. -

- -

5 License

- -

QuickJS is released under the MIT license. -

-

Unless otherwise specified, the QuickJS sources are copyright Fabrice -Bellard and Charlie Gordon. -

-
-
-

Footnotes

- -

(1)

-

https://tc39.es/ecma262/2023

-

(2)

-

https://github.com/tc39/test262

-

(3)

-

https://tc39.es/ecma262/

-

(4)

-

The old -ES5.1 tests can be extracted with git clone --single-branch ---branch es5-tests https://github.com/tc39/test262.git test262o

-

(5)

-

https://github.com/bterlson/test262-harness

-

(6)

-

We believe the current specification of tails calls is too complicated and presents limited practical interests.

-

(7)

-

https://bellard.org/libbf

-
-
- - - - - diff --git a/doc/quickjs.pdf b/doc/quickjs.pdf deleted file mode 100644 index 2338d7a..0000000 Binary files a/doc/quickjs.pdf and /dev/null differ diff --git a/doc/quickjs.texi b/doc/quickjs.texi deleted file mode 100644 index 898d46c..0000000 --- a/doc/quickjs.texi +++ /dev/null @@ -1,1120 +0,0 @@ -\input texinfo - -@iftex -@afourpaper -@headings double -@end iftex - -@titlepage -@afourpaper -@sp 7 -@center @titlefont{QuickJS Javascript Engine} -@sp 3 -@end titlepage - -@setfilename spec.info -@settitle QuickJS Javascript Engine - -@contents - -@chapter Introduction - -QuickJS is a small and embeddable Javascript engine. It supports most of the -ES2023 specification -@footnote{@url{https://tc39.es/ecma262/2023 }} -including modules, asynchronous generators, proxies and BigInt. - -It supports mathematical extensions such as big decimal float float -numbers (BigDecimal), big binary floating point numbers (BigFloat), -and operator overloading. - -@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 ES2023 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 ES2023 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 Mathematical extensions: BigDecimal, BigFloat, operator overloading, bigint mode, math mode. - -@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 --bignum -Enable the bignum extensions: BigDecimal object, BigFloat object and -the @code{"use math"} directive. - -@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. - -@item -fbignum -Enable the bignum extensions: BigDecimal object, BigFloat object and -the @code{"use math"} directive. - -@end table - -@section @code{qjscalc} application - -The @code{qjscalc} application is a superset of the @code{qjs} -command line interpreter implementing a Javascript calculator with -arbitrarily large integer and floating point numbers, fractions, -complex numbers, polynomials and matrices. The source code is in -@file{qjscalc.js}. More documentation and a web version are available at -@url{http://numcalc.com}. - -@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 ES2023 support - -The ES2023 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 WeakRef and FinalizationRegistry objects - -@item Symbols as WeakMap keys - -@end itemize - -@subsection ECMA402 - -ECMA402 (Internationalization API) is not supported. - -@subsection Extensions - -@itemize - -@item The directive @code{"use strip"} indicates that the debug information (including the source code of the functions) should not be retained to save memory. As @code{"use strict"}, the directive can be global to a script or local to a function. - -@item The first line of a script beginning with @code{#!} is ignored. - -@end itemize - -@subsection Mathematical extensions - -The mathematical extensions are fully backward compatible with -standard Javascript. See @code{jsbignum.pdf} for more information. - -@itemize - -@item @code{BigDecimal} support: arbitrary large floating point numbers in base 10. - -@item @code{BigFloat} support: arbitrary large floating point numbers in base 2. - -@item Operator overloading. - -@item The directive @code{"use bigint"} enables the bigint mode where integers are @code{BigInt} by default. - -@item The directive @code{"use math"} enables the math mode where the division and power operators on integers produce fractions. Floating point literals are @code{BigFloat} by default and integers are @code{BigInt} by default. - -@end itemize - -@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. - @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 - 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{\f} and @code{\v} are accepted as space characters - @item leading plus in numbers - @item octal (@code{0o} prefix) and hexadecimal (@code{0x} prefix) 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 ES2023 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, BigFloat, BigDecimal - -BigInt, BigFloat and BigDecimal are implemented with the @code{libbf} -library@footnote{@url{https://bellard.org/libbf}}. It weights about 90 -KiB (x86 code) and provides arbitrary precision IEEE 754 floating -point operations and transcendental functions with exact rounding. - -@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/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..b2d6de3 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,20 @@ +# 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/docs/.nvmrc b/docs/.nvmrc new file mode 100644 index 0000000..3c03207 --- /dev/null +++ b/docs/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/docs/babel.config.js b/docs/babel.config.js new file mode 100644 index 0000000..e00595d --- /dev/null +++ b/docs/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/docs/docs/building.md b/docs/docs/building.md new file mode 100644 index 0000000..3737a31 --- /dev/null +++ b/docs/docs/building.md @@ -0,0 +1,53 @@ +--- +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. + +## 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/docs/docs/cli.md b/docs/docs/cli.md new file mode 100644 index 0000000..2ef6d11 --- /dev/null +++ b/docs/docs/cli.md @@ -0,0 +1,130 @@ +--- +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/docs/docs/developer-guide/_category_.json b/docs/docs/developer-guide/_category_.json new file mode 100644 index 0000000..6050477 --- /dev/null +++ b/docs/docs/developer-guide/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Developer Guide", + "position": 6, + "link": { + "type": "generated-index" + } +} diff --git a/docs/docs/developer-guide/api.md b/docs/docs/developer-guide/api.md new file mode 100644 index 0000000..78bec94 --- /dev/null +++ b/docs/docs/developer-guide/api.md @@ -0,0 +1,3 @@ +# API Reference + +WIP. diff --git a/docs/docs/developer-guide/internals.md b/docs/docs/developer-guide/internals.md new file mode 100644 index 0000000..4c9afea --- /dev/null +++ b/docs/docs/developer-guide/internals.md @@ -0,0 +1,117 @@ +# 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/docs/docs/developer-guide/intro.md b/docs/docs/developer-guide/intro.md new file mode 100644 index 0000000..4d85efb --- /dev/null +++ b/docs/docs/developer-guide/intro.md @@ -0,0 +1,113 @@ +--- +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/docs/docs/diff.md b/docs/docs/diff.md new file mode 100644 index 0000000..1390e1b --- /dev/null +++ b/docs/docs/diff.md @@ -0,0 +1,68 @@ +# 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/docs/docs/es_features.md b/docs/docs/es_features.md new file mode 100644 index 0000000..d57754c --- /dev/null +++ b/docs/docs/es_features.md @@ -0,0 +1,11 @@ +--- +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/docs/docs/installation.md b/docs/docs/installation.md new file mode 100644 index 0000000..5df467c --- /dev/null +++ b/docs/docs/installation.md @@ -0,0 +1,34 @@ +--- +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/docs/docs/intro.md b/docs/docs/intro.md new file mode 100644 index 0000000..cb63ed5 --- /dev/null +++ b/docs/docs/intro.md @@ -0,0 +1,33 @@ +--- +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/docs/docs/projects.md b/docs/docs/projects.md new file mode 100644 index 0000000..d499a09 --- /dev/null +++ b/docs/docs/projects.md @@ -0,0 +1,28 @@ +# 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. diff --git a/docs/docs/stdlib.md b/docs/docs/stdlib.md new file mode 100644 index 0000000..1cb447e --- /dev/null +++ b/docs/docs/stdlib.md @@ -0,0 +1,553 @@ +--- +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. + +### `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. + +### `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`. + +### `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. + +### `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. + +#### `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 up 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/docs/docs/supported_platforms.md b/docs/docs/supported_platforms.md new file mode 100644 index 0000000..57fd7ea --- /dev/null +++ b/docs/docs/supported_platforms.md @@ -0,0 +1,18 @@ +--- +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 8 | VS >= 2022 and Clang are supported | +| 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! | diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js new file mode 100644 index 0000000..25524ed --- /dev/null +++ b/docs/docusaurus.config.js @@ -0,0 +1,114 @@ +// @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/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 0000000..f13c2d8 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,14656 @@ +{ + "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/docs/package.json b/docs/package.json new file mode 100644 index 0000000..4acf04c --- /dev/null +++ b/docs/package.json @@ -0,0 +1,42 @@ +{ + "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/docs/sidebars.js b/docs/sidebars.js new file mode 100644 index 0000000..3efb4ff --- /dev/null +++ b/docs/sidebars.js @@ -0,0 +1,20 @@ +/** + * 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/docs/src/css/custom.css b/docs/src/css/custom.css new file mode 100644 index 0000000..2bc6a4c --- /dev/null +++ b/docs/src/css/custom.css @@ -0,0 +1,30 @@ +/** + * 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/test262o_errors.txt b/docs/static/.nojekyll similarity index 100% rename from test262o_errors.txt rename to docs/static/.nojekyll diff --git a/docs/static/img/favicon.ico b/docs/static/img/favicon.ico new file mode 100644 index 0000000..c01d54b Binary files /dev/null and b/docs/static/img/favicon.ico differ diff --git a/examples/fib.c b/examples/fib.c index c77b705..b965acc 100644 --- a/examples/fib.c +++ b/examples/fib.c @@ -1,6 +1,6 @@ /* * QuickJS: Example of C module - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -35,8 +35,8 @@ static int fib(int n) return fib(n - 1) + fib(n - 2); } -static JSValue js_fib(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_fib(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int n, res; if (JS_ToInt32(ctx, &n, argv[0])) @@ -61,7 +61,15 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m) #define JS_INIT_MODULE js_init_module_fib #endif -JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +#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 *m; m = JS_NewCModule(ctx, module_name, js_fib_init); diff --git a/examples/fib_require.js b/examples/fib_require.js deleted file mode 100644 index eb98fec..0000000 --- a/examples/fib_require.js +++ /dev/null @@ -1,9 +0,0 @@ -function fib(n) -{ - if (n <= 0) - return 0; - else if (n == 1) - return 1; - else - return fib(n - 1) + fib(n - 2); -} diff --git a/examples/hello-require.js b/examples/hello-require.js deleted file mode 100644 index 65dadfb..0000000 --- a/examples/hello-require.js +++ /dev/null @@ -1,6 +0,0 @@ -/* example of JS module */ - -const fibModule = require("./fib_require.js"); - -console.log("Hello World"); -console.log("fib(10)=", fib(10)); diff --git a/examples/pi_bigdecimal.js b/examples/pi_bigdecimal.js deleted file mode 100644 index 6a416b7..0000000 --- a/examples/pi_bigdecimal.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * PI computation in Javascript using the QuickJS bigdecimal type - * (decimal floating point) - */ -"use strict"; - -/* compute PI with a precision of 'prec' digits */ -function calc_pi(prec) { - const CHUD_A = 13591409m; - const CHUD_B = 545140134m; - const CHUD_C = 640320m; - const CHUD_C3 = 10939058860032000m; /* C^3/24 */ - const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(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, b1; - if (a == (b - 1n)) { - b1 = BigDecimal(b); - G = (2m * b1 - 1m) * (6m * b1 - 1m) * (6m * b1 - 5m); - P = G * (CHUD_B * b1 + CHUD_A); - if (b & 1n) - P = -P; - G = G; - Q = b1 * b1 * b1 * 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 = 0m; - } - return [P, Q, G]; - } - - var n, P, Q, G; - /* number of serie terms */ - n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n; - [P, Q, G] = chud_bs(0n, n, false); - Q = BigDecimal.div(Q, (P + Q * CHUD_A), - { roundingMode: "half-even", - maximumSignificantDigits: prec }); - G = (CHUD_C / 12m) * BigDecimal.sqrt(CHUD_C, - { roundingMode: "half-even", - maximumSignificantDigits: prec }); - return Q * G; -} - -(function() { - var r, n_digits, n_bits; - if (typeof scriptArgs != "undefined") { - if (scriptArgs.length < 2) { - print("usage: pi n_digits"); - return; - } - n_digits = scriptArgs[1] | 0; - } else { - n_digits = 1000; - } - /* we add more digits to reduce the probability of bad rounding for - the last digits */ - r = calc_pi(n_digits + 20); - print(r.toFixed(n_digits, "down")); -})(); diff --git a/examples/pi_bigfloat.js b/examples/pi_bigfloat.js deleted file mode 100644 index 2bcda22..0000000 --- a/examples/pi_bigfloat.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * PI computation in Javascript using the QuickJS bigfloat type - * (binary floating point) - */ -"use strict"; - -/* compute PI with a precision of 'prec' bits */ -function calc_pi() { - 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 = BigFloat(G * (CHUD_B * b + CHUD_A)); - if (b & 1n) - P = -P; - G = BigFloat(G); - Q = BigFloat(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 = 0l; - } - return [P, Q, G]; - } - - var n, P, Q, G; - /* number of serie terms */ - n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; - [P, Q, G] = chud_bs(0n, n, false); - Q = Q / (P + Q * BigFloat(CHUD_A)); - G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C)); - return Q * G; -} - -(function() { - var r, n_digits, n_bits; - if (typeof scriptArgs != "undefined") { - if (scriptArgs.length < 2) { - print("usage: pi n_digits"); - return; - } - n_digits = scriptArgs[1]; - } else { - n_digits = 1000; - } - n_bits = Math.ceil(n_digits * Math.log2(10)); - /* we add more bits to reduce the probability of bad rounding for - the last digits */ - BigFloatEnv.setPrec( () => { - r = calc_pi(); - print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); - }, n_bits + 32); -})(); diff --git a/examples/pi_bigint.js b/examples/pi_bigint.js index cbbb2c4..e15abd1 100644 --- a/examples/pi_bigint.js +++ b/examples/pi_bigint.js @@ -54,7 +54,7 @@ function calc_pi(prec) { 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; diff --git a/examples/point.c b/examples/point.c index fbe2ce1..a82df15 100644 --- a/examples/point.c +++ b/examples/point.c @@ -1,6 +1,6 @@ /* * QuickJS: Example of C module with a class - * + * * Copyright (c) 2019 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -43,13 +43,13 @@ static void js_point_finalizer(JSRuntime *rt, JSValue val) } static JSValue js_point_ctor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) + JSValue new_target, + int argc, JSValue *argv) { JSPointData *s; JSValue obj = JS_UNDEFINED; JSValue proto; - + s = js_mallocz(ctx, sizeof(*s)); if (!s) return JS_EXCEPTION; @@ -74,7 +74,7 @@ static JSValue js_point_ctor(JSContext *ctx, return JS_EXCEPTION; } -static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic) +static JSValue js_point_get_xy(JSContext *ctx, JSValue 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, JSValueConst this_val, int magic) return JS_NewInt32(ctx, s->y); } -static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) +static JSValue js_point_set_xy(JSContext *ctx, JSValue 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, JSValueConst this_val, JSValue va return JS_UNDEFINED; } -static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_point_norm(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); if (!s) @@ -112,7 +112,7 @@ static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, static JSClassDef js_point_class = { "Point", .finalizer = js_point_finalizer, -}; +}; static const JSCFunctionListEntry js_point_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0), @@ -123,24 +123,33 @@ 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(&js_point_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class); + JS_NewClassID(rt, &js_point_class_id); + JS_NewClass(rt, 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)); - + point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0); /* set proto.constructor and ctor.prototype */ JS_SetConstructor(ctx, point_class, point_proto); JS_SetClassProto(ctx, js_point_class_id, point_proto); - + JS_SetModuleExport(ctx, m, "Point", point_class); return 0; } -JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +#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 *m; m = JS_NewCModule(ctx, module_name, js_point_init); diff --git a/examples/test_fib.js b/examples/test_fib.js index 70d26bd..f22c576 100644 --- a/examples/test_fib.js +++ b/examples/test_fib.js @@ -1,6 +1,8 @@ /* example of JS module importing a C module */ +import * as os from "qjs:os"; -import { fib } from "./fib.so"; +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/examples/test_point.js b/examples/test_point.js index 0659bc3..1e0fafa 100644 --- a/examples/test_point.js +++ b/examples/test_point.js @@ -1,5 +1,8 @@ /* example of JS module importing a C module */ -import { Point } from "./point.so"; +import * as os from "qjs:os"; + +const isWin = os.platform === 'win32'; +const { Point } = await import(`./point.${isWin ? 'dll' : 'so'}`); function assert(b, str) { diff --git a/fuzz.c b/fuzz.c new file mode 100644 index 0000000..cb5381d --- /dev/null +++ b/fuzz.c @@ -0,0 +1,23 @@ +// clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c +#include "quickjs.h" +#include "quickjs.c" +#include "cutils.c" +#include "libbf.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); + JSValueConst val = JS_ReadObject(ctx, buf, len, /*flags*/0); + JS_FreeValue(ctx, val); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; +} diff --git a/fuzz/README b/fuzz/README deleted file mode 100644 index 18c71cd..0000000 --- a/fuzz/README +++ /dev/null @@ -1,27 +0,0 @@ -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/fuzz/fuzz.dict b/fuzz/fuzz.dict deleted file mode 100644 index a5010e4..0000000 --- a/fuzz/fuzz.dict +++ /dev/null @@ -1,257 +0,0 @@ -"__loadScript" -"abs" -"acos" -"acosh" -"add" -"AggregateError" -"and" -"apply" -"Array" -"ArrayBuffer" -"asin" -"asinh" -"atan" -"atan2" -"atanh" -"Atomics" -"BigDecimal" -"BigFloat" -"BigFloatEnv" -"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/fuzz/fuzz_common.c b/fuzz/fuzz_common.c deleted file mode 100644 index 9f1662d..0000000 --- a/fuzz/fuzz_common.c +++ /dev/null @@ -1,62 +0,0 @@ -/* 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_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, 1); - 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/fuzz/fuzz_common.h b/fuzz/fuzz_common.h deleted file mode 100644 index 10cb497..0000000 --- a/fuzz/fuzz_common.h +++ /dev/null @@ -1,22 +0,0 @@ -/* 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/fuzz/fuzz_compile.c b/fuzz/fuzz_compile.c deleted file mode 100644 index 0ab1b03..0000000 --- a/fuzz/fuzz_compile.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 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/fuzz/fuzz_eval.c b/fuzz/fuzz_eval.c deleted file mode 100644 index aa26f1e..0000000 --- a/fuzz/fuzz_eval.c +++ /dev/null @@ -1,49 +0,0 @@ -/* 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/fuzz/fuzz_regexp.c b/fuzz/fuzz_regexp.c deleted file mode 100644 index 29d1951..0000000 --- a/fuzz/fuzz_regexp.c +++ /dev/null @@ -1,59 +0,0 @@ -/* 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" - - -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 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/fuzz/generate_dict.js b/fuzz/generate_dict.js deleted file mode 100644 index 1366fea..0000000 --- a/fuzz/generate_dict.js +++ /dev/null @@ -1,24 +0,0 @@ -// 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/gen/function_source.c b/gen/function_source.c new file mode 100644 index 0000000..489dfa2 --- /dev/null +++ b/gen/function_source.c @@ -0,0 +1,82 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include "quickjs-libc.h" + +const uint32_t qjsc_function_source_size = 320; + +const uint8_t qjsc_function_source[320] = { + 0x13, 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, 0xc0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x20, 0xfa, 0x01, 0xa2, + 0x01, 0x00, 0x05, 0x00, 0x03, 0x02, 0x01, 0x74, + 0x05, 0xc2, 0x03, 0x02, 0x00, 0x30, 0xc4, 0x03, + 0x04, 0x00, 0x70, 0xc2, 0x03, 0x04, 0x02, 0x70, + 0x10, 0x00, 0x01, 0x00, 0xe4, 0x01, 0x00, 0x01, + 0x00, 0xc6, 0x03, 0x00, 0x0d, 0xc4, 0x03, 0x01, + 0x01, 0x0c, 0x43, 0xfa, 0x01, 0xc4, 0x03, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0xbd, + 0x2a, 0x28, 0xc0, 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, 0xc3, 0x04, 0x08, 0xcd, + 0x08, 0xeb, 0x05, 0xc0, 0x00, 0xe3, 0x29, 0x04, + 0xe4, 0x00, 0x00, 0x00, 0xe2, 0x62, 0x00, 0x00, + 0xdf, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xca, 0x63, 0x00, 0x00, 0x66, 0x00, 0x00, + 0xb0, 0xeb, 0x0b, 0x39, 0x95, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x00, 0xf0, 0x30, 0x62, 0x02, 0x00, + 0x62, 0x01, 0x00, 0x39, 0x3b, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x04, 0xe2, 0x00, 0x00, 0x00, + 0x9e, 0x32, 0x01, 0x00, 0x03, 0x00, 0xcb, 0x63, + 0x01, 0x00, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0xcc, 0x63, 0x02, 0x00, 0x66, 0x00, + 0x00, 0xb0, 0xeb, 0x0b, 0x39, 0x95, 0x00, 0x00, + 0x00, 0x63, 0x02, 0x00, 0xf0, 0x30, 0x69, 0x02, + 0x00, 0x69, 0x01, 0x00, 0x06, 0x2f, 0xc0, 0x03, + 0x01, 0x01, 0x14, 0x00, 0x1c, 0x0a, 0x2a, 0x26, + 0x03, 0x39, 0x28, 0x00, 0x10, 0x08, 0x27, 0x11, + 0x12, 0x67, 0x0d, 0x26, 0x03, 0x39, 0x28, 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; + JSValue ret; + 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); + ret = js_std_loop(ctx); + if (JS_IsException(ret)) { + js_std_dump_error1(ctx, ret); + r = 1; + } + JS_FreeValue(ctx, ret); + JS_FreeContext(ctx); + js_std_free_handlers(rt); + JS_FreeRuntime(rt); + return r; +} diff --git a/gen/hello_module.c b/gen/hello_module.c new file mode 100644 index 0000000..b6f1470 --- /dev/null +++ b/gen/hello_module.c @@ -0,0 +1,109 @@ +/* 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] = { + 0x13, 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, 0xc0, 0x03, 0x00, 0x01, 0x00, + 0x00, 0xc2, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x20, + 0xfa, 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x09, 0x00, 0xc2, 0x03, 0x00, 0x01, + 0x0c, 0x43, 0xfa, 0x01, 0xc2, 0x03, 0x01, 0x00, + 0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xc4, 0x03, + 0x00, 0x01, 0x00, 0xc2, 0x03, 0x00, 0x00, 0xd2, + 0xb5, 0xa8, 0xeb, 0x03, 0xb5, 0x28, 0xd2, 0xb6, + 0xad, 0xeb, 0x03, 0xb6, 0x28, 0xde, 0xd2, 0xb6, + 0x9f, 0xf0, 0xde, 0xd2, 0xb7, 0x9f, 0xf0, 0x9e, + 0x28, 0xc0, 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, 0xeb, 0x05, 0xc0, 0x00, + 0xe2, 0x29, 0x06, 0x2f, 0xc0, 0x03, 0x01, 0x01, + 0x00, 0x00, +}; + +const uint32_t qjsc_hello_module_size = 187; + +const uint8_t qjsc_hello_module[187] = { + 0x13, 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, + 0xc0, 0x03, 0x01, 0xc2, 0x03, 0x00, 0x00, 0x01, + 0x00, 0xc4, 0x03, 0x00, 0x00, 0x0c, 0x20, 0xfa, + 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, + 0x00, 0x32, 0x00, 0xc4, 0x03, 0x00, 0x0c, 0x08, + 0xeb, 0x02, 0x29, 0x39, 0xe3, 0x00, 0x00, 0x00, + 0x43, 0xe4, 0x00, 0x00, 0x00, 0x04, 0xe5, 0x00, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0xe3, + 0x00, 0x00, 0x00, 0x43, 0xe4, 0x00, 0x00, 0x00, + 0x04, 0xe6, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, + 0xbd, 0x0a, 0xf0, 0x24, 0x02, 0x00, 0x0e, 0x06, + 0x2f, 0xc0, 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; + JSValue ret; + 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); + ret = js_std_loop(ctx); + if (JS_IsException(ret)) { + js_std_dump_error1(ctx, ret); + r = 1; + } + JS_FreeValue(ctx, ret); + JS_FreeContext(ctx); + js_std_free_handlers(rt); + JS_FreeRuntime(rt); + return r; +} diff --git a/gen/standalone.c b/gen/standalone.c new file mode 100644 index 0000000..998907a --- /dev/null +++ b/gen/standalone.c @@ -0,0 +1,318 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include + +const uint32_t qjsc_standalone_size = 2466; + +const uint8_t qjsc_standalone[2466] = { + 0x13, 0x4d, 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, 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, + 0xc0, 0x03, 0x03, 0xc2, 0x03, 0xc4, 0x03, 0xc6, + 0x03, 0x02, 0x00, 0x0b, 0xc8, 0x03, 0x00, 0x0c, + 0xca, 0x03, 0x00, 0x03, 0x00, 0xfc, 0x01, 0x00, + 0x01, 0xfc, 0x01, 0x01, 0x02, 0xfc, 0x01, 0x02, + 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa2, 0x01, 0x00, + 0x00, 0x00, 0x02, 0x0d, 0x04, 0x58, 0x00, 0xcc, + 0x03, 0x00, 0x0d, 0xce, 0x03, 0x01, 0x0d, 0xd0, + 0x03, 0x02, 0x0d, 0xd2, 0x03, 0x00, 0x0d, 0xd4, + 0x03, 0x01, 0x0d, 0xd6, 0x03, 0x02, 0x0d, 0xd8, + 0x03, 0x03, 0x0d, 0xda, 0x03, 0x04, 0x0d, 0xdc, + 0x03, 0x05, 0x0d, 0xde, 0x03, 0x06, 0x01, 0xe0, + 0x03, 0x07, 0x01, 0xc8, 0x03, 0x08, 0x01, 0xca, + 0x03, 0x09, 0x01, 0x0c, 0x43, 0x02, 0x01, 0xde, + 0x03, 0x01, 0x00, 0x01, 0x05, 0x00, 0x01, 0x1e, + 0x01, 0xe2, 0x03, 0x00, 0x01, 0x00, 0x0c, 0x42, + 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, + 0x00, 0x0a, 0x01, 0xe4, 0x03, 0x00, 0x01, 0x00, + 0xd2, 0x43, 0xf3, 0x00, 0x00, 0x00, 0xb5, 0x25, + 0x01, 0x00, 0x39, 0xa6, 0x00, 0x00, 0x00, 0x11, + 0xd2, 0x43, 0x5e, 0x00, 0x00, 0x00, 0xc1, 0x24, + 0x01, 0x00, 0x43, 0xf4, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x28, + 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x03, 0x01, 0x00, + 0x01, 0x03, 0x00, 0x01, 0x21, 0x01, 0xea, 0x03, + 0x00, 0x01, 0x00, 0x0c, 0x42, 0x02, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x0e, 0x01, + 0xe4, 0x03, 0x00, 0x01, 0x00, 0x39, 0x97, 0x00, + 0x00, 0x00, 0x43, 0xf6, 0x00, 0x00, 0x00, 0xd2, + 0x25, 0x01, 0x00, 0x39, 0x94, 0x00, 0x00, 0x00, + 0x43, 0x7b, 0x00, 0x00, 0x00, 0xd2, 0x24, 0x01, + 0x00, 0x43, 0xf4, 0x00, 0x00, 0x00, 0xc0, 0x00, + 0x24, 0x01, 0x00, 0x43, 0x5c, 0x00, 0x00, 0x00, + 0xc1, 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, + 0xc8, 0x03, 0x03, 0x0a, 0x03, 0x07, 0x08, 0x00, + 0x86, 0x04, 0x0d, 0xee, 0x03, 0x00, 0x01, 0x00, + 0xf0, 0x03, 0x00, 0x01, 0x00, 0xf2, 0x03, 0x00, + 0x01, 0x00, 0xf4, 0x03, 0x01, 0x00, 0x30, 0xf6, + 0x03, 0x01, 0x01, 0x30, 0xf8, 0x03, 0x01, 0x02, + 0x30, 0xfa, 0x03, 0x01, 0x03, 0x30, 0xfc, 0x03, + 0x01, 0x04, 0x30, 0xfe, 0x03, 0x01, 0x05, 0x30, + 0x80, 0x04, 0x01, 0x06, 0x30, 0x82, 0x04, 0x01, + 0x07, 0x30, 0x84, 0x04, 0x01, 0x08, 0x30, 0x86, + 0x04, 0x01, 0x09, 0x30, 0xcc, 0x03, 0x00, 0x0c, + 0xd0, 0x03, 0x02, 0x0c, 0xd6, 0x03, 0x05, 0x0c, + 0xd8, 0x03, 0x06, 0x0c, 0xda, 0x03, 0x07, 0x0c, + 0xdc, 0x03, 0x08, 0x0c, 0xde, 0x03, 0x09, 0x00, + 0xce, 0x03, 0x01, 0x0c, 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, 0x04, 0x01, + 0x00, 0x00, 0xd2, 0x24, 0x01, 0x00, 0xca, 0x63, + 0x00, 0x00, 0x97, 0xeb, 0x19, 0x39, 0x95, 0x00, + 0x00, 0x00, 0x11, 0x04, 0x05, 0x01, 0x00, 0x00, + 0x43, 0x5d, 0x00, 0x00, 0x00, 0xd2, 0x24, 0x01, + 0x00, 0x21, 0x01, 0x00, 0x30, 0x66, 0x00, 0x00, + 0x43, 0x06, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00, + 0x0b, 0x0a, 0x4d, 0x07, 0x01, 0x00, 0x00, 0x0a, + 0x4d, 0x08, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, + 0xcb, 0x39, 0xa6, 0x00, 0x00, 0x00, 0x11, 0x66, + 0x01, 0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63, + 0x01, 0x00, 0x66, 0x02, 0x00, 0x66, 0x03, 0x00, + 0xa5, 0x66, 0x04, 0x00, 0xa5, 0x24, 0x02, 0x00, + 0x21, 0x01, 0x00, 0xcc, 0xd4, 0x11, 0xb1, 0xeb, + 0x0c, 0x0e, 0x39, 0x8c, 0x00, 0x00, 0x00, 0x42, + 0x0a, 0x01, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00, + 0x43, 0x04, 0x01, 0x00, 0x00, 0x63, 0x03, 0x00, + 0x0b, 0x0a, 0x4d, 0x0b, 0x01, 0x00, 0x00, 0x24, + 0x02, 0x00, 0xc3, 0x04, 0x63, 0x04, 0x00, 0x97, + 0xeb, 0x1b, 0x39, 0x95, 0x00, 0x00, 0x00, 0x11, + 0x04, 0x0c, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, + 0x00, 0x00, 0x63, 0x03, 0x00, 0x24, 0x01, 0x00, + 0x21, 0x01, 0x00, 0x30, 0x63, 0x04, 0x00, 0xea, + 0xc3, 0x05, 0x63, 0x04, 0x00, 0x42, 0x0d, 0x01, + 0x00, 0x00, 0x43, 0x0e, 0x01, 0x00, 0x00, 0x63, + 0x05, 0x00, 0x63, 0x02, 0x00, 0xea, 0x9e, 0x66, + 0x05, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00, 0x9e, + 0x24, 0x01, 0x00, 0xc3, 0x06, 0x39, 0xa6, 0x00, + 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x21, 0x01, + 0x00, 0xc3, 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, 0x06, 0x00, + 0x66, 0x05, 0x00, 0x42, 0x10, 0x01, 0x00, 0x00, + 0xf0, 0x63, 0x05, 0x00, 0x63, 0x02, 0x00, 0xea, + 0x9e, 0x24, 0x02, 0x00, 0x0e, 0x39, 0xb0, 0x00, + 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x63, 0x05, + 0x00, 0x63, 0x02, 0x00, 0xea, 0x9e, 0x66, 0x05, + 0x00, 0x42, 0x11, 0x01, 0x00, 0x00, 0x9e, 0x66, + 0x05, 0x00, 0x42, 0x12, 0x01, 0x00, 0x00, 0x21, + 0x03, 0x00, 0xc3, 0x08, 0x63, 0x08, 0x00, 0x43, + 0x13, 0x01, 0x00, 0x00, 0xb5, 0x63, 0x05, 0x00, + 0x0a, 0x24, 0x03, 0x00, 0x0e, 0x66, 0x07, 0x00, + 0x43, 0x14, 0x01, 0x00, 0x00, 0xd3, 0x66, 0x07, + 0x00, 0x42, 0x15, 0x01, 0x00, 0x00, 0x66, 0x07, + 0x00, 0x42, 0x16, 0x01, 0x00, 0x00, 0xa5, 0x66, + 0x07, 0x00, 0x42, 0x17, 0x01, 0x00, 0x00, 0xa5, + 0xbe, 0xed, 0x01, 0x24, 0x03, 0x00, 0xc3, 0x09, + 0x63, 0x09, 0x00, 0xb5, 0xa7, 0xeb, 0x19, 0x39, + 0x95, 0x00, 0x00, 0x00, 0x11, 0x04, 0x18, 0x01, + 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xd3, + 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x66, + 0x07, 0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63, + 0x09, 0x00, 0x63, 0x06, 0x00, 0xb5, 0x63, 0x06, + 0x00, 0x42, 0x19, 0x01, 0x00, 0x00, 0x24, 0x04, + 0x00, 0xb5, 0xa7, 0xeb, 0x1f, 0x66, 0x07, 0x00, + 0x43, 0x1a, 0x01, 0x00, 0x00, 0x63, 0x09, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0x39, 0x95, 0x00, 0x00, + 0x00, 0x11, 0x04, 0x1b, 0x01, 0x00, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x66, 0x07, 0x00, 0x43, 0x1a, + 0x01, 0x00, 0x00, 0x63, 0x09, 0x00, 0x24, 0x01, + 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xca, 0x03, + 0x00, 0x09, 0x00, 0x07, 0x06, 0x00, 0xa4, 0x04, + 0x09, 0xb8, 0x04, 0x01, 0x00, 0x30, 0xfc, 0x03, + 0x01, 0x01, 0x30, 0xba, 0x04, 0x01, 0x02, 0x20, + 0xbc, 0x04, 0x01, 0x03, 0x30, 0xbe, 0x04, 0x01, + 0x04, 0x30, 0x84, 0x04, 0x01, 0x05, 0x30, 0xc0, + 0x04, 0x01, 0x06, 0x30, 0xf8, 0x03, 0x01, 0x07, + 0x30, 0xf6, 0x03, 0x01, 0x08, 0x30, 0xcc, 0x03, + 0x00, 0x0c, 0xdc, 0x03, 0x08, 0x0c, 0xe0, 0x03, + 0x0a, 0x00, 0xd0, 0x03, 0x02, 0x0c, 0xd2, 0x03, + 0x03, 0x0c, 0xd4, 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, 0x39, 0x8c, 0x00, 0x00, 0x00, 0x42, 0x0a, + 0x01, 0x00, 0x00, 0xca, 0x66, 0x00, 0x00, 0x43, + 0x14, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00, 0x04, + 0x21, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xcb, + 0x63, 0x01, 0x00, 0x97, 0xeb, 0x1b, 0x39, 0x95, + 0x00, 0x00, 0x00, 0x11, 0x04, 0x0c, 0x01, 0x00, + 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0x63, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x63, 0x01, 0x00, 0x43, 0x22, 0x01, 0x00, 0x00, + 0x66, 0x01, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00, + 0x8d, 0x66, 0x00, 0x00, 0x42, 0x23, 0x01, 0x00, + 0x00, 0x24, 0x02, 0x00, 0xcc, 0x63, 0x02, 0x00, + 0xb5, 0xa7, 0xeb, 0x1c, 0x39, 0x95, 0x00, 0x00, + 0x00, 0x11, 0x04, 0x24, 0x01, 0x00, 0x00, 0x43, + 0x5d, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x8d, + 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x39, + 0xa6, 0x00, 0x00, 0x00, 0x11, 0x66, 0x01, 0x00, + 0x42, 0x0f, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, + 0xcd, 0x63, 0x01, 0x00, 0x43, 0x25, 0x01, 0x00, + 0x00, 0x63, 0x03, 0x00, 0x42, 0x0d, 0x01, 0x00, + 0x00, 0xb5, 0x66, 0x01, 0x00, 0x42, 0x0f, 0x01, + 0x00, 0x00, 0x24, 0x03, 0x00, 0x0e, 0x39, 0xa6, + 0x00, 0x00, 0x00, 0x11, 0x63, 0x03, 0x00, 0x42, + 0x0d, 0x01, 0x00, 0x00, 0xb5, 0x66, 0x01, 0x00, + 0x42, 0x11, 0x01, 0x00, 0x00, 0x21, 0x03, 0x00, + 0xc3, 0x04, 0xe0, 0x63, 0x04, 0x00, 0xf0, 0x66, + 0x01, 0x00, 0x42, 0x10, 0x01, 0x00, 0x00, 0xb0, + 0xeb, 0x1c, 0x63, 0x01, 0x00, 0x43, 0x1a, 0x01, + 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0x39, 0x95, + 0x00, 0x00, 0x00, 0x11, 0x04, 0x26, 0x01, 0x00, + 0x00, 0x21, 0x01, 0x00, 0x30, 0x39, 0xb0, 0x00, + 0x00, 0x00, 0x11, 0x63, 0x03, 0x00, 0x42, 0x0d, + 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x42, 0x11, + 0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x42, 0x12, + 0x01, 0x00, 0x00, 0x21, 0x03, 0x00, 0xc3, 0x05, + 0x63, 0x05, 0x00, 0x43, 0x27, 0x01, 0x00, 0x00, + 0xb5, 0x0a, 0x24, 0x02, 0x00, 0xc3, 0x06, 0x39, + 0xa6, 0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, + 0x66, 0x01, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00, + 0x9f, 0x21, 0x01, 0x00, 0xc3, 0x07, 0x63, 0x01, + 0x00, 0x43, 0x22, 0x01, 0x00, 0x00, 0x63, 0x06, + 0x00, 0x66, 0x00, 0x00, 0x42, 0x28, 0x01, 0x00, + 0x00, 0x24, 0x02, 0x00, 0x11, 0x64, 0x02, 0x00, + 0x0e, 0x63, 0x02, 0x00, 0xb5, 0xa7, 0xeb, 0x28, + 0x63, 0x01, 0x00, 0x43, 0x1a, 0x01, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x0e, 0x39, 0x95, 0x00, 0x00, + 0x00, 0x11, 0x04, 0x24, 0x01, 0x00, 0x00, 0x43, + 0x5d, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x8d, + 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x63, + 0x01, 0x00, 0x43, 0x25, 0x01, 0x00, 0x00, 0x63, + 0x07, 0x00, 0x42, 0x0d, 0x01, 0x00, 0x00, 0xb5, + 0x63, 0x07, 0x00, 0xea, 0x24, 0x03, 0x00, 0x0e, + 0x63, 0x01, 0x00, 0x43, 0x29, 0x01, 0x00, 0x00, + 0x24, 0x00, 0x00, 0xeb, 0x1c, 0x63, 0x01, 0x00, + 0x43, 0x1a, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x0e, 0x39, 0x95, 0x00, 0x00, 0x00, 0x11, 0x04, + 0x2a, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x63, 0x01, 0x00, 0x43, 0x1a, 0x01, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x0e, 0x66, 0x03, 0x00, 0x43, + 0x25, 0x01, 0x00, 0x00, 0x63, 0x07, 0x00, 0x42, + 0x0d, 0x01, 0x00, 0x00, 0xb5, 0x63, 0x07, 0x00, + 0xea, 0x66, 0x04, 0x00, 0x66, 0x05, 0x00, 0xa5, + 0x24, 0x04, 0x00, 0xc3, 0x08, 0x66, 0x00, 0x00, + 0x43, 0x06, 0x01, 0x00, 0x00, 0x63, 0x08, 0x00, + 0x0b, 0x0a, 0x4d, 0x2b, 0x01, 0x00, 0x00, 0x25, + 0x02, 0x00, 0x08, 0xeb, 0x16, 0xc0, 0x00, 0x60, + 0x09, 0x00, 0xc0, 0x01, 0x60, 0x0a, 0x00, 0xc0, + 0x02, 0x60, 0x0b, 0x00, 0xc0, 0x03, 0x60, 0x0c, + 0x00, 0x29, 0xb6, 0xb5, 0xa0, 0xe5, 0xb6, 0xb8, + 0xa0, 0x60, 0x04, 0x00, 0xb6, 0xb5, 0xa0, 0x60, + 0x05, 0x00, 0xb6, 0xb8, 0xa0, 0x60, 0x06, 0x00, + 0xb6, 0xb9, 0xa0, 0x60, 0x07, 0x00, 0x0b, 0x04, + 0x2c, 0x01, 0x00, 0x00, 0x4d, 0x10, 0x01, 0x00, + 0x00, 0xbd, 0x08, 0x4d, 0x11, 0x01, 0x00, 0x00, + 0xb9, 0x4d, 0x12, 0x01, 0x00, 0x00, 0xbd, 0x0c, + 0x4d, 0x0f, 0x01, 0x00, 0x00, 0x60, 0x08, 0x00, + 0x06, 0x2f, +}; + diff --git a/gen/test_fib.c b/gen/test_fib.c new file mode 100644 index 0000000..2826500 --- /dev/null +++ b/gen/test_fib.c @@ -0,0 +1,83 @@ +/* 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] = { + 0x13, 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, + 0xc0, 0x03, 0x01, 0xc2, 0x03, 0x00, 0x00, 0x01, + 0x00, 0xfc, 0x01, 0x00, 0x01, 0x0c, 0x20, 0xfa, + 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, + 0x00, 0x73, 0x00, 0xc4, 0x03, 0x00, 0x0d, 0xc6, + 0x03, 0x00, 0x0d, 0xc8, 0x03, 0x01, 0x0d, 0x08, + 0xeb, 0x02, 0x29, 0x66, 0x00, 0x00, 0x42, 0xe5, + 0x00, 0x00, 0x00, 0x04, 0xe6, 0x00, 0x00, 0x00, + 0xaf, 0xe3, 0x06, 0x11, 0xf3, 0xec, 0x0b, 0x71, + 0x43, 0xe4, 0x00, 0x00, 0x00, 0xe4, 0x0e, 0xed, + 0x24, 0x0e, 0x04, 0xe7, 0x00, 0x00, 0x00, 0x43, + 0x5d, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0xeb, + 0x08, 0x04, 0xe8, 0x00, 0x00, 0x00, 0xed, 0x06, + 0x04, 0xe9, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x36, 0x8c, 0xed, 0xd4, 0x39, 0xea, 0x00, 0x00, + 0x00, 0x43, 0xeb, 0x00, 0x00, 0x00, 0x04, 0xec, + 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, + 0xea, 0x00, 0x00, 0x00, 0x43, 0xeb, 0x00, 0x00, + 0x00, 0x04, 0xed, 0x00, 0x00, 0x00, 0x66, 0x02, + 0x00, 0xbd, 0x0a, 0xf0, 0x24, 0x02, 0x00, 0x0e, + 0x06, 0x2f, 0xc0, 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; + JSValue ret; + 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); + ret = js_std_loop(ctx); + if (JS_IsException(ret)) { + js_std_dump_error1(ctx, ret); + r = 1; + } + JS_FreeValue(ctx, ret); + JS_FreeContext(ctx); + js_std_free_handlers(rt); + JS_FreeRuntime(rt); + return r; +} diff --git a/getopt_compat.h b/getopt_compat.h new file mode 100644 index 0000000..f98ba27 --- /dev/null +++ b/getopt_compat.h @@ -0,0 +1,653 @@ +#ifndef __GETOPT_H__ +/** + * DISCLAIMER + * This file is part of the mingw-w64 runtime package. + * + * The mingw-w64 runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + /* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma warning(disable:4996) + +#define __GETOPT_H__ + +/* All the headers include this file. */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +#undef optreset /* see getopt.h */ +#define optreset __mingw_optreset +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +//extern int optind; /* index of first non-option in argv */ +//extern int optopt; /* single option character, as parsed */ +//extern int opterr; /* flag to enable built-in diagnostics... */ +// /* (user may set to zero, to suppress) */ +// +//extern char *optarg; /* pointer to argument of current option */ + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#ifndef __CYGWIN__ +#define __progname __argv[0] +#else +extern char __declspec(dllimport) *__progname; +#endif + +#ifdef __CYGWIN__ +static char EMSG[] = ""; +#else +#define EMSG "" +#endif + +struct option /* specification for a long form option... */ +{ + const char *name; /* option name, without leading hyphens */ + int has_arg; /* does it take an argument? */ + int *flag; /* where to save its status, or NULL */ + int val; /* its associated status value */ +}; + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +static void +_vwarnx(const char *fmt,va_list ap) +{ + (void)fprintf(stderr,"%s: ",__progname); + if (fmt != NULL) + (void)vfprintf(stderr,fmt,ap); + (void)fprintf(stderr,"\n"); +} + +static void +warnx(const char *fmt,...) +{ + va_list ap; + va_start(ap,fmt); + _vwarnx(fmt,ap); + va_end(ap); +} + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +//extern int getopt(int nargc, char * const *nargv, const char *options); + +#ifdef _BSD_SOURCE +/* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset +extern int optreset; +#endif +#ifdef __cplusplus +} +#endif +/* + * POSIX requires the `getopt' API to be specified in `unistd.h'; + * thus, `unistd.h' includes this header. However, we do not want + * to expose the `getopt_long' or `getopt_long_only' APIs, when + * included in this manner. Thus, close the standard __GETOPT_H__ + * declarations block, and open an additional __GETOPT_LONG_H__ + * specific block, only when *not* __UNISTD_H_SOURCED__, in which + * to declare the extended API. + */ +#endif /* !defined(__GETOPT_H__) */ + +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) +#define __GETOPT_LONG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +enum /* permitted values for its `has_arg' field... */ +{ + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ +}; + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, ambiguous, match; + +#define IDENTICAL_INTERPRETATION(_x, _y) \ + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ + long_options[(_x)].flag == long_options[(_y)].flag && \ + long_options[(_x)].val == long_options[(_y)].val) + + current_argv = place; + match = -1; + ambiguous = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + ambiguous = 0; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else if (!IDENTICAL_INTERPRETATION(i, match)) + ambiguous = 1; + } + if (ambiguous) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +#undef IDENTICAL_INTERPRETATION +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + * + * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or + * optreset != 0 for GNU compatibility. + */ + if (posixly_correct == -1 || optreset != 0) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = (char*)strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} + +//extern int getopt_long(int nargc, char * const *nargv, const char *options, +// const struct option *long_options, int *idx); +//extern int getopt_long_only(int nargc, char * const *nargv, const char *options, +// const struct option *long_options, int *idx); +/* + * Previous MinGW implementation had... + */ +#ifndef HAVE_DECL_GETOPT +/* + * ...for the long form API only; keep this for compatibility. + */ +# define HAVE_DECL_GETOPT 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ \ No newline at end of file diff --git a/libbf.c b/libbf.c index 234b956..6293f4e 100644 --- a/libbf.c +++ b/libbf.c @@ -1,6 +1,6 @@ /* * Tiny arbitrary precision floating point library - * + * * Copyright (c) 2017-2021 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -37,12 +37,10 @@ /* enable it to check the multiplication result */ //#define USE_MUL_CHECK -#ifdef CONFIG_BIGNUM /* enable it to use FFT/NTT multiplication */ #define USE_FFT_MUL /* enable decimal floating point support */ #define USE_BF_DEC -#endif //#define inline __attribute__((always_inline)) @@ -57,8 +55,8 @@ #define UDIV1NORM_THRESHOLD 3 #if LIMB_BITS == 64 -#define FMT_LIMB1 "%" PRIx64 -#define FMT_LIMB "%016" PRIx64 +#define FMT_LIMB1 "%" PRIx64 +#define FMT_LIMB "%016" PRIx64 #define PRId_LIMB PRId64 #define PRIu_LIMB PRIu64 @@ -211,7 +209,7 @@ void bf_init(bf_context_t *s, bf_t *r) int bf_resize(bf_t *r, limb_t len) { limb_t *tab; - + if (len != r->len) { tab = bf_realloc(r->ctx, r->tab, len * sizeof(limb_t)); if (!tab && len != 0) @@ -229,7 +227,7 @@ int bf_set_ui(bf_t *r, uint64_t a) if (a == 0) { r->expn = BF_EXP_ZERO; bf_resize(r, 0); /* cannot fail */ - } + } #if LIMB_BITS == 32 else if (a <= 0xffffffff) #else @@ -309,7 +307,8 @@ int bf_set(bf_t *r, const bf_t *a) } r->sign = a->sign; r->expn = a->expn; - memcpy(r->tab, a->tab, a->len * sizeof(limb_t)); + if (a->len > 0) + memcpy(r->tab, a->tab, a->len * sizeof(limb_t)); return 0; } @@ -391,7 +390,7 @@ static inline limb_t scan_bit_nz(const bf_t *r, slimb_t bit_pos) { slimb_t pos; limb_t v; - + pos = bit_pos >> LIMB_LOG2_BITS; if (pos < 0) return 0; @@ -414,7 +413,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, { int add_one, inexact; limb_t bit1, bit0; - + if (rnd_mode == BF_RNDF) { bit0 = 1; /* faithful rounding does not honor the INEXACT flag */ } else { @@ -425,7 +424,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, /* get the bit at 'prec' */ bit1 = get_bit(r->tab, l, l * LIMB_BITS - 1 - prec); inexact = (bit1 | bit0) != 0; - + add_one = 0; switch(rnd_mode) { case BF_RNDZ: @@ -456,7 +455,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, default: abort(); } - + if (inexact) *pret |= BF_ST_INEXACT; return add_one; @@ -466,7 +465,7 @@ static int bf_set_overflow(bf_t *r, int sign, limb_t prec, bf_flags_t flags) { slimb_t i, l, e_max; int rnd_mode; - + rnd_mode = flags & BF_RND_MASK; if (prec == BF_PREC_INF || rnd_mode == BF_RNDN || @@ -509,7 +508,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1); e_min = -e_range + 3; e_max = e_range; - + if (flags & BF_FLAG_RADPNT_PREC) { /* 'prec' is the precision after the radix point */ if (prec1 != BF_PREC_INF) @@ -528,7 +527,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, /* round to prec bits */ rnd_mode = flags & BF_RND_MASK; add_one = bf_get_rnd_add(&ret, r, l, prec, rnd_mode); - + if (prec <= 0) { if (add_one) { bf_resize(r, 1); /* cannot fail */ @@ -541,12 +540,12 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, } } else if (add_one) { limb_t carry; - + /* add one starting at digit 'prec - 1' */ bit_pos = l * LIMB_BITS - 1 - (prec - 1); pos = bit_pos >> LIMB_LOG2_BITS; carry = (limb_t)1 << (bit_pos & (LIMB_BITS - 1)); - + for(i = pos; i < l; i++) { v = r->tab[i] + carry; carry = (v < carry); @@ -565,7 +564,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, r->expn++; } } - + /* check underflow */ if (unlikely(r->expn < e_min)) { if (flags & BF_FLAG_SUBNORMAL) { @@ -579,11 +578,11 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, return ret; } } - + /* check overflow */ if (unlikely(r->expn > e_max)) return bf_set_overflow(r, r->sign, prec1, flags); - + /* keep the bits starting at 'prec - 1' */ bit_pos = l * LIMB_BITS - 1 - (prec - 1); i = bit_pos >> LIMB_LOG2_BITS; @@ -611,7 +610,7 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags) limb_t l, v, a; int shift, ret; slimb_t i; - + // bf_print_str("bf_renorm", r); l = r->len; while (l > 0 && r->tab[l - 1] == 0) @@ -650,7 +649,7 @@ int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k) BOOL is_rndn; slimb_t bit_pos, n; limb_t bit; - + if (a->expn == BF_EXP_INF || a->expn == BF_EXP_NAN) return FALSE; if (rnd_mode == BF_RNDF) { @@ -664,7 +663,7 @@ int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k) bit_pos = a->len * LIMB_BITS - 1 - prec; n = k - prec; /* bit pattern for RNDN or RNDNA: 0111.. or 1000... - for other rounding modes: 000... or 111... + for other rounding modes: 000... or 111... */ bit = get_bit(a->tab, a->len, bit_pos); bit_pos--; @@ -756,7 +755,7 @@ int bf_cmpu(const bf_t *a, const bf_t *b) { slimb_t i; limb_t len, v1, v2; - + if (a->expn != b->expn) { if (a->expn < b->expn) return -1; @@ -781,7 +780,7 @@ int bf_cmpu(const bf_t *a, const bf_t *b) int bf_cmp_full(const bf_t *a, const bf_t *b) { int res; - + if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { if (a->expn == b->expn) res = 0; @@ -805,7 +804,7 @@ int bf_cmp_full(const bf_t *a, const bf_t *b) int bf_cmp(const bf_t *a, const bf_t *b) { int res; - + if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { res = 2; } else if (a->sign != b->sign) { @@ -824,7 +823,7 @@ int bf_cmp(const bf_t *a, const bf_t *b) /* Compute the number of bits 'n' matching the pattern: a= X1000..0 b= X0111..1 - + When computing a-b, the result will have at least n leading zero bits. @@ -939,7 +938,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, } else { cancelled_bits = 0; } - + /* add two extra bits for rounding */ precl = (cancelled_bits + prec + 2 + LIMB_BITS - 1) / LIMB_BITS; tot_len = bf_max(a->len, b->len + (d + LIMB_BITS - 1) / LIMB_BITS); @@ -957,7 +956,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, while (i < 0) { slimb_t ap, bp; BOOL inflag; - + ap = a_offset + i; bp = b_bit_offset + i * LIMB_BITS; inflag = FALSE; @@ -981,7 +980,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, if (ap < 0) i = bf_min(i, -a_offset); /* b_bit_offset + i * LIMB_BITS + LIMB_BITS >= 1 - equivalent to + equivalent to i >= ceil(-b_bit_offset + 1 - LIMB_BITS) / LIMB_BITS) */ if (bp + LIMB_BITS <= 0) @@ -1038,12 +1037,12 @@ static int __bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, return bf_add_internal(r, a, b, prec, flags, 1); } -limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, +limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, limb_t n, limb_t carry) { slimb_t i; limb_t k, a, v, k1; - + k = carry; for(i=0;i> 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 limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, int shift, limb_t high) { mp_size_t i; @@ -1144,7 +1143,7 @@ static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, } /* tabr[] = taba[] * b + l. Return the high carry */ -static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n, +static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n, limb_t b, limb_t l) { limb_t i; @@ -1164,7 +1163,7 @@ static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n, { limb_t i, l; dlimb_t t; - + l = 0; for(i = 0; i < n; i++) { t = (dlimb_t)taba[i] * (dlimb_t)b + l + tabr[i]; @@ -1175,12 +1174,12 @@ static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n, } /* size of the result : op1_size + op2_size. */ -static void mp_mul_basecase(limb_t *result, - const limb_t *op1, limb_t op1_size, - const limb_t *op2, limb_t op2_size) +static void mp_mul_basecase(limb_t *result, + const limb_t *op1, limb_t op1_size, + const limb_t *op2, limb_t op2_size) { limb_t i, r; - + result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0); for(i=1;i= FFT_MUL_THRESHOLD)) { @@ -1217,7 +1216,7 @@ static limb_t mp_sub_mul1(limb_t *tabr, const limb_t *taba, limb_t n, { limb_t i, l; dlimb_t t; - + l = 0; for(i = 0; i < n; i++) { t = tabr[i] - (dlimb_t)taba[i] * (dlimb_t)b - l; @@ -1281,15 +1280,15 @@ static limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n, return r; } -static int mp_divnorm_large(bf_context_t *s, - limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm_large(bf_context_t *s, + limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb); /* base case division: divides taba[0..na-1] by tabb[0..nb-1]. tabb[nb - 1] must be >= 1 << (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 int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb) { limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r; @@ -1304,7 +1303,7 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, if (bf_min(n, nb) >= DIVNORM_LARGE_THRESHOLD) { return mp_divnorm_large(s, tabq, taba, na, tabb, nb); } - + if (n >= UDIV1NORM_THRESHOLD) b1_inv = udiv1norm_init(b1); else @@ -1323,7 +1322,7 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, if (q) { mp_sub(taba + n, taba + n, tabb, nb, 0); } - + for(i = n - 1; i >= 0; i--) { if (unlikely(taba[i + nb] >= b1)) { q = -1; @@ -1362,14 +1361,14 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, /* compute r=B^(2*n)/a such as a*r < B^(2*n) < a*r + 2 with n >= 1. 'a' has n limbs with a[n-1] >= B/2 and 'r' has n+1 limbs with r[n] = 1. - + See Modern Computer Arithmetic by Richard P. Brent and Paul Zimmermann, algorithm 3.5 */ int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n) { mp_size_t l, h, k, i; limb_t *tabxh, *tabt, c, *tabu; - + if (n <= 2) { /* return ceil(B^(2*n)/a) - 1 */ /* XXX: could avoid allocation */ @@ -1447,8 +1446,8 @@ static int mp_cmp(const limb_t *taba, const limb_t *tabb, mp_size_t n) //#define DEBUG_DIVNORM_LARGE2 /* subquadratic divnorm */ -static int mp_divnorm_large(bf_context_t *s, - limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm_large(bf_context_t *s, + limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb) { limb_t *tabb_inv, nq, *tabt, i, n; @@ -1461,7 +1460,7 @@ static int mp_divnorm_large(bf_context_t *s, assert(nq >= 1); n = nq; if (nq < nb) - n++; + n++; tabb_inv = bf_malloc(s, sizeof(limb_t) * (n + 1)); tabt = bf_malloc(s, sizeof(limb_t) * 2 * (n + 1)); if (!tabb_inv || !tabt) @@ -1490,7 +1489,7 @@ static int mp_divnorm_large(bf_context_t *s, /* Q=A*B^-1 */ if (mp_mul(s, tabt, tabb_inv, n + 1, taba + na - (n + 1), n + 1)) goto fail; - + for(i = 0; i < nq + 1; i++) tabq[i] = tabt[i + 2 * (n + 1) - (nq + 1)]; #ifdef DEBUG_DIVNORM_LARGE @@ -1500,7 +1499,7 @@ static int mp_divnorm_large(bf_context_t *s, bf_free(s, tabt); bf_free(s, tabb_inv); tabb_inv = NULL; - + /* R=A-B*Q */ tabt = bf_malloc(s, sizeof(limb_t) * (na + 1)); if (!tabt) @@ -1571,10 +1570,10 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_t tmp, *r1 = NULL; limb_t a_len, b_len, precl; limb_t *a_tab, *b_tab; - + a_len = a->len; b_len = b->len; - + if ((flags & BF_RND_MASK) == BF_RNDF) { /* faithful rounding does not require using the full inputs */ precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS; @@ -1583,7 +1582,7 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, } a_tab = a->tab + a->len - a_len; b_tab = b->tab + b->len - b_len; - + #ifdef USE_FFT_MUL if (b_len >= FFT_MUL_THRESHOLD) { int mul_flags = 0; @@ -1602,9 +1601,7 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, r = &tmp; } if (bf_resize(r, a_len + b_len)) { -#ifdef USE_FFT_MUL fail: -#endif bf_set_nan(r); ret = BF_ST_MEM_ERROR; goto done; @@ -1641,7 +1638,7 @@ slimb_t bf_get_exp_min(const bf_t *a) slimb_t i; limb_t v; int k; - + for(i = 0; i < a->len; i++) { v = a->tab[i]; if (v != 0) { @@ -1674,7 +1671,7 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_context_t *s = r->ctx; int ret, r_sign; limb_t n, nb, precl; - + r_sign = a->sign ^ b->sign; if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) { if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -1707,12 +1704,19 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS; nb = b->len; n = bf_max(a->len, precl); - + { limb_t *taba, na; slimb_t d; - + na = n + nb; + +#if LIMB_LOG2_BITS == 6 + if (na >= (SIZE_MAX / sizeof(limb_t)) - 1) { + return BF_ST_MEM_ERROR; /* Return memory error status */ + } +#endif + taba = bf_malloc(s, (na + 1) * sizeof(limb_t)); if (!taba) goto fail; @@ -1740,8 +1744,8 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, return BF_ST_MEM_ERROR; } -/* division and remainder. - +/* division and remainder. + rnd_mode is the rounding mode for the quotient. The additional rounding mode BF_RND_EUCLIDIAN is supported. @@ -1755,11 +1759,11 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, bf_t b1_s, *b1 = &b1_s; int q_sign, ret; BOOL is_ceil, is_rndn; - + assert(q != a && q != b); assert(r != a && r != b); assert(q != r); - + if (a->len == 0 || b->len == 0) { bf_set_zero(q, 0); if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -1801,7 +1805,7 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, a1->tab = a->tab; a1->len = a->len; a1->sign = 0; - + b1->expn = b->expn; b1->tab = b->tab; b1->len = b->len; @@ -1847,7 +1851,7 @@ int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t q_s, *q = &q_s; int ret; - + bf_init(r->ctx, q); ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode); bf_delete(q); @@ -1868,7 +1872,7 @@ int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t q_s, *q = &q_s; int ret; - + bf_init(r->ctx, q); ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode); bf_get_limb(pq, q, BF_GET_INT_MOD); @@ -1906,7 +1910,7 @@ static const uint16_t sqrt_table[192] = { static limb_t mp_sqrtrem1(limb_t *pr, limb_t a) { limb_t s1, r1, s, r, q, u, num; - + /* use a table for the 16 -> 8 bit sqrt */ s1 = sqrt_table[(a >> (LIMB_BITS - 8)) - 64]; r1 = (a >> (LIMB_BITS - 16)) - s1 * s1; @@ -1914,7 +1918,7 @@ static limb_t mp_sqrtrem1(limb_t *pr, limb_t a) r1 -= 2 * s1 + 1; s1++; } - + /* one iteration to get a 32 -> 16 bit sqrt */ num = (r1 << 8) | ((a >> (LIMB_BITS - 32 + 8)) & 0xff); q = num / (2 * s1); /* q <= 2^8 */ @@ -1996,7 +2000,7 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, limb_t *tmp_buf, limb_t *prh) { limb_t l, h, rh, ql, qh, c, i; - + if (n == 1) { *prh = mp_sqrtrem2(tabs, taba); return 0; @@ -2013,7 +2017,7 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h("r1", taba + 2 * l, h, qh); mp_print_str_h("r2", taba + l, n, qh); #endif - + /* the remainder is in taba + 2 * l. Its high bit is in qh */ if (qh) { mp_sub(taba + 2 * l, taba + 2 * l, tabs + l, h, 0); @@ -2035,12 +2039,12 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h("q", tabs, l, qh); mp_print_str_h("u", taba + l, h, rh); #endif - + mp_add_ui(tabs + l, qh, h); #ifdef DEBUG_SQRTREM mp_print_str_h("s2", tabs, n, sh); #endif - + /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */ if (qh) { @@ -2092,7 +2096,7 @@ int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n) int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a) { int ret; - + if (a->len == 0) { if (a->expn == BF_EXP_NAN) { bf_set_nan(r); @@ -2112,7 +2116,7 @@ int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a) ret = BF_ST_INVALID_OP; } else { bf_t rem_s, *rem; - + bf_sqrt(r, a, (a->expn + 1) / 2, BF_RNDZ); bf_rint(r, BF_RNDZ); /* see if the result is exact by computing the remainder */ @@ -2166,7 +2170,7 @@ int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) limb_t *a1; slimb_t n, n1; limb_t res; - + /* convert the mantissa to an integer with at least 2 * prec + 4 bits */ n = (2 * (prec + 2) + 2 * LIMB_BITS - 1) / (2 * LIMB_BITS); @@ -2211,7 +2215,7 @@ static no_inline int bf_op2(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t tmp; int ret; - + if (r == a || r == b) { bf_init(r->ctx, &tmp); ret = func(&tmp, a, b, prec, flags); @@ -2269,7 +2273,7 @@ int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, { bf_t b; int ret; - + bf_init(r->ctx, &b); ret = bf_set_si(&b, b1); ret |= bf_add(r, a, &b, prec, flags); @@ -2281,7 +2285,7 @@ static int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec, bf_flags_t flags) { int ret, n_bits, i; - + assert(r != a); if (b == 0) return bf_set_ui(r, 1); @@ -2300,15 +2304,12 @@ static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, { bf_t a; int ret; - -#ifdef USE_BF_DEC + if (a1 == 10 && b <= LIMB_DIGITS) { /* use precomputed powers. We do not round at this point because we expect the caller to do it */ ret = bf_set_ui(r, mp_pow_dec[b]); - } else -#endif - { + } else { bf_init(r->ctx, &a); ret = bf_set_ui(&a, a1); ret |= bf_pow_ui(r, &a, b, prec, flags); @@ -2348,7 +2349,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) slimb_t l, i, a_bit_offset, b_bit_offset; limb_t v1, v2, v1_mask, v2_mask, r_mask; int ret; - + assert(r != a1 && r != b1); if (a1->expn <= 0) @@ -2360,7 +2361,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) b_sign = 0; /* minus zero is considered as positive */ else b_sign = b1->sign; - + if (a_sign) { a = &a1_s; bf_init(r->ctx, a); @@ -2380,7 +2381,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) } else { b = (bf_t *)b1; } - + r_sign = bf_logic_op1(a_sign, b_sign, op); if (op == BF_LOGIC_AND && r_sign == 0) { /* no need to compute extra zeros for and */ @@ -2457,13 +2458,13 @@ int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode) Float64Union u; int e, ret; uint64_t m; - + ret = 0; if (a->expn == BF_EXP_NAN) { u.u = 0x7ff8000000000000; /* quiet nan */ } else { bf_t b_s, *b = &b_s; - + bf_init(a->ctx, b); bf_set(b, a); if (bf_is_finite(b)) { @@ -2506,7 +2507,7 @@ int bf_set_float64(bf_t *a, double d) Float64Union u; uint64_t m; int shift, e, sgn; - + u.d = d; sgn = u.u >> 63; e = (u.u >> 52) & ((1 << 11) - 1); @@ -2577,7 +2578,7 @@ int bf_get_int32(int *pres, const bf_t *a, int flags) ret = BF_ST_INVALID_OP; if (a->sign) { v = (uint32_t)INT32_MAX + 1; - if (a->expn == 32 && + if (a->expn == 32 && (a->tab[a->len - 1] >> (LIMB_BITS - 32)) == v) { ret = 0; } @@ -2585,7 +2586,7 @@ int bf_get_int32(int *pres, const bf_t *a, int flags) v = INT32_MAX; } } else { - v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); + v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); if (a->sign) v = -v; ret = 0; @@ -2643,7 +2644,7 @@ int bf_get_int64(int64_t *pres, const bf_t *a, int flags) } } else { slimb_t bit_pos = a->len * LIMB_BITS - a->expn; - v = get_bits(a->tab, a->len, bit_pos); + v = get_bits(a->tab, a->len, bit_pos); #if LIMB_BITS == 32 v |= (uint64_t)get_bits(a->tab, a->len, bit_pos + 32) << 32; #endif @@ -2703,7 +2704,7 @@ static limb_t get_limb_radix(int radix) { int i, k; limb_t radixl; - + k = digits_per_limb_table[radix - 2]; radixl = radix; for(i = 1; i < k; i++) @@ -2722,7 +2723,7 @@ static int bf_integer_from_radix_rec(bf_t *r, const limb_t *tab, } else { bf_t T_s, *T = &T_s, *B; limb_t n1, n2; - + n2 = (((n0 * 2) >> (level + 1)) + 1) / 2; n1 = n - n2; // printf("level=%d n0=%ld n1=%ld n2=%ld\n", level, n0, n1, n2); @@ -2758,7 +2759,7 @@ static int bf_integer_from_radix(bf_t *r, const limb_t *tab, int pow_tab_len, i, ret; limb_t radixl; bf_t *pow_tab; - + radixl = get_limb_radix(radix); pow_tab_len = ceil_log2(n) + 2; /* XXX: check */ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len); @@ -2839,7 +2840,7 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, return ret; } -static inline int to_digit(int c) +static inline int bf_to_digit(int c) { if (c >= '0' && c <= '9') return c - '0'; @@ -2907,7 +2908,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, slimb_t pos, expn, int_len, digit_count; BOOL has_decpt, is_bin_exp; bf_t a_s, *a; - + *pexponent = 0; p = str; if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 && @@ -2917,7 +2918,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } is_neg = 0; - + if (p[0] == '+') { p++; p_start = p; @@ -2946,7 +2947,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto no_prefix; } /* there must be a digit after the prefix */ - if (to_digit((uint8_t)*p) >= radix) { + if (bf_to_digit((uint8_t)*p) >= radix) { bf_set_nan(r); ret = 0; goto done; @@ -2960,7 +2961,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } } - + if (radix == 0) radix = 10; if (is_dec) { @@ -2994,14 +2995,14 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, int_len = digit_count = 0; for(;;) { limb_t c; - if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) { + if (*p == '.' && (p > p_start || bf_to_digit(p[1]) < radix)) { if (has_decpt) break; has_decpt = TRUE; int_len = digit_count; p++; } - c = to_digit(*p); + c = bf_to_digit(*p); if (c >= radix) break; digit_count++; @@ -3051,7 +3052,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } } - + /* reset the next limbs to zero (we prefer to reallocate in the renormalization) */ memset(a->tab, 0, (pos + 1) * sizeof(limb_t)); @@ -3082,7 +3083,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, } for(;;) { int c; - c = to_digit(*p); + c = bf_to_digit(*p); if (c >= 10) break; if (unlikely(expn > ((BF_RAW_EXP_MAX - 2 - 9) / 10))) { @@ -3109,7 +3110,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, } else if (radix_bits) { /* XXX: may overflow */ if (!is_bin_exp) - expn *= radix_bits; + expn *= radix_bits; a->expn = expn + (int_len * radix_bits); a->sign = is_neg; ret = bf_normalize_and_round(a, prec, flags); @@ -3148,9 +3149,9 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, return ret; } -/* +/* Return (status, n, exp). 'status' is the floating point status. 'n' - is the parsed number. + is the parsed number. If (flags & BF_ATOF_EXPONENT) and if the radix is not a power of two, the parsed number is equal to r * @@ -3365,7 +3366,7 @@ slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, const uint32_t *tab; limb_t b0, b1; dlimb_t t; - + if (is_inv) { tab = inv_log2_radix[radix - 2]; #if LIMB_BITS == 32 @@ -3399,7 +3400,7 @@ static int bf_integer_to_radix_rec(bf_t *pow_tab, { limb_t n1, n2, q_prec; int ret; - + assert(n >= 1); if (n == 1) { out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); @@ -3439,7 +3440,7 @@ static int bf_integer_to_radix_rec(bf_t *pow_tab, q_prec = n1 * radixl_bits; ret |= bf_mul(&Q, a, B_inv, q_prec, BF_RNDN); ret |= bf_rint(&Q, BF_RNDZ); - + ret |= bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ); ret |= bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ); @@ -3484,7 +3485,7 @@ static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl) limb_t r_len; bf_t *pow_tab; int i, pow_tab_len, ret; - + r_len = r->len; pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len); @@ -3514,7 +3515,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE, slimb_t E, e, prec, extra_bits, ziv_extra_bits, prec0; bf_t B_s, *B = &B_s; int e_sign, ret, res; - + if (a->len == 0) { /* zero case */ *pE = 0; @@ -3529,7 +3530,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE, } // bf_print_str("a", a); // printf("E=%ld P=%ld radix=%d\n", E, P, radix); - + for(;;) { e = P - E; e_sign = 0; @@ -3725,7 +3726,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, bf_context_t *ctx = a2->ctx; DynBuf s_s, *s = &s_s; int radix_bits; - + // bf_print_str("ftoa", a2); // printf("radix=%d\n", radix); dbuf_init2(s, ctx, bf_dbuf_realloc); @@ -3807,7 +3808,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, a->len = a2->len; a->expn = a2->expn; a->sign = 0; - + /* one more digit for the rounding */ n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE); n_digits = n + prec; @@ -3882,19 +3883,19 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, n = ceil_div(a1->expn, radix_bits); } else { bf_t a_s, *a = &a_s; - + /* make a positive number */ a->tab = a2->tab; a->len = a2->len; a->expn = a2->expn; a->sign = 0; - + if (fmt == BF_FTOA_FORMAT_FIXED) { n_digits = prec; n_max = n_digits; } else { slimb_t n_digits_max, n_digits_min; - + assert(prec != BF_PREC_INF); n_digits = 1 + bf_mul_log2_radix(prec, radix, TRUE, TRUE); /* max number of digits for non exponential @@ -3903,7 +3904,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, n_max = n_digits + 4; if (fmt == BF_FTOA_FORMAT_FREE_MIN) { bf_t b_s, *b = &b_s; - + /* find the minimum number of digits by dichotomy. */ /* XXX: inefficient */ @@ -4042,7 +4043,7 @@ static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1, bf_t T1_s, *T1 = &T1_s; bf_t P1_s, *P1 = &P1_s; bf_t Q1_s, *Q1 = &Q1_s; - + m = n1 + ((n2 - n1) >> 1); bf_const_log2_rec(T, P, Q, n1, m, TRUE); bf_init(s, T1); @@ -4093,7 +4094,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, if (a == (b - 1)) { bf_t T0, T1; - + bf_init(s, &T0); bf_init(s, &T1); bf_set_ui(G, 2 * b - 1); @@ -4114,7 +4115,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, bf_delete(&T1); } else { bf_t P2, Q2, G2; - + bf_init(s, &P2); bf_init(s, &Q2); bf_init(s, &G2); @@ -4122,7 +4123,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, c = (a + b) / 2; chud_bs(P, Q, G, a, c, 1, prec); chud_bs(&P2, &Q2, &G2, c, b, need_g, prec); - + /* Q = Q1 * Q2 */ /* G = G1 * G2 */ /* P = P1 * Q2 + P2 * G1 */ @@ -4158,11 +4159,11 @@ static void bf_const_pi_internal(bf_t *Q, limb_t prec) bf_init(s, &G); chud_bs(&P, Q, &G, 0, n, 0, BF_PREC_INF); - + bf_mul_ui(&G, Q, CHUD_A, prec1, BF_RNDN); bf_add(&P, &G, &P, prec1, BF_RNDN); bf_div(Q, Q, &P, prec1, BF_RNDF); - + bf_set_ui(&P, CHUD_C); bf_sqrt(&G, &P, prec1, BF_RNDF); bf_mul_ui(&G, &G, (uint64_t)CHUD_C / 12, prec1, BF_RNDF); @@ -4245,7 +4246,7 @@ static int bf_ziv_rounding(bf_t *r, const bf_t *a, { int rnd_mode, ret; slimb_t prec1, ziv_extra_bits; - + rnd_mode = flags & BF_RND_MASK; if (rnd_mode == BF_RNDF) { /* no need to iterate */ @@ -4304,7 +4305,7 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; slimb_t n, K, l, i, prec1; - + assert(r != a); /* argument reduction: @@ -4337,14 +4338,14 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* reduce the range of T */ bf_mul_2exp(T, -K, BF_PREC_INF, BF_RNDZ); - + /* Taylor expansion around zero : - 1 + x + x^2/2 + ... + x^n/n! + 1 + x + x^2/2 + ... + x^n/n! = (1 + x * (1 + x/2 * (1 + ... (x/n)))) */ { bf_t U_s, *U = &U_s; - + bf_init(s, U); bf_set_ui(r, 1); for(i = l ; i >= 1; i--) { @@ -4356,7 +4357,7 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_delete(U); } bf_delete(T); - + /* undo the range reduction */ for(i = 0; i < K; i++) { bf_mul(r, r, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP); @@ -4376,7 +4377,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, bf_t T_s, *T = &T_s; bf_t log2_s, *log2 = &log2_s; slimb_t e_min, e_max; - + if (a_high->expn <= 0) return 0; @@ -4384,7 +4385,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, e_min = -e_max + 3; if (flags & BF_FLAG_SUBNORMAL) e_min -= (prec - 1); - + bf_init(s, T); bf_init(s, log2); bf_const_log2(log2, LIMB_BITS, BF_RNDU); @@ -4401,7 +4402,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, bf_mul_si(T, log2, e_min - 2, LIMB_BITS, BF_RNDD); if (bf_cmp_lt(a_high, T)) { int rnd_mode = flags & BF_RND_MASK; - + /* underflow */ bf_delete(T); bf_delete(log2); @@ -4441,12 +4442,12 @@ int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) ret = check_exp_underflow_overflow(s, r, a, a, prec, flags); if (ret) return ret; - if (a->expn < 0 && (-a->expn) >= (prec + 2)) { + if (a->expn < 0 && (-a->expn) >= (prec + 2)) { /* small argument case: result = 1 + epsilon * sign(x) */ bf_set_ui(r, 1); return bf_add_epsilon(r, r, -(prec + 2), a->sign, prec, flags); } - + return bf_ziv_rounding(r, a, prec, flags, bf_exp_internal, NULL); } @@ -4457,7 +4458,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_t U_s, *U = &U_s; bf_t V_s, *V = &V_s; slimb_t n, prec1, l, i, K; - + assert(r != a); bf_init(s, T); @@ -4470,7 +4471,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) T->expn = 0; /* U= ~ 2/3 */ bf_init(s, U); - bf_set_ui(U, 0xaaaaaaaa); + bf_set_ui(U, 0xaaaaaaaa); U->expn = 0; if (bf_cmp_lt(T, U)) { T->expn++; @@ -4483,18 +4484,18 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* XXX: precision analysis */ /* number of iterations for argument reduction 2 */ - K = bf_isqrt((prec + 1) / 2); + K = bf_isqrt((prec + 1) / 2); /* order of Taylor expansion */ - l = prec / (2 * K) + 1; + l = prec / (2 * K) + 1; /* precision of the intermediate computations */ prec1 = prec + K + 2 * l + 32; bf_init(s, U); bf_init(s, V); - + /* Note: cancellation occurs here, so we use more precision (XXX: reduce the precision by computing the exact cancellation) */ - bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN); + bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN); /* argument reduction 2 */ for(i = 0; i < K; i++) { @@ -4512,7 +4513,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_init(s, Y2); /* compute ln(1+x) = ln((1+y)/(1-y)) with y=x/(2+x) - = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1) + = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1) with Y=Y^2 = y*(1+Y/3+Y^2/5+...) = y*(1+Y*(1/3+Y*(1/5 + ...))) */ @@ -4539,12 +4540,12 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* multiplication by 2 for the Taylor expansion and undo the argument reduction 2*/ bf_mul_2exp(r, K + 1, BF_PREC_INF, BF_RNDZ); - + /* undo the argument reduction 1 */ bf_const_log2(T, prec1, BF_RNDF); bf_mul_si(T, T, n, prec1, BF_RNDN); bf_add(r, r, T, prec1, BF_RNDN); - + bf_delete(T); return BF_ST_INEXACT; } @@ -4553,7 +4554,7 @@ int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) { bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; - + assert(r != a); if (a->len == 0) { if (a->expn == BF_EXP_NAN) { @@ -4618,7 +4619,7 @@ static int bf_pow_int(bf_t *r, const bf_t *x, limb_t prec, void *opaque) limb_t prec1; int ret; slimb_t y1; - + bf_get_limb(&y1, y, 0); if (y1 < 0) y1 = -y1; @@ -4643,7 +4644,7 @@ static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n) bf_t T_s, *T = &T_s; slimb_t e, i, er; limb_t v; - + /* x = m*2^e with m odd integer */ e = bf_get_exp_min(x); /* fast check on the exponent */ @@ -4683,7 +4684,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) BOOL y_is_int, y_is_odd; int r_sign, ret, rnd_mode; slimb_t y_emin; - + if (x->len == 0 || y->len == 0) { if (y->expn == BF_EXP_ZERO) { /* pow(x, 0) = 1 */ @@ -4757,7 +4758,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) bf_t al_s, *al = &al_s; bf_t ah_s, *ah = &ah_s; limb_t precl = LIMB_BITS; - + bf_init(s, al); bf_init(s, ah); /* compute bounds of log(abs(x)) * y with a low precision */ @@ -4773,7 +4774,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) if (ret) goto done; } - + if (y_is_int) { slimb_t T_bits, e; int_pow: @@ -4820,11 +4821,6 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) bf_t *y1; if (y_emin < 0 && check_exact_power2n(r, T, -y_emin)) { /* the problem is reduced to a power to an integer */ -#if 0 - printf("\nn=%" PRId64 "\n", -(int64_t)y_emin); - bf_print_str("T", T); - bf_print_str("r", r); -#endif bf_set(T, r); y1 = &ytmp_s; y1->tab = y->tab; @@ -4868,18 +4864,18 @@ static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec) bf_t r_s, *r = &r_s; slimb_t K, prec1, i, l, mod, prec2; int is_neg; - + assert(c != a && s != a); bf_init(s1, T); bf_init(s1, U); bf_init(s1, r); - + /* XXX: precision analysis */ K = bf_isqrt(prec / 2); l = prec / (2 * K) + 1; prec1 = prec + 2 * K + l + 8; - + /* after the modulo reduction, -pi/4 <= T <= pi/4 */ if (a->expn <= -1) { /* abs(a) <= 0.25: no modulo reduction needed */ @@ -4902,13 +4898,13 @@ static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec) } mod &= 3; } - + is_neg = T->sign; - + /* compute cosm1(x) = cos(x) - 1 */ bf_mul(T, T, T, prec1, BF_RNDN); bf_mul_2exp(T, -2 * K, BF_PREC_INF, BF_RNDZ); - + /* Taylor expansion: -x^2/2 + x^4/4! - x^6/6! + ... */ @@ -4987,7 +4983,7 @@ int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, 1, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_cos_internal, NULL); } @@ -5030,7 +5026,7 @@ static int bf_tan_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; limb_t prec1; - + /* XXX: precision analysis */ prec1 = prec + 8; bf_init(s, T); @@ -5066,7 +5062,7 @@ int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, a->sign, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_tan_internal, NULL); } @@ -5083,13 +5079,13 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, bf_t X2_s, *X2 = &X2_s; int cmp_1; slimb_t prec1, i, K, l; - + /* XXX: precision analysis */ K = bf_isqrt((prec + 1) / 2); l = prec / (2 * K) + 1; prec1 = prec + K + 2 * l + 32; // printf("prec=%d K=%d l=%d prec1=%d\n", (int)prec, (int)K, (int)l, (int)prec1); - + bf_init(s, T); cmp_1 = (a->expn >= 1); /* a >= 1 */ if (cmp_1) { @@ -5115,8 +5111,8 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, bf_div(T, T, V, prec1, BF_RNDN); } - /* Taylor series: - x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1) + /* Taylor series: + x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1) */ bf_mul(X2, T, T, prec1, BF_RNDN); bf_set_ui(r, 0); @@ -5134,7 +5130,7 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, /* undo the argument reduction */ bf_mul_2exp(r, K, BF_PREC_INF, BF_RNDZ); - + bf_delete(U); bf_delete(V); bf_delete(X2); @@ -5153,7 +5149,7 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, T->sign = (i < 0); bf_add(r, T, r, prec1, BF_RNDN); } - + bf_delete(T); return BF_ST_INEXACT; } @@ -5163,7 +5159,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; int res; - + if (a->len == 0) { if (a->expn == BF_EXP_NAN) { bf_set_nan(r); @@ -5178,7 +5174,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return 0; } } - + bf_init(s, T); bf_set_ui(T, 1); res = bf_cmpu(a, T); @@ -5200,7 +5196,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)FALSE); } @@ -5211,7 +5207,7 @@ static int bf_atan2_internal(bf_t *r, const bf_t *y, limb_t prec, void *opaque) bf_t T_s, *T = &T_s; limb_t prec1; int ret; - + if (y->expn == BF_EXP_NAN || x->expn == BF_EXP_NAN) { bf_set_nan(r); return 0; @@ -5254,8 +5250,8 @@ static int bf_asin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) BOOL is_acos = (BOOL)(intptr_t)opaque; bf_t T_s, *T = &T_s; limb_t prec1, prec2; - - /* asin(x) = atan(x/sqrt(1-x^2)) + + /* asin(x) = atan(x/sqrt(1-x^2)) acos(x) = pi/2 - asin(x) */ prec1 = prec + 8; /* increase the precision in x^2 to compensate the cancellation in @@ -5305,7 +5301,7 @@ int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_set_nan(r); return BF_ST_INVALID_OP; } - + /* small argument case: result = x+r(x) with r(x) = x^3/6 + O(X^5). We assume r(x) < 2^(3*EXP(x) - 2). */ if (a->expn < 0) { @@ -5350,7 +5346,7 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_set_zero(r, 0); return 0; } - + return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE); } @@ -5376,19 +5372,20 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) #if LIMB_BITS == 64 /* Note: we assume __int128 is available */ +/* uint128_t defined in libbf.h */ #define muldq(r1, r0, a, b) \ do { \ - unsigned __int128 __t; \ - __t = (unsigned __int128)(a) * (unsigned __int128)(b); \ + uint128_t __t; \ + __t = (uint128_t)(a) * (uint128_t)(b); \ r0 = __t; \ r1 = __t >> 64; \ } while (0) #define divdq(q, r, a1, a0, b) \ do { \ - unsigned __int128 __t; \ + uint128_t __t; \ limb_t __b = (b); \ - __t = ((unsigned __int128)(a1) << 64) | (a0); \ + __t = ((uint128_t)(a1) << 64) | (a0); \ q = __t / __b; \ r = __t % __b; \ } while (0) @@ -5568,8 +5565,8 @@ static inline limb_t fast_shr_dec(limb_t a, int shift) /* division and remainder by 10^shift */ #define fast_shr_rem_dec(q, r, a, shift) q = fast_shr_dec(a, shift), r = a - q * mp_pow_dec[shift] - -limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, + +limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, mp_size_t n, limb_t carry) { limb_t base = BF_DEC_BASE; @@ -5582,7 +5579,7 @@ limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, v = op1[i]; a = v + op2[i] + k - base; k = a <= v; - if (!k) + if (!k) a += base; res[i]=a; } @@ -5600,7 +5597,7 @@ limb_t mp_add_ui_dec(limb_t *tab, limb_t b, mp_size_t n) v = tab[i]; a = v + k - base; k = a <= v; - if (!k) + if (!k) a += base; tab[i] = a; if (k == 0) @@ -5609,7 +5606,7 @@ limb_t mp_add_ui_dec(limb_t *tab, limb_t b, mp_size_t n) return k; } -limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2, +limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2, mp_size_t n, limb_t carry) { limb_t base = BF_DEC_BASE; @@ -5633,7 +5630,7 @@ limb_t mp_sub_ui_dec(limb_t *tab, limb_t b, mp_size_t n) limb_t base = BF_DEC_BASE; mp_size_t i; limb_t k, v, a; - + k=b; for(i=0;i= UDIV1NORM_THRESHOLD) { shift = clz(b); @@ -5822,7 +5819,7 @@ static __maybe_unused void mp_print_str_h_dec(const char *str, #define DIV_STATIC_ALLOC_LEN 16 -/* return q = a / b and r = a % b. +/* return q = a / b and r = a % b. taba[na] must be allocated if tabb1[nb - 1] < B / 2. tabb1[nb - 1] must be != zero. na must be >= nb. 's' can be NULL if tabb1[nb - 1] @@ -5836,14 +5833,14 @@ static __maybe_unused void mp_print_str_h_dec(const char *str, */ /* XXX: optimize */ static int mp_div_dec(bf_context_t *s, limb_t *tabq, - limb_t *taba, mp_size_t na, + limb_t *taba, mp_size_t na, const limb_t *tabb1, mp_size_t nb) { limb_t base = BF_DEC_BASE; limb_t r, mult, t0, t1, a, c, q, v, *tabb; mp_size_t i, j; limb_t static_tabb[DIV_STATIC_ALLOC_LEN]; - + #ifdef DEBUG_DIV_SLOW mp_print_str_dec("a", taba, na); mp_print_str_dec("b", tabb1, nb); @@ -5941,7 +5938,7 @@ static int mp_div_dec(bf_context_t *s, limb_t *tabq, } /* divide by 10^shift */ -static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, limb_t shift, limb_t high) { mp_size_t i; @@ -5959,7 +5956,7 @@ static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, } /* multiply by 10^shift */ -static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, limb_t shift, limb_t low) { mp_size_t i; @@ -6005,7 +6002,7 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, limb_t *tmp_buf) { limb_t l, h, rh, ql, qh, c, i; - + if (n == 1) return mp_sqrtrem2_dec(tabs, taba); #ifdef DEBUG_SQRTREM_DEC @@ -6019,7 +6016,7 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h_dec("r1", taba + 2 * l, h, qh); mp_print_str_h_dec("r2", taba + l, n, qh); #endif - + /* the remainder is in taba + 2 * l. Its high bit is in qh */ if (qh) { mp_sub_dec(taba + 2 * l, taba + 2 * l, tabs + l, h, 0); @@ -6040,12 +6037,12 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h_dec("q", tabs, l, qh); mp_print_str_h_dec("u", taba + l, h, rh); #endif - + mp_add_ui_dec(tabs + l, qh, h); #ifdef DEBUG_SQRTREM_DEC mp_print_str_dec("s2", tabs, n); #endif - + /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */ if (qh) { @@ -6333,41 +6330,13 @@ static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos) return fast_shr_dec(tab[i], shift) % 10; } -#if 0 -static limb_t get_digits(const limb_t *tab, limb_t len, slimb_t pos) -{ - limb_t a0, a1; - int shift; - slimb_t i; - - i = floor_div(pos, LIMB_DIGITS); - shift = pos - i * LIMB_DIGITS; - if (i >= 0 && i < len) - a0 = tab[i]; - else - a0 = 0; - if (shift == 0) { - return a0; - } else { - i++; - if (i >= 0 && i < len) - a1 = tab[i]; - else - a1 = 0; - return fast_shr_dec(a0, shift) + - fast_urem(a1, &mp_pow_div[LIMB_DIGITS - shift]) * - mp_pow_dec[shift]; - } -} -#endif - /* return the addend for rounding. Note that prec can be <= 0 for bf_rint() */ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, slimb_t prec, int rnd_mode) { int add_one, inexact; limb_t digit1, digit0; - + // bfdec_print_str("get_rnd_add", r); if (rnd_mode == BF_RNDF) { digit0 = 1; /* faithful rounding does not honor the INEXACT flag */ @@ -6379,7 +6348,7 @@ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, /* get the digit at 'prec' */ digit1 = get_digit(r->tab, l, l * LIMB_DIGITS - 1 - prec); inexact = (digit1 | digit0) != 0; - + add_one = 0; switch(rnd_mode) { case BF_RNDZ: @@ -6412,7 +6381,7 @@ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, default: abort(); } - + if (inexact) *pret |= BF_ST_INEXACT; return add_one; @@ -6432,7 +6401,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1); e_min = -e_range + 3; e_max = e_range; - + if (flags & BF_FLAG_RADPNT_PREC) { /* 'prec' is the precision after the decimal point */ if (prec1 != BF_PREC_INF) @@ -6447,12 +6416,12 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) } else { prec = prec1; } - + /* round to prec bits */ rnd_mode = flags & BF_RND_MASK; ret = 0; add_one = bfdec_get_rnd_add(&ret, r, l, prec, rnd_mode); - + if (prec <= 0) { if (add_one) { bfdec_resize(r, 1); /* cannot fail because r is non zero */ @@ -6465,7 +6434,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) } } else if (add_one) { limb_t carry; - + /* add one starting at digit 'prec - 1' */ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1); pos = bit_pos / LIMB_DIGITS; @@ -6477,7 +6446,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) r->expn++; } } - + /* check underflow */ if (unlikely(r->expn < e_min)) { if (flags & BF_FLAG_SUBNORMAL) { @@ -6491,14 +6460,14 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) return ret; } } - + /* check overflow */ if (unlikely(r->expn > e_max)) { bfdec_set_inf(r, r->sign); ret |= BF_ST_OVERFLOW | BF_ST_INEXACT; return ret; } - + /* keep the bits starting at 'prec - 1' */ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1); i = floor_div(bit_pos, LIMB_DIGITS); @@ -6535,7 +6504,7 @@ int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags) { limb_t l, v; int shift, ret; - + // bfdec_print_str("bf_renorm", r); l = r->len; while (l > 0 && r->tab[l - 1] == 0) @@ -6652,7 +6621,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li limb_t *b1_tab; int b_shift; mp_size_t b1_len; - + d = a->expn - b->expn; /* XXX: not efficient in time and memory if the precision is @@ -6668,7 +6637,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li r->tab[i] = 0; for(i = 0; i < a->len; i++) r->tab[a_offset + i] = a->tab[i]; - + b_shift = d % LIMB_DIGITS; if (b_shift == 0) { b1_len = b->len; @@ -6682,7 +6651,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li mp_pow_dec[LIMB_DIGITS - b_shift]; } b_offset = r_len - (b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS); - + if (is_sub) { carry = mp_sub_dec(r->tab + b_offset, r->tab + b_offset, b1_tab, b1_len, 0); @@ -6778,12 +6747,12 @@ int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bfdec_t tmp, *r1 = NULL; limb_t a_len, b_len; limb_t *a_tab, *b_tab; - + a_len = a->len; b_len = b->len; a_tab = a->tab; b_tab = b->tab; - + if (r == a || r == b) { bfdec_init(r->ctx, &tmp); r1 = r; @@ -6822,7 +6791,7 @@ int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec, { bfdec_t b; int ret; - + bfdec_init(r->ctx, &b); ret = bfdec_set_si(&b, b1); ret |= bfdec_add(r, a, &b, prec, flags); @@ -6835,7 +6804,7 @@ static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, { int ret, r_sign; limb_t n, nb, precl; - + r_sign = a->sign ^ b->sign; if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) { if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -6880,11 +6849,11 @@ static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, precl = (prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS; } n = bf_max(a->len, precl); - + { limb_t *taba, na, i; slimb_t d; - + na = n + nb; taba = bf_malloc(r->ctx, (na + 1) * sizeof(limb_t)); if (!taba) @@ -6945,8 +6914,8 @@ static void bfdec_tdivremu(bf_context_t *s, bfdec_t *q, bfdec_t *r, } } -/* division and remainder. - +/* division and remainder. + rnd_mode is the rounding mode for the quotient. The additional rounding mode BF_RND_EUCLIDIAN is supported. @@ -6962,11 +6931,11 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, bfdec_t r1_s, *r1 = &r1_s; int q_sign, res; BOOL is_ceil, is_rndn; - + assert(q != a && q != b); assert(r != a && r != b); assert(q != r); - + if (a->len == 0 || b->len == 0) { bfdec_set_zero(q, 0); if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -7008,7 +6977,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, a1->tab = a->tab; a1->len = a->len; a1->sign = 0; - + b1->expn = b->expn; b1->tab = b->tab; b1->len = b->len; @@ -7022,7 +6991,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, goto fail; // bfdec_print_str("q", q); // bfdec_print_str("r", r); - + if (r->len != 0) { if (is_rndn) { bfdec_init(s, r1); @@ -7063,7 +7032,7 @@ int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, { bfdec_t q_s, *q = &q_s; int ret; - + bfdec_init(r->ctx, q); ret = bfdec_divrem(q, r, a, b, prec, flags, rnd_mode); bfdec_delete(q); @@ -7211,7 +7180,7 @@ int bfdec_get_int32(int *pres, const bfdec_t *a) int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b) { int ret, n_bits, i; - + assert(r != a); if (b == 0) return bfdec_set_ui(r, 1); @@ -7351,7 +7320,7 @@ static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = { typedef struct BFNTTState { bf_context_t *ctx; - + /* used for mul_mod_fast() */ limb_t ntt_mods_div[NB_MODS]; @@ -7391,16 +7360,16 @@ static inline limb_t sub_mod(limb_t a, limb_t b, limb_t m) return r; } -/* return (r0+r1*B) mod m - precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN) +/* return (r0+r1*B) mod m + precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN) */ -static inline limb_t mod_fast(dlimb_t r, +static inline limb_t mod_fast(dlimb_t r, limb_t m, limb_t m_inv) { limb_t a1, q, t0, r1, r0; - + a1 = r >> NTT_MOD_LOG2_MIN; - + q = ((dlimb_t)a1 * m_inv) >> LIMB_BITS; r = r - (dlimb_t)q * m - m * 2; r1 = r >> LIMB_BITS; @@ -7412,9 +7381,9 @@ static inline limb_t mod_fast(dlimb_t r, return r0; } -/* faster version using precomputed modulo inverse. +/* faster version using precomputed modulo inverse. precondition: 0 <= a * b < 2^(64+NTT_MOD_LOG2_MIN) */ -static inline limb_t mul_mod_fast(limb_t a, limb_t b, +static inline limb_t mul_mod_fast(limb_t a, limb_t b, limb_t m, limb_t m_inv) { dlimb_t r; @@ -7433,7 +7402,7 @@ static inline limb_t init_mul_mod_fast(limb_t m) /* Faster version used when the multiplier is constant. 0 <= a < 2^64, 0 <= b < m. */ -static inline limb_t mul_mod_fast2(limb_t a, limb_t b, +static inline limb_t mul_mod_fast2(limb_t a, limb_t b, limb_t m, limb_t b_inv) { limb_t r, q; @@ -7448,7 +7417,7 @@ static inline limb_t mul_mod_fast2(limb_t a, limb_t b, /* Faster version used when the multiplier is constant. 0 <= a < 2^64, 0 <= b < m. Let r = a * b mod m. The return value is 'r' or 'r + m'. */ -static inline limb_t mul_mod_fast3(limb_t a, limb_t b, +static inline limb_t mul_mod_fast3(limb_t a, limb_t b, limb_t m, limb_t b_inv) { limb_t r, q; @@ -7554,9 +7523,9 @@ static no_inline int ntt_fft(BFNTTState *s, __m256d m_inv, mf, m2f, c, a0, a1, b0, b1; limb_t m; int l; - + m = ntt_mods[m_idx]; - + m_inv = _mm256_set1_pd(1.0 / (double)m); mf = _mm256_set1_pd(m); m2f = _mm256_set1_pd(m * 2); @@ -7610,7 +7579,7 @@ static no_inline int ntt_fft(BFNTTState *s, tmp = tab_in; tab_in = tab_out; tab_out = tmp; - + nb_blocks = n / 4; fft_per_block = 4; @@ -7661,7 +7630,7 @@ static void ntt_vec_mul(BFNTTState *s, { limb_t i, c_inv, n, m; __m256d m_inv, mf, a, b, c; - + m = ntt_mods[m_idx]; c_inv = s->ntt_len_inv[m_idx][k_tot][0]; m_inv = _mm256_set1_pd(1.0 / (double)m); @@ -7683,7 +7652,7 @@ static no_inline void mul_trig(NTTLimb *buf, limb_t i, c2, c3, c4; __m256d c, c_mul, a0, mf, m_inv; assert(n >= 2); - + mf = _mm256_set1_pd(m); m_inv = _mm256_set1_pd(1.0 / (double)m); @@ -7732,7 +7701,7 @@ static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf, limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j, m, m2; NTTLimb *tab_in, *tab_out, *tmp, a0, a1, b0, b1, c, *trig, c_inv; int l; - + m = ntt_mods[m_idx]; m2 = 2 * m; n = (limb_t)1 << fft_len_log2; @@ -7772,7 +7741,7 @@ static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf, tab_out = tmp; } /* no twiddle in last step */ - tab_out = out_buf; + tab_out = out_buf; for(k = 0; k < stride_in; k++) { a0 = tab_in[k]; a1 = tab_in[k + stride_in]; @@ -7789,7 +7758,7 @@ static void ntt_vec_mul(BFNTTState *s, int k_tot, int m_idx) { limb_t i, norm, norm_inv, a, n, m, m_inv; - + m = ntt_mods[m_idx]; m_inv = s->ntt_mods_div[m_idx]; norm = s->ntt_len_inv[m_idx][k_tot][0]; @@ -7811,7 +7780,7 @@ static no_inline void mul_trig(NTTLimb *buf, limb_t n, limb_t c_mul, limb_t m, limb_t m_inv) { limb_t i, c0, c_mul_inv; - + c0 = 1; c_mul_inv = init_mul_mod_fast2(c_mul, m); for(i = 0; i < n; i++) { @@ -7827,7 +7796,7 @@ static no_inline NTTLimb *get_trig(BFNTTState *s, { NTTLimb *tab; limb_t i, n2, c, c_mul, m, c_mul_inv; - + if (k > NTT_TRIG_K_MAX) return NULL; @@ -7892,7 +7861,7 @@ static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1, { limb_t i, j, c_mul, c0, m, m_inv, strip_len, l; NTTLimb *buf2, *buf3; - + buf2 = NULL; buf3 = ntt_malloc(s, sizeof(NTTLimb) * n1); if (!buf3) @@ -7925,7 +7894,7 @@ static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1, mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv); c_mul = mul_mod_fast(c_mul, c0, m, m_inv); } - + for(i = 0; i < n1; i++) { for(l = 0; l < strip_len; l++) { buf1[i * n2 + (j + l)] = buf2[i + l *n1]; @@ -7949,7 +7918,7 @@ static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2, { limb_t n1, n2, i; int k1, k2; - + if (k <= NTT_TRIG_K_MAX) { k1 = k; } else { @@ -7959,7 +7928,7 @@ static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2, k2 = k - k1; n1 = (limb_t)1 << k1; n2 = (limb_t)1 << k2; - + if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 0, m_idx)) return -1; if (ntt_fft_partial(s, buf2, k1, k2, n1, n2, 0, m_idx)) @@ -7986,13 +7955,7 @@ static no_inline void limb_to_ntt(BFNTTState *s, dlimb_t a, b; int j, shift; limb_t base_mask1, a0, a1, a2, r, m, m_inv; - -#if 0 - for(i = 0; i < a_len; i++) { - printf("%" PRId64 ": " FMT_LIMB "\n", - (int64_t)i, taba[i]); - } -#endif + memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods); shift = dpl & (LIMB_BITS - 1); if (shift == 0) @@ -8057,21 +8020,21 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, slimb_t i, len, pos; int j, k, l, shift, n_limb1, p; dlimb_t t; - + j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2; mods_cr_vec = s->ntt_mods_cr_vec + j; mf = s->ntt_mods_vec + NB_MODS - nb_mods; m_inv = s->ntt_mods_inv_vec + NB_MODS - nb_mods; - + shift = dpl & (LIMB_BITS - 1); if (shift == 0) base_mask1 = -1; else base_mask1 = ((limb_t)1 << shift) - 1; n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) carry[j] = 0; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) u[j] = 0; /* avoid warnings */ memset(tabr, 0, sizeof(limb_t) * r_len); fft_len = (limb_t)1 << fft_len_log2; @@ -8093,7 +8056,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } } y[j].v = ntt_mod1(y[j].v, mf[j]); - + for(p = 0; p < VEC_LEN; p++) { /* back to normal representation */ u[0] = (int64_t)y[nb_mods - 1].d[p]; @@ -8109,7 +8072,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, l++; } /* XXX: for nb_mods = 5, l should be 4 */ - + /* last step adds the carry */ r = (int64_t)y[0].d[p]; for(k = 0; k < l; k++) { @@ -8119,14 +8082,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } u[l] = r + carry[l]; -#if 0 - printf("%" PRId64 ": ", i); - for(j = nb_mods - 1; j >= 0; j--) { - printf(" %019" PRIu64, u[j]); - } - printf("\n"); -#endif - /* write the digits */ pos = i * dpl; for(j = 0; j < n_limb1; j++) { @@ -8160,7 +8115,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, slimb_t i, len, pos; int j, k, l, shift, n_limb1; dlimb_t t; - + j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2; mods_cr = ntt_mods_cr + j; mods_cr_inv = s->ntt_mods_cr_inv + j; @@ -8171,9 +8126,9 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, else base_mask1 = ((limb_t)1 << shift) - 1; n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) carry[j] = 0; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) u[j] = 0; /* avoid warnings */ memset(tabr, 0, sizeof(limb_t) * r_len); fft_len = (limb_t)1 << fft_len_log2; @@ -8191,12 +8146,12 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, m = mods[k]; /* Note: there is no overflow in the sub_mod() because the modulos are sorted by increasing order */ - y[k] = mul_mod_fast2(y[k] - y[j] + m, + y[k] = mul_mod_fast2(y[k] - y[j] + m, mods_cr[l], m, mods_cr_inv[l]); l++; } } - + /* back to normal representation */ u[0] = y[nb_mods - 1]; l = 1; @@ -8210,7 +8165,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, u[l] = r; l++; } - + /* last step adds the carry */ r = y[0]; for(k = 0; k < l; k++) { @@ -8220,14 +8175,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } u[l] = r + carry[l]; -#if 0 - printf("%" PRId64 ": ", (int64_t)i); - for(j = nb_mods - 1; j >= 0; j--) { - printf(" " FMT_LIMB, u[j]); - } - printf("\n"); -#endif - /* write the digits */ pos = i * dpl; for(j = 0; j < n_limb1; j++) { @@ -8268,7 +8215,7 @@ static int ntt_static_init(bf_context_t *s1) memset(s, 0, sizeof(*s)); s1->ntt_state = s; s->ctx = s1; - + for(j = 0; j < NB_MODS; j++) { m = ntt_mods[j]; m_inv = init_mul_mod_fast(m); @@ -8317,7 +8264,7 @@ int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len) int dpl, fft_len_log2, n_bits, nb_mods, dpl_found, fft_len_log2_found; int int_bits, nb_mods_found; limb_t cost, min_cost; - + min_cost = -1; dpl_found = 0; nb_mods_found = 4; @@ -8373,11 +8320,11 @@ static no_inline int fft_mul(bf_context_t *s1, #if defined(USE_MUL_CHECK) limb_t ha, hb, hr, h_ref; #endif - + if (ntt_static_init(s1)) return -1; s = s1->ntt_state; - + /* find the optimal number of digits per limb (dpl) */ len = a_len + b_len; fft_len_log2 = bf_get_fft_size(&dpl, &nb_mods, len); @@ -8405,7 +8352,7 @@ static no_inline int fft_mul(bf_context_t *s1, return -1; limb_to_ntt(s, buf1, fft_len, a_tab, a_len, dpl, NB_MODS - nb_mods, nb_mods); - if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == + if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == FFT_MUL_R_OVERLAP_A) { if (!(mul_flags & FFT_MUL_R_NORESIZE)) bf_resize(res, 0); @@ -8455,7 +8402,7 @@ static no_inline int fft_mul(bf_context_t *s1, // printf("ha=0x" FMT_LIMB" hb=0x" FMT_LIMB " hr=0x" FMT_LIMB " expected=0x" FMT_LIMB "\n", ha, hb, hr, h_ref); exit(1); } -#endif +#endif return 0; fail: ntt_free(s, buf1); @@ -8471,3 +8418,7 @@ int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len) } #endif /* !USE_FFT_MUL */ + +#undef malloc +#undef free +#undef realloc diff --git a/libbf.h b/libbf.h index 0457c18..3586532 100644 --- a/libbf.h +++ b/libbf.h @@ -1,6 +1,6 @@ /* * Tiny arbitrary precision floating point library - * + * * Copyright (c) 2017-2021 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,7 +27,11 @@ #include #include -#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX) +#ifdef __cplusplus +extern "C" { +#endif + +#if INTPTR_MAX >= INT64_MAX && !defined(_WIN32) && !defined(__TINYC__) #define LIMB_LOG2_BITS 6 #else #define LIMB_LOG2_BITS 5 @@ -36,8 +40,10 @@ #define LIMB_BITS (1 << LIMB_LOG2_BITS) #if LIMB_BITS == 64 -typedef __int128 int128_t; -typedef unsigned __int128 uint128_t; +#ifndef INT128_MAX +__extension__ typedef __int128 int128_t; +__extension__ typedef unsigned __int128 uint128_t; +#endif typedef int64_t slimb_t; typedef uint64_t limb_t; typedef uint128_t dlimb_t; @@ -171,7 +177,7 @@ static inline bf_flags_t bf_set_exp_bits(int n) #define BF_ST_UNDERFLOW (1 << 3) #define BF_ST_INEXACT (1 << 4) /* indicate that a memory allocation error occured. NaN is returned */ -#define BF_ST_MEM_ERROR (1 << 5) +#define BF_ST_MEM_ERROR (1 << 5) #define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */ @@ -284,7 +290,7 @@ int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags) int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags); -int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, +int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags); int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); @@ -341,12 +347,12 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, /* fractional format: prec digits after the decimal point rounded with (flags & BF_RND_MASK) */ #define BF_FTOA_FORMAT_FRAC (1 << 16) -/* free format: - +/* free format: + For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum number of digits to represent 'a'. The precision and the rounding mode are ignored. - + For the non binary radices with bf_ftoa(): use as many digits as necessary so that bf_atof() return the same number when using precision 'prec', rounding to nearest and the subnormal @@ -373,7 +379,7 @@ char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec, bf_flags_t flags); /* modulo 2^n instead of saturation. NaN and infinity return 0 */ -#define BF_GET_INT_MOD (1 << 0) +#define BF_GET_INT_MOD (1 << 0) int bf_get_int32(int *pres, const bf_t *a, int flags); int bf_get_int64(int64_t *pres, const bf_t *a, int flags); int bf_get_uint64(uint64_t *pres, const bf_t *a); @@ -387,10 +393,10 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags); int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k); slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, int is_ceil1); -int mp_mul(bf_context_t *s, limb_t *result, - const limb_t *op1, limb_t op1_size, +int mp_mul(bf_context_t *s, limb_t *result, + const limb_t *op1, limb_t op1_size, const limb_t *op2, limb_t op2_size); -limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, +limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, limb_t n, limb_t carry); limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n); int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n); @@ -532,4 +538,8 @@ static inline int bfdec_resize(bfdec_t *r, limb_t len) } int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags); +#ifdef __cplusplus +} /* extern "C" { */ +#endif + #endif /* LIBBF_H */ diff --git a/libregexp-opcode.h b/libregexp-opcode.h index 189d121..5c1714a 100644 --- a/libregexp-opcode.h +++ b/libregexp-opcode.h @@ -1,6 +1,6 @@ /* * Regular Expression Engine - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,7 +25,8 @@ #ifdef DEF DEF(invalid, 1) /* never used */ -DEF(char, 3) +DEF(char8, 2) /* 7 bits in fact */ +DEF(char16, 3) DEF(char32, 5) DEF(dot, 1) DEF(any, 1) /* same as dot but match any character including line terminator */ diff --git a/libregexp.c b/libregexp.c index b6af454..b4b0e0c 100644 --- a/libregexp.c +++ b/libregexp.c @@ -1,6 +1,6 @@ /* * Regular Expression Engine - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -60,13 +60,15 @@ 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_utf16; + BOOL is_unicode; + BOOL unicode_sets; BOOL ignore_case; BOOL dotall; int capture_count; @@ -98,12 +100,13 @@ static const REOpCode reopcode_info[REOP_COUNT] = { }; #define RE_HEADER_FLAGS 0 -#define RE_HEADER_CAPTURE_COUNT 1 -#define RE_HEADER_STACK_SIZE 2 +#define RE_HEADER_CAPTURE_COUNT 2 +#define RE_HEADER_STACK_SIZE 3 +#define RE_HEADER_BYTECODE_LEN 4 -#define RE_HEADER_LEN 7 +#define RE_HEADER_LEN 8 -static inline int is_digit(int c) { +static inline int lre_is_digit(int c) { return c >= '0' && c <= '9'; } @@ -196,7 +199,7 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c) BOOL invert; const uint16_t *c_pt; int len, i; - + invert = c & 1; c_pt = char_range_table[c >> 1]; len = *c_pt++; @@ -221,19 +224,19 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, { int pos, len, opcode, bc_len, re_flags, i; uint32_t val; - + assert(buf_len >= RE_HEADER_LEN); - re_flags= buf[0]; - bc_len = get_u32(buf + 3); + re_flags = lre_get_flags(buf); + bc_len = get_u32(buf + RE_HEADER_BYTECODE_LEN); assert(bc_len + RE_HEADER_LEN <= buf_len); printf("flags: 0x%x capture_count=%d stack_size=%d\n", - re_flags, buf[1], buf[2]); + re_flags, buf[RE_HEADER_CAPTURE_COUNT], buf[RE_HEADER_STACK_SIZE]); if (re_flags & LRE_FLAG_NAMED_GROUPS) { const char *p; p = (char *)buf + RE_HEADER_LEN + bc_len; printf("named groups: "); - for(i = 1; i < buf[1]; i++) { + for(i = 1; i < buf[RE_HEADER_CAPTURE_COUNT]; i++) { if (i != 1) printf(","); printf("<%s>", p); @@ -260,15 +263,15 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, } printf("%s", reopcode_info[opcode].name); switch(opcode) { - case REOP_char: + case REOP_char8: + val = get_u8(buf + pos + 1); + goto printchar; + case REOP_char16: val = get_u16(buf + pos + 1); - if (val >= ' ' && val <= 126) - printf(" '%c'", val); - else - printf(" 0x%04x", val); - break; + goto printchar; case REOP_char32: val = get_u32(buf + pos + 1); + printchar: if (val >= ' ' && val <= 126) printf(" '%c'", val); else @@ -392,7 +395,7 @@ static int parse_digits(const uint8_t **pp, BOOL allow_overflow) const uint8_t *p; uint64_t v; int c; - + p = *pp; v = 0; for(;;) { @@ -464,7 +467,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) { int h, n, i; uint32_t c1; - + if (*p == '{' && allow_utf16) { p++; c = 0; @@ -494,7 +497,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) } c = (c << 4) | h; } - if (c >= 0xd800 && c < 0xdc00 && + if (is_hi_surrogate(c) && allow_utf16 == 2 && p[0] == '\\' && p[1] == 'u') { /* convert an escaped surrogate pair into a unicode char */ @@ -505,9 +508,9 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) break; c1 = (c1 << 4) | h; } - if (i == 4 && c1 >= 0xdc00 && c1 < 0xe000) { + if (i == 4 && is_lo_surrogate(c1)) { p += 6; - c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; + c = from_surrogate(c, c1); } } } @@ -518,7 +521,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 || is_digit(*p)) + if (c != 0 || lre_is_digit(*p)) return -1; } else { /* parse a legacy octal sequence */ @@ -544,7 +547,6 @@ 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) { @@ -647,7 +649,6 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, out_of_memory: return re_parse_out_of_memory(s); } -#endif /* CONFIG_ALL_UNICODE */ /* return -1 if error otherwise the character or a class range (CLASS_RANGE_BASE). In case of class range, 'cr' is @@ -655,10 +656,10 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, static int get_class_atom(REParseState *s, CharRange *cr, const uint8_t **pp, BOOL inclass) { - const uint8_t *p; + const uint8_t *p, *p_next; uint32_t c; int ret; - + p = *pp; c = *p; @@ -696,10 +697,10 @@ static int get_class_atom(REParseState *s, CharRange *cr, if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (((c >= '0' && c <= '9') || c == '_') && - inclass && !s->is_utf16)) { /* Annex B.1.4 */ + inclass && !s->is_unicode)) { /* Annex B.1.4 */ c &= 0x1f; p++; - } else if (s->is_utf16) { + } else if (s->is_unicode) { goto invalid_escape; } else { /* otherwise return '\' and 'c' */ @@ -707,27 +708,28 @@ static int get_class_atom(REParseState *s, CharRange *cr, c = '\\'; } break; -#ifdef CONFIG_ALL_UNICODE case 'p': case 'P': - if (s->is_utf16) { + if (s->is_unicode) { if (parse_unicode_property(s, cr, &p, (c == 'P'))) return -1; c = CLASS_RANGE_BASE; break; } /* fall thru */ -#endif default: p--; - ret = lre_parse_escape(&p, s->is_utf16 * 2); + 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_utf16) { + } else if (s->is_unicode) { + // special case: allowed inside [] but not outside + if (ret == -2 && *p == '-' && inclass) + goto normal_char; invalid_escape: return re_parse_error(s, "invalid escape sequence in regular expression"); } else { @@ -746,15 +748,18 @@ static int get_class_atom(REParseState *s, CharRange *cr, /* fall thru */ default: normal_char: - /* normal char */ - if (c >= 128) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); - if ((unsigned)c > 0xffff && !s->is_utf16) { - /* XXX: should handle non BMP-1 code points */ + 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 return re_parse_error(s, "malformed unicode char"); } - } else { - p++; } break; } @@ -766,7 +771,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) { int len, i; uint32_t high; - + len = (unsigned)cr->len / 2; if (len >= 65535) return re_parse_error(s, "too many ranges"); @@ -800,6 +805,8 @@ 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) { const uint8_t *p; @@ -807,25 +814,51 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) CharRange cr_s, *cr = &cr_s; CharRange cr1_s, *cr1 = &cr1_s; BOOL invert; - + cr_init(cr, s->opaque, lre_realloc); 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; if (*p == '^') { p++; invert = 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_utf16) { + if (s->is_unicode) { cr_free(cr1); goto invalid_class_range; } @@ -837,7 +870,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) goto fail; if (c2 >= CLASS_RANGE_BASE) { cr_free(cr1); - if (s->is_utf16) { + if (s->is_unicode) { goto invalid_class_range; } /* Annex B: match '-' character */ @@ -866,7 +899,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) } } if (s->ignore_case) { - if (cr_regexp_canonicalize(cr, s->is_utf16)) + if (cr_regexp_canonicalize(cr, s->is_unicode)) goto memory_error; } if (invert) { @@ -895,9 +928,10 @@ static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) int pos, opcode, len; uint32_t val; BOOL ret; - + ret = TRUE; pos = 0; + while (pos < bc_buf_len) { opcode = bc_buf[pos]; len = reopcode_info[opcode].size; @@ -910,8 +944,9 @@ static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) val = get_u16(bc_buf + pos + 1); len += val * 8; goto simple_char; - case REOP_char: case REOP_char32: + case REOP_char16: + case REOP_char8: case REOP_dot: case REOP_any: simple_char: @@ -948,7 +983,7 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) { int pos, opcode, len, count; uint32_t val; - + count = 0; pos = 0; while (pos < bc_buf_len) { @@ -963,8 +998,9 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) val = get_u16(bc_buf + pos + 1); len += val * 8; goto simple_char; - case REOP_char: case REOP_char32: + case REOP_char16: + case REOP_char8: case REOP_dot: case REOP_any: simple_char: @@ -986,35 +1022,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, *p1; + const uint8_t *p, *p_next; 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 >= 128) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); - if (c >= 0xD800 && c <= 0xDBFF) { - d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); - if (d >= 0xDC00 && d <= 0xDFFF) { - c = 0x10000 + 0x400 * (c - 0xD800) + (d - 0xDC00); - p = p1; + } else if (c >= 0x80) { + c = utf8_decode(p - 1, &p_next); + if (p_next == p) + return -1; + p = p_next; + if (is_hi_surrogate(c)) { + d = utf8_decode(p, &p_next); + if (is_lo_surrogate(d)) { + c = from_surrogate(c, d); + p = p_next; } } - } else { - p++; } - if (c > 0x10FFFF) - return -1; if (q == buf) { if (!lre_js_is_ident_first(c)) return -1; @@ -1024,16 +1060,15 @@ 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 < 128) { + if (c < 0x80) { *q++ = c; } else { - q += unicode_to_utf8((uint8_t*)q, c); + q += utf8_encode((uint8_t*)q, c); } } if (q == buf) return -1; *q = '\0'; - p++; *pp = p; return 0; } @@ -1113,10 +1148,11 @@ static int find_group_name(REParseState *s, const char *name) const char *p, *buf_end; size_t len, name_len; int capture_index; - - name_len = strlen(name); + p = (char *)s->group_names.buf; + if (!p) return -1; buf_end = (char *)s->group_names.buf + s->group_names.size; + name_len = strlen(name); capture_index = 1; while (p < buf_end) { len = strlen(p); @@ -1136,7 +1172,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) 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; - + last_atom_start = -1; last_capture_count = 0; p = s->buf_ptr; @@ -1161,9 +1197,9 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) re_emit_op(s, REOP_prev); break; case '{': - if (s->is_utf16) { + if (s->is_unicode) { return re_parse_error(s, "syntax error"); - } else if (!is_digit(p[1])) { + } else if (!lre_is_digit(p[1])) { /* Annex B: we accept '{' not followed by digits as a normal atom */ goto parse_class_atom; @@ -1173,7 +1209,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) parse_digits(&p1, TRUE); if (*p1 == ',') { p1++; - if (is_digit(*p1)) { + if (lre_is_digit(*p1)) { parse_digits(&p1, TRUE); } } @@ -1213,7 +1249,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) lookahead: /* Annex B allows lookahead to be used as an atom for the quantifiers */ - if (!s->is_utf16 && !is_backward_lookahead) { + if (!s->is_unicode && !is_backward_lookahead) { last_atom_start = s->byte_code.size; last_capture_count = s->capture_count; } @@ -1259,15 +1295,15 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) capture_index = s->capture_count++; re_emit_op_u8(s, REOP_save_start + is_backward_dir, capture_index); - + s->buf_ptr = p; if (re_parse_disjunction(s, is_backward_dir)) return -1; p = s->buf_ptr; - + re_emit_op_u8(s, REOP_save_start + 1 - is_backward_dir, capture_index); - + if (re_parse_expect(s, &p, ')')) return -1; } @@ -1283,13 +1319,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) { const uint8_t *p1; int dummy_res; - + p1 = p; if (p1[2] != '<') { /* annex B: we tolerate invalid group names in non unicode mode if there is no named capture definition */ - if (s->is_utf16 || re_has_named_captures(s)) + if (s->is_unicode || re_has_named_captures(s)) return re_parse_error(s, "expecting group name"); else goto parse_class_atom; @@ -1297,7 +1333,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) p1 += 3; if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf), &p1)) { - if (s->is_utf16 || re_has_named_captures(s)) + if (s->is_unicode || re_has_named_captures(s)) return re_parse_error(s, "invalid group name"); else goto parse_class_atom; @@ -1308,7 +1344,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) after (inefficient, but hopefully not common */ c = re_parse_captures(s, &dummy_res, s->u.tmp_buf); if (c < 0) { - if (s->is_utf16 || re_has_named_captures(s)) + if (s->is_unicode || re_has_named_captures(s)) return re_parse_error(s, "group name not defined"); else goto parse_class_atom; @@ -1320,8 +1356,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) case '0': p += 2; c = 0; - if (s->is_utf16) { - if (is_digit(*p)) { + if (s->is_unicode) { + if (lre_is_digit(*p)) { return re_parse_error(s, "invalid decimal escape in regular expression"); } } else { @@ -1336,13 +1372,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) goto normal_char; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': - case '9': + case '9': { const uint8_t *q = ++p; - + c = parse_digits(&p, FALSE); if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) { - if (!s->is_utf16) { + if (!s->is_unicode) { /* Annex B.1.4: accept legacy octal */ p = q; if (*p <= '7') { @@ -1384,7 +1420,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) break; case ']': case '}': - if (s->is_utf16) + if (s->is_unicode) return re_parse_error(s, "syntax error"); goto parse_class_atom; default: @@ -1406,9 +1442,11 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) return -1; } else { if (s->ignore_case) - c = lre_canonicalize(c, s->is_utf16); - if (c <= 0xffff) - re_emit_op_u16(s, REOP_char, c); + 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); } @@ -1441,8 +1479,8 @@ 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 (!is_digit(p[1])) { - if (s->is_utf16) + if (!lre_is_digit(p[1])) { + if (s->is_unicode) goto invalid_quant_count; break; } @@ -1451,7 +1489,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) quant_max = quant_min; if (*p == ',') { p++; - if (is_digit(*p)) { + if (lre_is_digit(*p)) { quant_max = parse_digits(&p, TRUE); if (quant_max < quant_min) { invalid_quant_count: @@ -1461,7 +1499,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) quant_max = INT32_MAX; /* infinity */ } } - if (*p != '}' && !s->is_utf16) { + if (*p != '}' && !s->is_unicode) { /* Annex B: normal atom if invalid '{' syntax */ p = p1; break; @@ -1480,7 +1518,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) } if (greedy) { int len, pos; - + if (quant_max > 0) { /* specific optimization for simple quantifiers */ if (dbuf_error(&s->byte_code)) @@ -1489,7 +1527,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) s->byte_code.size - last_atom_start); if (len > 0) { re_emit_op(s, REOP_match); - + if (dbuf_insert(&s->byte_code, last_atom_start, 17)) goto out_of_memory; pos = last_atom_start; @@ -1506,19 +1544,17 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) goto done; } } - + if (dbuf_error(&s->byte_code)) goto out_of_memory; - /* the spec tells that if there is no advance when - running the atom after the first quant_min times, - then there is no match. We remove this test when we - are sure the atom always advances the position. */ - add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start, - s->byte_code.size - last_atom_start); - } else { - add_zero_advance_check = FALSE; } - + /* the spec tells that if there is no advance when + running the atom after the first quant_min times, + then there is no match. We remove this test when we + are sure the atom always advances the position. */ + add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start, + s->byte_code.size - last_atom_start); + { int len, pos; len = s->byte_code.size - last_atom_start; @@ -1544,7 +1580,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) len + 5 * has_goto + add_zero_advance_check * 2); if (add_zero_advance_check) { s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos; - re_emit_op(s, REOP_check_advance); + re_emit_op(s, REOP_check_advance); } if (has_goto) re_emit_goto(s, REOP_goto, last_atom_start); @@ -1655,14 +1691,14 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir) } return 0; } - + static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) { int start, len, pos; if (lre_check_stack_overflow(s->opaque, 0)) return re_parse_error(s, "stack overflow"); - + start = s->byte_code.size; if (re_parse_alternative(s, is_backward_dir)) return -1; @@ -1682,7 +1718,7 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) if (re_parse_alternative(s, is_backward_dir)) return -1; - + /* patch the goto */ len = s->byte_code.size - (pos + 4); put_u32(s->byte_code.buf + pos, len); @@ -1691,11 +1727,11 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) } /* the control flow is recursive so the analysis can be linear */ -static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) +static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) { int stack_size, stack_size_max, pos, opcode, len; uint32_t val; - + stack_size = 0; stack_size_max = 0; bc_buf += RE_HEADER_LEN; @@ -1746,29 +1782,30 @@ 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; - + memset(s, 0, sizeof(*s)); s->opaque = opaque; s->buf_ptr = (const uint8_t *)buf; s->buf_end = s->buf_ptr + buf_len; s->buf_start = s->buf_ptr; s->re_flags = re_flags; - s->is_utf16 = ((re_flags & LRE_FLAG_UTF16) != 0); + s->is_unicode = ((re_flags & LRE_FLAG_UNICODE) != 0); is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0); s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 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->group_names, opaque, lre_realloc); - dbuf_putc(&s->byte_code, re_flags); /* first element is the flags */ + dbuf_put_u16(&s->byte_code, re_flags); /* first element is the flags */ dbuf_putc(&s->byte_code, 0); /* second element is the number of captures */ dbuf_putc(&s->byte_code, 0); /* stack size */ dbuf_put_u32(&s->byte_code, 0); /* bytecode length */ - + if (!is_sticky) { /* iterate thru all positions (about the same as .*?( ... ) ) . We do it without an explicit loop so that lock step @@ -1784,13 +1821,13 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, error: dbuf_free(&s->byte_code); dbuf_free(&s->group_names); - pstrcpy(error_msg, error_msg_size, s->u.error_msg); + js__pstrcpy(error_msg, error_msg_size, s->u.error_msg); *plen = 0; return NULL; } re_emit_op_u8(s, REOP_save_end, 0); - + re_emit_op(s, REOP_match); if (*s->buf_ptr != '\0') { @@ -1802,28 +1839,30 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, re_parse_out_of_memory(s); goto error; } - - stack_size = compute_stack_size(s->byte_code.buf, s->byte_code.size); + + stack_size = lre_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; } - + s->byte_code.buf[RE_HEADER_CAPTURE_COUNT] = s->capture_count; s->byte_code.buf[RE_HEADER_STACK_SIZE] = stack_size; - put_u32(s->byte_code.buf + 3, s->byte_code.size - RE_HEADER_LEN); + put_u32(s->byte_code.buf + RE_HEADER_BYTECODE_LEN, + s->byte_code.size - RE_HEADER_LEN); /* add the named groups if needed */ if (s->group_names.size > (s->capture_count - 1)) { dbuf_put(&s->byte_code, s->group_names.buf, s->group_names.size); - s->byte_code.buf[RE_HEADER_FLAGS] |= LRE_FLAG_NAMED_GROUPS; + put_u16(s->byte_code.buf + RE_HEADER_FLAGS, + LRE_FLAG_NAMED_GROUPS | lre_get_flags(s->byte_code.buf)); } dbuf_free(&s->group_names); - + #ifdef DUMP_REOP lre_dump_bytecode(s->byte_code.buf, s->byte_code.size); #endif - + error_msg[0] = '\0'; *plen = s->byte_code.size; return s->byte_code.buf; @@ -1842,93 +1881,86 @@ static BOOL is_word_char(uint32_t c) (c == '_')); } -#define GET_CHAR(c, cptr, cbuf_end) \ +#define GET_CHAR(c, cptr, cbuf_end, cbuf_type) \ do { \ if (cbuf_type == 0) { \ c = *cptr++; \ } else { \ - uint32_t __c1; \ - c = *(uint16_t *)cptr; \ - cptr += 2; \ - if (c >= 0xd800 && c < 0xdc00 && \ - cbuf_type == 2 && cptr < cbuf_end) { \ - __c1 = *(uint16_t *)cptr; \ - if (__c1 >= 0xdc00 && __c1 < 0xe000) { \ - c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \ - cptr += 2; \ - } \ - } \ + 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++); \ + cptr = (const void *)_p; \ } \ } while (0) -#define PEEK_CHAR(c, cptr, cbuf_end) \ - do { \ - if (cbuf_type == 0) { \ - c = cptr[0]; \ - } else { \ - uint32_t __c1; \ - c = ((uint16_t *)cptr)[0]; \ - if (c >= 0xd800 && c < 0xdc00 && \ - cbuf_type == 2 && (cptr + 2) < cbuf_end) { \ - __c1 = ((uint16_t *)cptr)[1]; \ - if (__c1 >= 0xdc00 && __c1 < 0xe000) { \ - c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \ - } \ - } \ - } \ - } while (0) - -#define PEEK_PREV_CHAR(c, cptr, cbuf_start) \ - do { \ - if (cbuf_type == 0) { \ - c = cptr[-1]; \ - } else { \ - uint32_t __c1; \ - c = ((uint16_t *)cptr)[-1]; \ - if (c >= 0xdc00 && c < 0xe000 && \ - cbuf_type == 2 && (cptr - 4) >= cbuf_start) { \ - __c1 = ((uint16_t *)cptr)[-2]; \ - if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \ - c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \ - } \ - } \ +#define PEEK_CHAR(c, cptr, cbuf_end, cbuf_type) \ + do { \ + if (cbuf_type == 0) { \ + c = cptr[0]; \ + } else { \ + 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); \ } \ } while (0) -#define GET_PREV_CHAR(c, cptr, cbuf_start) \ - do { \ - if (cbuf_type == 0) { \ - cptr--; \ - c = cptr[0]; \ - } else { \ - uint32_t __c1; \ - cptr -= 2; \ - c = ((uint16_t *)cptr)[0]; \ - if (c >= 0xdc00 && c < 0xe000 && \ - cbuf_type == 2 && cptr > cbuf_start) { \ - __c1 = ((uint16_t *)cptr)[-1]; \ - if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \ - cptr -= 2; \ - c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \ - } \ - } \ +#define PEEK_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \ + do { \ + if (cbuf_type == 0) { \ + c = cptr[-1]; \ + } else { \ + 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); \ } \ } while (0) -#define PREV_CHAR(cptr, cbuf_start) \ - do { \ - if (cbuf_type == 0) { \ - cptr--; \ - } else { \ - cptr -= 2; \ - if (cbuf_type == 2) { \ - c = ((uint16_t *)cptr)[0]; \ - if (c >= 0xdc00 && c < 0xe000 && cptr > cbuf_start) { \ - c = ((uint16_t *)cptr)[-1]; \ - if (c >= 0xd800 && c < 0xdc00) \ - cptr -= 2; \ - } \ - } \ +#define GET_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \ + do { \ + if (cbuf_type == 0) { \ + cptr--; \ + c = cptr[0]; \ + } else { \ + 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); \ + cptr = (const void *)_p; \ + } \ + } while (0) + +#define PREV_CHAR(cptr, cbuf_start, cbuf_type) \ + do { \ + if (cbuf_type == 0) { \ + cptr--; \ + } 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--; \ + cptr = (const void *)_p; \ } \ } while (0) @@ -1947,19 +1979,19 @@ typedef struct REExecState { size_t count; /* only used for RE_EXEC_STATE_GREEDY_QUANT */ const uint8_t *cptr; const uint8_t *pc; - void *buf[0]; + void *buf[]; } REExecState; typedef struct { const uint8_t *cbuf; const uint8_t *cbuf_end; /* 0 = 8 bit chars, 1 = 16 bit chars, 2 = 16 bit chars, UTF-16 */ - int cbuf_type; + int cbuf_type; int capture_count; int stack_size_max; BOOL multi_line; BOOL ignore_case; - BOOL is_utf16; + BOOL is_unicode; void *opaque; /* used for stack overflow check */ size_t state_size; @@ -2016,7 +2048,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, int cbuf_type; uint32_t val, c; const uint8_t *cbuf_end; - + cbuf_type = s->cbuf_type; cbuf_end = s->cbuf_end; @@ -2068,7 +2100,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, /* go backward */ char_count = get_u32(pc + 12); for(i = 0; i < char_count; i++) { - PREV_CHAR(cptr, s->cbuf); + PREV_CHAR(cptr, s->cbuf, cbuf_type); } pc = (pc + 16) + (int)get_u32(pc); rs->cptr = cptr; @@ -2097,15 +2129,19 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, val = get_u32(pc); pc += 4; goto test_char; - case REOP_char: + case REOP_char16: 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); + GET_CHAR(c, cptr, cbuf_end, cbuf_type); if (s->ignore_case) { - c = lre_canonicalize(c, s->is_utf16); + c = lre_canonicalize(c, s->is_unicode); } if (val != c) goto no_match; @@ -2114,7 +2150,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, case REOP_split_next_first: { const uint8_t *pc1; - + val = get_u32(pc); pc += 4; if (opcode == REOP_split_next_first) { @@ -2140,7 +2176,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (ret < 0) return -1; break; - + case REOP_goto: val = get_u32(pc); pc += 4 + (int)val; @@ -2150,7 +2186,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, break; if (!s->multi_line) goto no_match; - PEEK_PREV_CHAR(c, cptr, s->cbuf); + PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); if (!is_line_terminator(c)) goto no_match; break; @@ -2159,21 +2195,21 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, break; if (!s->multi_line) goto no_match; - PEEK_CHAR(c, cptr, cbuf_end); + PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); if (!is_line_terminator(c)) goto no_match; break; case REOP_dot: if (cptr == cbuf_end) goto no_match; - GET_CHAR(c, cptr, cbuf_end); + GET_CHAR(c, cptr, cbuf_end, cbuf_type); if (is_line_terminator(c)) goto no_match; break; case REOP_any: if (cptr == cbuf_end) goto no_match; - GET_CHAR(c, cptr, cbuf_end); + GET_CHAR(c, cptr, cbuf_end, cbuf_type); break; case REOP_save_start: case REOP_save_end: @@ -2225,14 +2261,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (cptr == s->cbuf) { v1 = FALSE; } else { - PEEK_PREV_CHAR(c, cptr, s->cbuf); + PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); v1 = is_word_char(c); } /* current char */ if (cptr >= cbuf_end) { v2 = FALSE; } else { - PEEK_CHAR(c, cptr, cbuf_end); + PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); v2 = is_word_char(c); } if (v1 ^ v2 ^ (REOP_not_word_boundary - opcode)) @@ -2244,7 +2280,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { const uint8_t *cptr1, *cptr1_end, *cptr1_start; uint32_t c1, c2; - + val = *pc++; if (val >= s->capture_count) goto no_match; @@ -2257,11 +2293,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, while (cptr1 < cptr1_end) { if (cptr >= cbuf_end) goto no_match; - GET_CHAR(c1, cptr1, cptr1_end); - GET_CHAR(c2, cptr, cbuf_end); + GET_CHAR(c1, cptr1, cptr1_end, cbuf_type); + GET_CHAR(c2, cptr, cbuf_end, cbuf_type); if (s->ignore_case) { - c1 = lre_canonicalize(c1, s->is_utf16); - c2 = lre_canonicalize(c2, s->is_utf16); + c1 = lre_canonicalize(c1, s->is_unicode); + c2 = lre_canonicalize(c2, s->is_unicode); } if (c1 != c2) goto no_match; @@ -2271,11 +2307,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, while (cptr1 > cptr1_start) { if (cptr == s->cbuf) goto no_match; - GET_PREV_CHAR(c1, cptr1, cptr1_start); - GET_PREV_CHAR(c2, cptr, s->cbuf); + GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type); + GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type); if (s->ignore_case) { - c1 = lre_canonicalize(c1, s->is_utf16); - c2 = lre_canonicalize(c2, s->is_utf16); + c1 = lre_canonicalize(c1, s->is_unicode); + c2 = lre_canonicalize(c2, s->is_unicode); } if (c1 != c2) goto no_match; @@ -2287,14 +2323,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { int n; uint32_t low, high, idx_min, idx_max, idx; - + n = get_u16(pc); /* n must be >= 1 */ pc += 2; if (cptr >= cbuf_end) goto no_match; - GET_CHAR(c, cptr, cbuf_end); + GET_CHAR(c, cptr, cbuf_end, cbuf_type); if (s->ignore_case) { - c = lre_canonicalize(c, s->is_utf16); + c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; low = get_u16(pc + 0 * 4); @@ -2327,14 +2363,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { int n; uint32_t low, high, idx_min, idx_max, idx; - + n = get_u16(pc); /* n must be >= 1 */ pc += 2; if (cptr >= cbuf_end) goto no_match; - GET_CHAR(c, cptr, cbuf_end); + GET_CHAR(c, cptr, cbuf_end, cbuf_type); if (s->ignore_case) { - c = lre_canonicalize(c, s->is_utf16); + c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; low = get_u32(pc + 0 * 8); @@ -2364,7 +2400,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, /* go to the previous char */ if (cptr == s->cbuf) goto no_match; - PREV_CHAR(cptr, s->cbuf); + PREV_CHAR(cptr, s->cbuf, cbuf_type); break; case REOP_simple_greedy_quant: { @@ -2372,14 +2408,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, size_t q; intptr_t res; const uint8_t *pc1; - + next_pos = get_u32(pc); quant_min = get_u32(pc + 4); quant_max = get_u32(pc + 8); pc += 16; pc1 = pc; pc += (int)next_pos; - + q = 0; for(;;) { res = lre_exec_backtrack(s, capture, stack, stack_len, @@ -2422,17 +2458,17 @@ int lre_exec(uint8_t **capture, REExecContext s_s, *s = &s_s; int re_flags, i, alloca_size, ret; StackInt *stack_buf; - - re_flags = bc_buf[RE_HEADER_FLAGS]; + + 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_utf16 = (re_flags & LRE_FLAG_UTF16) != 0; + s->is_unicode = (re_flags & LRE_FLAG_UNICODE) != 0; s->capture_count = bc_buf[RE_HEADER_CAPTURE_COUNT]; s->stack_size_max = bc_buf[RE_HEADER_STACK_SIZE]; s->cbuf = cbuf; s->cbuf_end = cbuf + (clen << cbuf_type); s->cbuf_type = cbuf_type; - if (s->cbuf_type == 1 && s->is_utf16) + if (s->cbuf_type == 1 && s->is_unicode) s->cbuf_type = 2; s->opaque = opaque; @@ -2442,7 +2478,7 @@ int lre_exec(uint8_t **capture, s->state_stack = NULL; s->state_stack_len = 0; s->state_stack_size = 0; - + for(i = 0; i < s->capture_count * 2; i++) capture[i] = NULL; alloca_size = s->stack_size_max * sizeof(stack_buf[0]); @@ -2460,7 +2496,7 @@ int lre_get_capture_count(const uint8_t *bc_buf) int lre_get_flags(const uint8_t *bc_buf) { - return bc_buf[RE_HEADER_FLAGS]; + return get_u16(bc_buf + RE_HEADER_FLAGS); } /* Return NULL if no group names. Otherwise, return a pointer to @@ -2470,8 +2506,82 @@ const char *lre_get_groupnames(const uint8_t *bc_buf) uint32_t re_bytecode_len; if ((lre_get_flags(bc_buf) & LRE_FLAG_NAMED_GROUPS) == 0) return NULL; - re_bytecode_len = get_u32(bc_buf + 3); - return (const char *)(bc_buf + 7 + re_bytecode_len); + re_bytecode_len = get_u32(bc_buf + RE_HEADER_BYTECODE_LEN); + 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 @@ -2488,27 +2598,28 @@ void *lre_realloc(void *opaque, void *ptr, size_t size) int main(int argc, char **argv) { - int len, ret, i; + int len, flags, ret, i; uint8_t *bc; char error_msg[64]; uint8_t *capture[CAPTURE_COUNT_MAX * 2]; const char *input; int input_len, capture_count; - - if (argc < 3) { - printf("usage: %s regexp input\n", argv[0]); + + if (argc < 4) { + printf("usage: %s regexp flags input\n", argv[0]); exit(1); } + flags = atoi(argv[2]); bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1], - strlen(argv[1]), 0, NULL); + strlen(argv[1]), flags, NULL); if (!bc) { fprintf(stderr, "error: %s\n", error_msg); exit(1); } - input = argv[2]; + input = argv[3]; input_len = strlen(input); - + ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL); printf("ret=%d\n", ret); if (ret == 1) { diff --git a/libregexp.h b/libregexp.h index c0bc58d..c2e664a 100644 --- a/libregexp.h +++ b/libregexp.h @@ -1,6 +1,6 @@ /* * Regular Expression Engine - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -28,17 +28,21 @@ #include "libunicode.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LRE_BOOL int /* for documentation purposes */ #define LRE_FLAG_GLOBAL (1 << 0) #define LRE_FLAG_IGNORECASE (1 << 1) #define LRE_FLAG_MULTILINE (1 << 2) #define LRE_FLAG_DOTALL (1 << 3) -#define LRE_FLAG_UTF16 (1 << 4) +#define LRE_FLAG_UNICODE (1 << 4) #define LRE_FLAG_STICKY (1 << 5) #define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */ - #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ +#define LRE_FLAG_UNICODE_SETS (1 << 8) uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, const char *buf, size_t buf_len, int re_flags, @@ -53,8 +57,10 @@ int lre_exec(uint8_t **capture, int lre_parse_escape(const uint8_t **pp, int allow_utf16); LRE_BOOL lre_is_space(int c); +void lre_byte_swap(uint8_t *buf, size_t len, LRE_BOOL is_byte_swapped); + /* must be provided by the user */ -LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); +LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); void *lre_realloc(void *opaque, void *ptr, size_t size); /* JS identifier test */ @@ -66,11 +72,7 @@ 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 { -#ifdef CONFIG_ALL_UNICODE return lre_is_id_start(c); -#else - return !lre_is_space(c); -#endif } } @@ -80,14 +82,14 @@ static inline int lre_js_is_ident_next(int c) return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; } else { /* ZWNJ and ZWJ are accepted in identifiers */ -#ifdef CONFIG_ALL_UNICODE return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; -#else - return !lre_is_space(c) || c == 0x200C || c == 0x200D; -#endif } } #undef LRE_BOOL +#ifdef __cplusplus +} /* extern "C" { */ +#endif + #endif /* LIBREGEXP_H */ diff --git a/libunicode-table.h b/libunicode-table.h index 513ed94..b48a3a7 100644 --- a/libunicode-table.h +++ b/libunicode-table.h @@ -3,7 +3,7 @@ #include -static const uint32_t case_conv_table1[370] = { +static const uint32_t case_conv_table1[378] = { 0x00209a30, 0x00309a00, 0x005a8173, 0x00601730, 0x006c0730, 0x006f81b3, 0x00701700, 0x007c0700, 0x007f8100, 0x00803040, 0x009801c3, 0x00988190, @@ -13,140 +13,143 @@ static const uint32_t case_conv_table1[370] = { 0x00c48230, 0x00c58240, 0x00c70130, 0x00c78130, 0x00c80130, 0x00c88240, 0x00c98130, 0x00ca0130, 0x00ca8100, 0x00cb0130, 0x00cb8130, 0x00cc0240, - 0x00cd0100, 0x00ce0130, 0x00ce8130, 0x00cf0100, - 0x00cf8130, 0x00d00640, 0x00d30130, 0x00d38240, - 0x00d48130, 0x00d60240, 0x00d70130, 0x00d78240, - 0x00d88230, 0x00d98440, 0x00db8130, 0x00dc0240, - 0x00de0240, 0x00df8100, 0x00e20350, 0x00e38350, - 0x00e50350, 0x00e69040, 0x00ee8100, 0x00ef1240, - 0x00f801b4, 0x00f88350, 0x00fa0240, 0x00fb0130, - 0x00fb8130, 0x00fc2840, 0x01100130, 0x01111240, - 0x011d0131, 0x011d8240, 0x011e8130, 0x011f0131, - 0x011f8201, 0x01208240, 0x01218130, 0x01220130, - 0x01228130, 0x01230a40, 0x01280101, 0x01288101, - 0x01290101, 0x01298100, 0x012a0100, 0x012b0200, - 0x012c8100, 0x012d8100, 0x012e0101, 0x01300100, - 0x01308101, 0x01318100, 0x01328101, 0x01330101, - 0x01340100, 0x01348100, 0x01350101, 0x01358101, - 0x01360101, 0x01378100, 0x01388101, 0x01390100, - 0x013a8100, 0x013e8101, 0x01400100, 0x01410101, - 0x01418100, 0x01438101, 0x01440100, 0x01448100, - 0x01450200, 0x01460100, 0x01490100, 0x014e8101, - 0x014f0101, 0x01a28173, 0x01b80440, 0x01bb0240, - 0x01bd8300, 0x01bf8130, 0x01c30130, 0x01c40330, - 0x01c60130, 0x01c70230, 0x01c801d0, 0x01c89130, - 0x01d18930, 0x01d60100, 0x01d68300, 0x01d801d3, - 0x01d89100, 0x01e10173, 0x01e18900, 0x01e60100, - 0x01e68200, 0x01e78130, 0x01e80173, 0x01e88173, - 0x01ea8173, 0x01eb0173, 0x01eb8100, 0x01ec1840, - 0x01f80173, 0x01f88173, 0x01f90100, 0x01f98100, - 0x01fa01a0, 0x01fa8173, 0x01fb8240, 0x01fc8130, - 0x01fd0240, 0x01fe8330, 0x02001030, 0x02082030, - 0x02182000, 0x02281000, 0x02302240, 0x02453640, - 0x02600130, 0x02608e40, 0x02678100, 0x02686040, - 0x0298a630, 0x02b0a600, 0x02c381b5, 0x08502631, - 0x08638131, 0x08668131, 0x08682b00, 0x087e8300, - 0x09d05011, 0x09f80610, 0x09fc0620, 0x0e400174, - 0x0e408174, 0x0e410174, 0x0e418174, 0x0e420174, - 0x0e428174, 0x0e430174, 0x0e438180, 0x0e440180, - 0x0e482b30, 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, - 0x0ec70101, 0x0f007e40, 0x0f3f1840, 0x0f4b01b5, - 0x0f4b81b6, 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7, - 0x0f4d8180, 0x0f4f0130, 0x0f506040, 0x0f800800, - 0x0f840830, 0x0f880600, 0x0f8c0630, 0x0f900800, - 0x0f940830, 0x0f980800, 0x0f9c0830, 0x0fa00600, - 0x0fa40630, 0x0fa801b0, 0x0fa88100, 0x0fa901d3, - 0x0fa98100, 0x0faa01d3, 0x0faa8100, 0x0fab01d3, - 0x0fab8100, 0x0fac8130, 0x0fad8130, 0x0fae8130, - 0x0faf8130, 0x0fb00800, 0x0fb40830, 0x0fb80200, - 0x0fb90400, 0x0fbb0200, 0x0fbc0201, 0x0fbd0201, - 0x0fbe0201, 0x0fc008b7, 0x0fc40867, 0x0fc808b8, - 0x0fcc0868, 0x0fd008b8, 0x0fd40868, 0x0fd80200, - 0x0fd901b9, 0x0fd981b1, 0x0fda01b9, 0x0fdb01b1, - 0x0fdb81d7, 0x0fdc0230, 0x0fdd0230, 0x0fde0161, - 0x0fdf0173, 0x0fe101b9, 0x0fe181b2, 0x0fe201ba, - 0x0fe301b2, 0x0fe381d8, 0x0fe40430, 0x0fe60162, - 0x0fe80200, 0x0fe901d0, 0x0fe981d0, 0x0feb01b0, - 0x0feb81d0, 0x0fec0230, 0x0fed0230, 0x0ff00201, - 0x0ff101d3, 0x0ff181d3, 0x0ff201ba, 0x0ff28101, - 0x0ff301b0, 0x0ff381d3, 0x0ff40230, 0x0ff50230, - 0x0ff60131, 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb, - 0x0ffb01b2, 0x0ffb81d9, 0x0ffc0230, 0x0ffd0230, - 0x0ffe0162, 0x109301a0, 0x109501a0, 0x109581a0, - 0x10990131, 0x10a70101, 0x10b01031, 0x10b81001, - 0x10c18240, 0x125b1a31, 0x12681a01, 0x16003031, - 0x16183001, 0x16300240, 0x16310130, 0x16318130, - 0x16320130, 0x16328100, 0x16330100, 0x16338640, - 0x16368130, 0x16370130, 0x16378130, 0x16380130, - 0x16390240, 0x163a8240, 0x163f0230, 0x16406440, - 0x16758440, 0x16790240, 0x16802600, 0x16938100, - 0x16968100, 0x53202e40, 0x53401c40, 0x53910e40, - 0x53993e40, 0x53bc8440, 0x53be8130, 0x53bf0a40, - 0x53c58240, 0x53c68130, 0x53c80440, 0x53ca0101, - 0x53cb1440, 0x53d50130, 0x53d58130, 0x53d60130, - 0x53d68130, 0x53d70130, 0x53d80130, 0x53d88130, - 0x53d90130, 0x53d98131, 0x53da1040, 0x53e20131, - 0x53e28130, 0x53e30130, 0x53e38440, 0x53e80240, - 0x53eb0440, 0x53fa8240, 0x55a98101, 0x55b85020, - 0x7d8001b2, 0x7d8081b2, 0x7d8101b2, 0x7d8181da, - 0x7d8201da, 0x7d8281b3, 0x7d8301b3, 0x7d8981bb, - 0x7d8a01bb, 0x7d8a81bb, 0x7d8b01bc, 0x7d8b81bb, - 0x7f909a31, 0x7fa09a01, 0x82002831, 0x82142801, - 0x82582431, 0x826c2401, 0x82b80b31, 0x82be0f31, - 0x82c60731, 0x82ca0231, 0x82cb8b01, 0x82d18f01, - 0x82d98701, 0x82dd8201, 0x86403331, 0x86603301, + 0x00cd0100, 0x00cd8101, 0x00ce0130, 0x00ce8130, + 0x00cf0100, 0x00cf8130, 0x00d00640, 0x00d30130, + 0x00d38240, 0x00d48130, 0x00d60240, 0x00d70130, + 0x00d78240, 0x00d88230, 0x00d98440, 0x00db8130, + 0x00dc0240, 0x00de0240, 0x00df8100, 0x00e20350, + 0x00e38350, 0x00e50350, 0x00e69040, 0x00ee8100, + 0x00ef1240, 0x00f801b4, 0x00f88350, 0x00fa0240, + 0x00fb0130, 0x00fb8130, 0x00fc2840, 0x01100130, + 0x01111240, 0x011d0131, 0x011d8240, 0x011e8130, + 0x011f0131, 0x011f8201, 0x01208240, 0x01218130, + 0x01220130, 0x01228130, 0x01230a40, 0x01280101, + 0x01288101, 0x01290101, 0x01298100, 0x012a0100, + 0x012b0200, 0x012c8100, 0x012d8100, 0x012e0101, + 0x01300100, 0x01308101, 0x01318100, 0x01320101, + 0x01328101, 0x01330101, 0x01340100, 0x01348100, + 0x01350101, 0x01358101, 0x01360101, 0x01378100, + 0x01388101, 0x01390100, 0x013a8100, 0x013e8101, + 0x01400100, 0x01410101, 0x01418100, 0x01438101, + 0x01440100, 0x01448100, 0x01450200, 0x01460100, + 0x01490100, 0x014e8101, 0x014f0101, 0x01a28173, + 0x01b80440, 0x01bb0240, 0x01bd8300, 0x01bf8130, + 0x01c30130, 0x01c40330, 0x01c60130, 0x01c70230, + 0x01c801d0, 0x01c89130, 0x01d18930, 0x01d60100, + 0x01d68300, 0x01d801d3, 0x01d89100, 0x01e10173, + 0x01e18900, 0x01e60100, 0x01e68200, 0x01e78130, + 0x01e80173, 0x01e88173, 0x01ea8173, 0x01eb0173, + 0x01eb8100, 0x01ec1840, 0x01f80173, 0x01f88173, + 0x01f90100, 0x01f98100, 0x01fa01a0, 0x01fa8173, + 0x01fb8240, 0x01fc8130, 0x01fd0240, 0x01fe8330, + 0x02001030, 0x02082030, 0x02182000, 0x02281000, + 0x02302240, 0x02453640, 0x02600130, 0x02608e40, + 0x02678100, 0x02686040, 0x0298a630, 0x02b0a600, + 0x02c381b5, 0x08502631, 0x08638131, 0x08668131, + 0x08682b00, 0x087e8300, 0x09d05011, 0x09f80610, + 0x09fc0620, 0x0e400174, 0x0e408174, 0x0e410174, + 0x0e418174, 0x0e420174, 0x0e428174, 0x0e430174, + 0x0e438180, 0x0e440180, 0x0e448240, 0x0e482b30, + 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, 0x0ec70101, + 0x0f007e40, 0x0f3f1840, 0x0f4b01b5, 0x0f4b81b6, + 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7, 0x0f4d8180, + 0x0f4f0130, 0x0f506040, 0x0f800800, 0x0f840830, + 0x0f880600, 0x0f8c0630, 0x0f900800, 0x0f940830, + 0x0f980800, 0x0f9c0830, 0x0fa00600, 0x0fa40630, + 0x0fa801b0, 0x0fa88100, 0x0fa901d3, 0x0fa98100, + 0x0faa01d3, 0x0faa8100, 0x0fab01d3, 0x0fab8100, + 0x0fac8130, 0x0fad8130, 0x0fae8130, 0x0faf8130, + 0x0fb00800, 0x0fb40830, 0x0fb80200, 0x0fb90400, + 0x0fbb0201, 0x0fbc0201, 0x0fbd0201, 0x0fbe0201, + 0x0fc008b7, 0x0fc40867, 0x0fc808b8, 0x0fcc0868, + 0x0fd008b8, 0x0fd40868, 0x0fd80200, 0x0fd901b9, + 0x0fd981b1, 0x0fda01b9, 0x0fdb01b1, 0x0fdb81d7, + 0x0fdc0230, 0x0fdd0230, 0x0fde0161, 0x0fdf0173, + 0x0fe101b9, 0x0fe181b2, 0x0fe201ba, 0x0fe301b2, + 0x0fe381d8, 0x0fe40430, 0x0fe60162, 0x0fe80201, + 0x0fe901d0, 0x0fe981d0, 0x0feb01b0, 0x0feb81d0, + 0x0fec0230, 0x0fed0230, 0x0ff00201, 0x0ff101d3, + 0x0ff181d3, 0x0ff201ba, 0x0ff28101, 0x0ff301b0, + 0x0ff381d3, 0x0ff40231, 0x0ff50230, 0x0ff60131, + 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb, 0x0ffb01b2, + 0x0ffb81d9, 0x0ffc0230, 0x0ffd0230, 0x0ffe0162, + 0x109301a0, 0x109501a0, 0x109581a0, 0x10990131, + 0x10a70101, 0x10b01031, 0x10b81001, 0x10c18240, + 0x125b1a31, 0x12681a01, 0x16003031, 0x16183001, + 0x16300240, 0x16310130, 0x16318130, 0x16320130, + 0x16328100, 0x16330100, 0x16338640, 0x16368130, + 0x16370130, 0x16378130, 0x16380130, 0x16390240, + 0x163a8240, 0x163f0230, 0x16406440, 0x16758440, + 0x16790240, 0x16802600, 0x16938100, 0x16968100, + 0x53202e40, 0x53401c40, 0x53910e40, 0x53993e40, + 0x53bc8440, 0x53be8130, 0x53bf0a40, 0x53c58240, + 0x53c68130, 0x53c80440, 0x53ca0101, 0x53cb1440, + 0x53d50130, 0x53d58130, 0x53d60130, 0x53d68130, + 0x53d70130, 0x53d80130, 0x53d88130, 0x53d90130, + 0x53d98131, 0x53da1040, 0x53e20131, 0x53e28130, + 0x53e30130, 0x53e38440, 0x53e58130, 0x53e60240, + 0x53e80240, 0x53eb0640, 0x53ee0130, 0x53fa8240, + 0x55a98101, 0x55b85020, 0x7d8001b2, 0x7d8081b2, + 0x7d8101b2, 0x7d8181da, 0x7d8201da, 0x7d8281b3, + 0x7d8301b3, 0x7d8981bb, 0x7d8a01bb, 0x7d8a81bb, + 0x7d8b01bc, 0x7d8b81bb, 0x7f909a31, 0x7fa09a01, + 0x82002831, 0x82142801, 0x82582431, 0x826c2401, + 0x82b80b31, 0x82be0f31, 0x82c60731, 0x82ca0231, + 0x82cb8b01, 0x82d18f01, 0x82d98701, 0x82dd8201, + 0x86403331, 0x86603301, 0x86a81631, 0x86b81601, 0x8c502031, 0x8c602001, 0xb7202031, 0xb7302001, 0xf4802231, 0xf4912201, }; -static const uint8_t case_conv_table2[370] = { +static const uint8_t case_conv_table2[378] = { 0x01, 0x00, 0x9c, 0x06, 0x07, 0x4d, 0x03, 0x04, 0x10, 0x00, 0x8f, 0x0b, 0x00, 0x00, 0x11, 0x00, - 0x08, 0x00, 0x53, 0x4a, 0x51, 0x00, 0x52, 0x00, - 0x53, 0x00, 0x3a, 0x54, 0x55, 0x00, 0x57, 0x59, - 0x3f, 0x5d, 0x5c, 0x00, 0x46, 0x61, 0x63, 0x42, - 0x64, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, - 0x6c, 0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00, 0x20, - 0x35, 0x00, 0x27, 0x00, 0x21, 0x00, 0x24, 0x22, - 0x2a, 0x00, 0x13, 0x6b, 0x6d, 0x00, 0x26, 0x24, - 0x27, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x3e, 0x1e, - 0x3f, 0x1f, 0x39, 0x3d, 0x22, 0x21, 0x41, 0x1e, - 0x40, 0x25, 0x25, 0x26, 0x28, 0x20, 0x2a, 0x48, - 0x2c, 0x43, 0x2e, 0x4b, 0x30, 0x4c, 0x32, 0x44, - 0x42, 0x99, 0x00, 0x00, 0x95, 0x8f, 0x7d, 0x7e, - 0x83, 0x84, 0x12, 0x80, 0x82, 0x76, 0x77, 0x12, - 0x7b, 0xa3, 0x7c, 0x78, 0x79, 0x8a, 0x92, 0x98, - 0xa6, 0xa0, 0x85, 0x00, 0x9a, 0xa1, 0x93, 0x75, - 0x33, 0x95, 0x00, 0x8e, 0x00, 0x74, 0x99, 0x98, - 0x97, 0x96, 0x00, 0x00, 0x9e, 0x00, 0x9c, 0x00, - 0xa1, 0xa0, 0x15, 0x2e, 0x2f, 0x30, 0xb4, 0xb5, - 0x4f, 0xaa, 0xa9, 0x12, 0x14, 0x1e, 0x21, 0x22, - 0x22, 0x2a, 0x34, 0x35, 0xa6, 0xa7, 0x36, 0x1f, - 0x49, 0x00, 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d, - 0x36, 0x05, 0x00, 0xc4, 0xc3, 0xc6, 0xc5, 0xc8, - 0xc7, 0xca, 0xc9, 0xcc, 0xcb, 0xc4, 0xd5, 0x45, - 0xd6, 0x42, 0xd7, 0x46, 0xd8, 0xce, 0xd0, 0xd2, - 0xd4, 0xda, 0xd9, 0xee, 0xf6, 0xfe, 0x0e, 0x07, - 0x0f, 0x80, 0x9f, 0x00, 0x21, 0x80, 0xa3, 0xed, - 0x00, 0xc0, 0x40, 0xc6, 0x60, 0xe7, 0xdb, 0xe6, - 0x99, 0xc0, 0x00, 0x00, 0x06, 0x60, 0xdc, 0x29, - 0xfd, 0x15, 0x12, 0x06, 0x16, 0xf8, 0xdd, 0x06, - 0x15, 0x12, 0x84, 0x08, 0xc6, 0x16, 0xff, 0xdf, - 0x03, 0xc0, 0x40, 0x00, 0x46, 0x60, 0xde, 0xe0, - 0x6d, 0x37, 0x38, 0x39, 0x15, 0x14, 0x17, 0x16, - 0x00, 0x1a, 0x19, 0x1c, 0x1b, 0x00, 0x5f, 0xb7, - 0x65, 0x44, 0x47, 0x00, 0x4f, 0x62, 0x4e, 0x50, - 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xa3, 0xa4, - 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, - 0x00, 0x5a, 0x00, 0x47, 0x00, 0x5b, 0x56, 0x58, - 0x60, 0x5e, 0x70, 0x69, 0x6f, 0x4e, 0x00, 0x3b, - 0x67, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa8, - 0x8a, 0x8b, 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf, - 0x94, 0xb0, 0x6f, 0xb2, 0x5d, 0x5c, 0x5f, 0x5e, - 0x61, 0x60, 0x66, 0x67, 0x68, 0x69, 0x62, 0x63, - 0x64, 0x65, 0x6b, 0x6a, 0x6d, 0x6c, 0x6f, 0x6e, - 0x71, 0x70, + 0x08, 0x00, 0x53, 0x4b, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x3b, 0x55, 0x56, 0x00, 0x58, 0x5a, + 0x40, 0x5f, 0x5e, 0x00, 0x47, 0x52, 0x63, 0x65, + 0x43, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, 0x6c, + 0x00, 0x6e, 0x00, 0x70, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00, + 0x20, 0x36, 0x00, 0x28, 0x00, 0x24, 0x00, 0x24, + 0x25, 0x2d, 0x00, 0x13, 0x6d, 0x6f, 0x00, 0x29, + 0x27, 0x2a, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x41, + 0x1e, 0x42, 0x1f, 0x4e, 0x3c, 0x40, 0x22, 0x21, + 0x44, 0x21, 0x43, 0x26, 0x28, 0x27, 0x29, 0x23, + 0x2b, 0x4b, 0x2d, 0x46, 0x2f, 0x4c, 0x31, 0x4d, + 0x33, 0x47, 0x45, 0x99, 0x00, 0x00, 0x97, 0x91, + 0x7f, 0x80, 0x85, 0x86, 0x12, 0x82, 0x84, 0x78, + 0x79, 0x12, 0x7d, 0xa3, 0x7e, 0x7a, 0x7b, 0x8c, + 0x92, 0x98, 0xa6, 0xa0, 0x87, 0x00, 0x9a, 0xa1, + 0x95, 0x77, 0x33, 0x95, 0x00, 0x90, 0x00, 0x76, + 0x9b, 0x9a, 0x99, 0x98, 0x00, 0x00, 0xa0, 0x00, + 0x9e, 0x00, 0xa3, 0xa2, 0x15, 0x31, 0x32, 0x33, + 0xb7, 0xb8, 0x55, 0xac, 0xab, 0x12, 0x14, 0x1e, + 0x21, 0x22, 0x22, 0x2a, 0x34, 0x35, 0x00, 0xa8, + 0xa9, 0x39, 0x22, 0x4c, 0x00, 0x00, 0x97, 0x01, + 0x5a, 0xda, 0x1d, 0x36, 0x05, 0x00, 0xc7, 0xc6, + 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce, + 0xc4, 0xd8, 0x45, 0xd9, 0x42, 0xda, 0x46, 0xdb, + 0xd1, 0xd3, 0xd5, 0xd7, 0xdd, 0xdc, 0xf1, 0xf9, + 0x01, 0x11, 0x0a, 0x12, 0x80, 0x9f, 0x00, 0x21, + 0x80, 0xa3, 0xf0, 0x00, 0xc0, 0x40, 0xc6, 0x60, + 0xea, 0xde, 0xe6, 0x99, 0xc0, 0x00, 0x00, 0x06, + 0x60, 0xdf, 0x29, 0x00, 0x15, 0x12, 0x06, 0x16, + 0xfb, 0xe0, 0x09, 0x15, 0x12, 0x84, 0x0b, 0xc6, + 0x16, 0x02, 0xe2, 0x06, 0xc0, 0x40, 0x00, 0x46, + 0x60, 0xe1, 0xe3, 0x6d, 0x37, 0x38, 0x39, 0x18, + 0x17, 0x1a, 0x19, 0x00, 0x1d, 0x1c, 0x1f, 0x1e, + 0x00, 0x61, 0xba, 0x67, 0x45, 0x48, 0x00, 0x50, + 0x64, 0x4f, 0x51, 0x00, 0x00, 0x49, 0x00, 0x00, + 0x00, 0xa5, 0xa6, 0xa7, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xb9, 0x00, 0x00, 0x5c, 0x00, 0x4a, 0x00, + 0x5d, 0x57, 0x59, 0x62, 0x60, 0x72, 0x6b, 0x71, + 0x54, 0x00, 0x3e, 0x69, 0xbb, 0x00, 0x5b, 0x00, + 0x00, 0x00, 0x25, 0x00, 0x48, 0xaa, 0x8a, 0x8b, + 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, + 0x6f, 0xb2, 0x63, 0x62, 0x65, 0x64, 0x67, 0x66, + 0x6c, 0x6d, 0x6e, 0x6f, 0x68, 0x69, 0x6a, 0x6b, + 0x71, 0x70, 0x73, 0x72, 0x75, 0x74, 0x77, 0x76, + 0x79, 0x78, }; static const uint16_t case_conv_ext[58] = { @@ -160,41 +163,41 @@ static const uint16_t case_conv_ext[58] = { 0x006b, 0x00e5, }; -static const uint8_t unicode_prop_Cased1_table[196] = { +static const uint8_t unicode_prop_Cased1_table[193] = { 0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3, - 0x80, 0x8c, 0x80, 0x8d, 0x81, 0x8d, 0x02, 0x80, - 0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, - 0x11, 0x00, 0x01, 0x04, 0x08, 0x01, 0x08, 0x30, - 0x08, 0x01, 0x15, 0x20, 0x00, 0x39, 0x99, 0x31, - 0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6, - 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x4b, 0x72, - 0x80, 0x4c, 0x02, 0xf8, 0x02, 0x80, 0x8f, 0x80, - 0xb0, 0x40, 0xdb, 0x08, 0x80, 0x41, 0xd0, 0x80, - 0x8c, 0x80, 0x8f, 0x8c, 0xe4, 0x03, 0x01, 0x89, - 0x00, 0x14, 0x28, 0x10, 0x11, 0x02, 0x01, 0x18, - 0x0b, 0x24, 0x4b, 0x26, 0x01, 0x01, 0x86, 0xe5, - 0x80, 0x60, 0x79, 0xb6, 0x81, 0x40, 0x91, 0x81, - 0xbd, 0x88, 0x94, 0x05, 0x80, 0x98, 0x80, 0xa2, - 0x00, 0x80, 0x9b, 0x12, 0x82, 0x43, 0x34, 0xa2, - 0x06, 0x80, 0x8d, 0x60, 0x5c, 0x15, 0x01, 0x10, - 0xa9, 0x80, 0x88, 0x60, 0xcc, 0x44, 0xd4, 0x80, - 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, - 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, - 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, - 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, - 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, - 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, 0x89, 0x80, - 0x93, 0x2d, 0x41, 0x04, 0xbd, 0x50, 0xc1, 0x99, - 0x85, 0x99, 0x85, 0x99, + 0x80, 0x9b, 0x81, 0x8d, 0x02, 0x80, 0xe1, 0x80, + 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, 0x11, 0x03, + 0x04, 0x08, 0x01, 0x08, 0x30, 0x08, 0x01, 0x15, + 0x20, 0x00, 0x39, 0x99, 0x31, 0x9d, 0x84, 0x40, + 0x94, 0x80, 0xd6, 0x82, 0xa6, 0x80, 0x41, 0x62, + 0x80, 0xa6, 0x80, 0x4b, 0x72, 0x80, 0x4c, 0x02, + 0xf8, 0x02, 0x80, 0x8f, 0x80, 0xb0, 0x40, 0xdb, + 0x08, 0x80, 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f, + 0x8c, 0xe4, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28, + 0x10, 0x11, 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b, + 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79, + 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94, + 0x05, 0x80, 0x98, 0x80, 0xa2, 0x00, 0x80, 0x9b, + 0x12, 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8d, + 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80, 0x88, + 0x60, 0xcc, 0x44, 0xd4, 0x80, 0xc6, 0x01, 0x08, + 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, + 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, + 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x07, 0x47, 0x33, 0x89, 0x80, 0x93, 0x2d, 0x41, + 0x04, 0xbd, 0x50, 0xc1, 0x99, 0x85, 0x99, 0x85, + 0x99, }; -static const uint8_t unicode_prop_Cased1_index[21] = { - 0xb9, 0x02, 0xe0, 0xc0, 0x1d, 0x20, 0xe5, 0x2c, - 0x20, 0xb1, 0x07, 0x21, 0xc1, 0xd6, 0x21, 0x4a, - 0xf1, 0x01, 0x8a, 0xf1, 0x01, +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, }; -static const uint8_t unicode_prop_Case_Ignorable_table[737] = { +static const uint8_t unicode_prop_Case_Ignorable_table[764] = { 0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40, @@ -203,7 +206,7 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = { 0x89, 0x8a, 0x00, 0xa2, 0x80, 0x89, 0x94, 0x8f, 0x80, 0xe4, 0x38, 0x89, 0x03, 0xa0, 0x00, 0x80, 0x9d, 0x9a, 0xda, 0x8a, 0xb9, 0x8a, 0x18, 0x08, - 0x97, 0x97, 0xaa, 0x82, 0xab, 0x06, 0x0d, 0x87, + 0x97, 0x97, 0xaa, 0x82, 0xab, 0x06, 0x0c, 0x88, 0xa8, 0xb9, 0xb6, 0x00, 0x03, 0x3b, 0x02, 0x86, 0x89, 0x81, 0x8c, 0x80, 0x8e, 0x80, 0xb9, 0x03, 0x1f, 0x80, 0x93, 0x81, 0x99, 0x01, 0x81, 0xb8, @@ -257,26 +260,29 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = { 0x80, 0x40, 0x94, 0x84, 0x44, 0x04, 0x28, 0xa9, 0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83, - 0x41, 0x82, 0x81, 0xcf, 0x82, 0xc5, 0x8a, 0xb0, - 0x83, 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81, - 0x89, 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89, - 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, - 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde, - 0x11, 0x00, 0x0d, 0x01, 0x80, 0x40, 0x9c, 0x02, - 0x87, 0x94, 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32, - 0x84, 0x40, 0xc2, 0x39, 0x10, 0x80, 0x96, 0x80, - 0xd3, 0x28, 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d, - 0x08, 0x81, 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81, - 0xe9, 0x00, 0x01, 0x28, 0x80, 0xe4, 0x11, 0x18, - 0x84, 0x41, 0x02, 0x88, 0x01, 0x40, 0xff, 0x08, - 0x03, 0x80, 0x40, 0x8f, 0x19, 0x0b, 0x80, 0x9f, - 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82, - 0xad, 0x8c, 0x01, 0x41, 0x95, 0x30, 0x28, 0x80, - 0xd1, 0x95, 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00, - 0x08, 0x30, 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41, - 0x5a, 0x81, 0x8a, 0x81, 0xb3, 0x24, 0x00, 0x80, - 0x54, 0xec, 0x90, 0x85, 0x8e, 0x60, 0x36, 0x99, - 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80, + 0xa5, 0x80, 0x99, 0x20, 0x80, 0x41, 0x3a, 0x81, + 0xce, 0x83, 0xc5, 0x8a, 0xb0, 0x83, 0xfa, 0x80, + 0xb5, 0x8e, 0xa8, 0x01, 0x81, 0x89, 0x82, 0xb0, + 0x19, 0x09, 0x03, 0x80, 0x89, 0x80, 0xb1, 0x82, + 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b, 0x81, 0xb3, + 0x88, 0x89, 0x19, 0x80, 0xde, 0x11, 0x00, 0x0d, + 0x01, 0x80, 0x40, 0x9c, 0x02, 0x87, 0x94, 0x81, + 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0xc5, 0x85, + 0x8c, 0x00, 0x00, 0x80, 0x8d, 0x81, 0xd4, 0x39, + 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, 0x03, 0x08, + 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81, 0x9a, 0x81, + 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, 0x01, 0x28, + 0x80, 0xe4, 0x00, 0x01, 0x18, 0x84, 0x41, 0x02, + 0x88, 0x01, 0x40, 0xff, 0x08, 0x03, 0x80, 0x40, + 0x8f, 0x19, 0x0b, 0x80, 0x9f, 0x89, 0xa7, 0x29, + 0x1f, 0x80, 0x88, 0x29, 0x82, 0xad, 0x8c, 0x01, + 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95, 0x0e, + 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x80, + 0xc7, 0x0a, 0x00, 0x80, 0x41, 0x5a, 0x81, 0x8a, + 0x81, 0xb3, 0x24, 0x00, 0x80, 0x96, 0x80, 0x54, + 0xd4, 0x90, 0x85, 0x8e, 0x60, 0x2c, 0xc7, 0x8b, + 0x12, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x88, 0x83, + 0x41, 0xfb, 0x82, 0xa7, 0x81, 0x41, 0xe1, 0x80, 0xbe, 0x90, 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a, 0x18, 0x30, 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52, 0x5b, 0xad, 0x81, 0x96, 0x42, 0x1f, 0x82, 0x88, @@ -285,24 +291,24 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = { 0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x84, 0xbd, 0xa0, 0x80, 0x40, 0x9f, 0x8d, 0x41, 0x6f, 0x80, 0xbc, 0x83, 0x41, 0xfa, 0x84, - 0x43, 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84, - 0x6c, 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40, - 0xef, + 0x40, 0xfd, 0x81, 0x42, 0xdf, 0x86, 0xec, 0x87, + 0x4a, 0xae, 0x84, 0x6c, 0x0c, 0x00, 0x80, 0x9d, + 0xdf, 0xff, 0x40, 0xef, }; -static const uint8_t unicode_prop_Case_Ignorable_index[69] = { +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, 0x75, 0x10, 0x01, - 0xeb, 0x12, 0x21, 0x41, 0x16, 0x01, 0x5c, 0x1a, - 0x01, 0x43, 0x1f, 0x01, 0x2e, 0xcf, 0x41, 0x25, - 0xe0, 0x01, 0xf0, 0x01, 0x0e, + 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, }; -static const uint8_t unicode_prop_ID_Start_table[1100] = { +static const uint8_t unicode_prop_ID_Start_table[1133] = { 0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03, 0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83, 0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20, @@ -346,7 +352,7 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = { 0x83, 0x99, 0xb5, 0x96, 0x88, 0xb4, 0xd1, 0x80, 0xdc, 0xae, 0x90, 0x87, 0xb5, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x99, 0xa3, 0xa8, 0x82, 0x89, 0xa3, - 0x81, 0x88, 0x86, 0xaa, 0x0a, 0xa8, 0x18, 0x28, + 0x81, 0x8a, 0x84, 0xaa, 0x0a, 0xa8, 0x18, 0x28, 0x0a, 0x04, 0x40, 0xbf, 0xbf, 0x41, 0x15, 0x0d, 0x81, 0xa5, 0x0d, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x81, 0xb4, 0x06, 0x00, 0x12, 0x06, 0x13, @@ -362,8 +368,8 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = { 0x41, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x56, 0x8c, 0xc2, 0xad, 0x81, 0x41, 0x0c, 0x82, 0x8f, 0x89, 0x81, 0x93, 0xae, 0x8f, 0x9e, 0x81, 0xcf, 0xa6, - 0x88, 0x81, 0xe6, 0x81, 0xbf, 0x21, 0x00, 0x04, - 0x97, 0x8f, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3, + 0x88, 0x81, 0xe6, 0x81, 0xc2, 0x09, 0x00, 0x07, + 0x94, 0x8f, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3, 0x8d, 0xb1, 0xbd, 0x2a, 0x00, 0x81, 0x8a, 0x9b, 0x89, 0x96, 0x98, 0x9c, 0x86, 0xae, 0x9b, 0x80, 0x8f, 0x20, 0x89, 0x89, 0x20, 0xa8, 0x96, 0x10, @@ -383,91 +389,95 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = { 0xa5, 0x89, 0x9d, 0x81, 0xa3, 0x1f, 0x04, 0xa9, 0x40, 0x9d, 0x91, 0xa3, 0x83, 0xa3, 0x83, 0xa7, 0x87, 0xb3, 0x8b, 0x8a, 0x80, 0x8e, 0x06, 0x01, - 0x80, 0x8a, 0x80, 0x8e, 0x06, 0x01, 0xc2, 0x41, - 0x36, 0x88, 0x95, 0x89, 0x87, 0x97, 0x28, 0xa9, - 0x80, 0x88, 0xc4, 0x29, 0x00, 0xab, 0x01, 0x10, - 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e, 0xc0, 0x92, - 0x01, 0x89, 0x95, 0x89, 0x99, 0xc5, 0xb7, 0x29, - 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c, 0xa9, 0x9c, - 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, 0xb5, 0x89, - 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed, 0xc8, 0xb6, - 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0x41, 0x5b, 0xa9, - 0x29, 0xcd, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91, + 0x80, 0x8a, 0x80, 0x8e, 0x06, 0x01, 0x82, 0xb3, + 0x8b, 0x41, 0x36, 0x88, 0x95, 0x89, 0x87, 0x97, + 0x28, 0xa9, 0x80, 0x88, 0xc4, 0x29, 0x00, 0xab, + 0x01, 0x10, 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e, + 0xc0, 0x92, 0x01, 0x89, 0x95, 0x89, 0x99, 0xc5, + 0xb7, 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c, + 0xa9, 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, + 0xb5, 0x89, 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed, + 0xc8, 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0xa5, + 0x9b, 0x88, 0x96, 0x40, 0xf9, 0xa9, 0x29, 0x8f, + 0x82, 0xba, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91, 0xad, 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09, 0x80, 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c, 0x01, 0x07, 0xa2, 0x10, 0x8b, 0xaf, 0x8d, 0x83, 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92, 0x81, 0xbe, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89, 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, - 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d, - 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, 0x93, - 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, - 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, - 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf, - 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00, - 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, - 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, - 0x92, 0x80, 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80, - 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08, - 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d, - 0x80, 0x41, 0x46, 0x92, 0x8e, 0x00, 0x8c, 0x80, - 0xa1, 0xfb, 0x80, 0xce, 0x43, 0x99, 0xe5, 0xee, - 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0, 0x8e, 0x44, - 0x2f, 0x90, 0x85, 0x4f, 0xb8, 0x42, 0x46, 0x60, - 0x21, 0xb8, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce, - 0x90, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, - 0x84, 0x92, 0x42, 0xaf, 0xbf, 0xff, 0xca, 0x20, - 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, 0x57, 0xf7, - 0x87, 0x44, 0xd5, 0xa9, 0x88, 0x60, 0x22, 0xe6, - 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, 0x80, 0x9c, - 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, 0x49, 0x03, - 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, 0x89, 0x57, - 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, - 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, - 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, - 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x47, - 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, 0x40, 0x91, - 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40, 0x9d, - 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x42, 0xf3, 0x30, - 0x18, 0x08, 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3, - 0x30, 0x44, 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, - 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, - 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, - 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, - 0x51, 0x43, 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, - 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, - 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53, - 0x4a, 0x84, 0x50, 0x5f, + 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x9d, 0x89, + 0x00, 0x08, 0x80, 0xa5, 0x00, 0x98, 0x00, 0x80, + 0xab, 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, + 0x93, 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, + 0xa3, 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, + 0xc6, 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, + 0xbf, 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, + 0x00, 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, + 0x9b, 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, + 0xad, 0x92, 0x80, 0x91, 0xc8, 0x40, 0xc6, 0xa0, + 0x9e, 0x88, 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d, + 0xef, 0x30, 0x08, 0xa5, 0x94, 0x80, 0x98, 0x28, + 0x08, 0x9f, 0x8d, 0x80, 0x41, 0x46, 0x92, 0x8e, + 0x00, 0x8c, 0x80, 0xa1, 0xfb, 0x80, 0xce, 0x43, + 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0x4b, + 0xe0, 0x8e, 0x44, 0x2f, 0x90, 0x85, 0x98, 0x4f, + 0x9a, 0x84, 0x42, 0x46, 0x5a, 0xb8, 0x9d, 0x46, + 0xe1, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce, 0x90, + 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, 0x84, + 0x92, 0x41, 0xaf, 0xac, 0x40, 0xd2, 0xbf, 0xff, + 0xca, 0x20, 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, + 0x57, 0xf7, 0x87, 0x44, 0xd5, 0xa8, 0x89, 0x60, + 0x22, 0xe6, 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, + 0x80, 0x9c, 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, + 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, + 0x89, 0x57, 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, + 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, + 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, + 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x07, 0x47, 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, + 0x40, 0x91, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, + 0x40, 0x9d, 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x40, + 0xe3, 0x9d, 0x08, 0x41, 0xee, 0x30, 0x18, 0x08, + 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3, 0x30, 0x44, + 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89, + 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, + 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89, + 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43, + 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, + 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e, + 0x42, 0x6d, 0x49, 0xa1, 0x42, 0x1d, 0x45, 0xe1, + 0x53, 0x4a, 0x84, 0x50, 0x5f, }; -static const uint8_t unicode_prop_ID_Start_index[105] = { +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, 0xda, 0xa7, 0x00, 0x4c, 0xaa, 0x20, + 0x32, 0x00, 0xdd, 0xa7, 0x00, 0x4c, 0xaa, 0x20, 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02, - 0x21, 0x96, 0x05, 0x01, 0xf3, 0x08, 0x01, 0xb3, - 0x0c, 0x21, 0x73, 0x11, 0x61, 0x34, 0x13, 0x01, - 0x1b, 0x17, 0x21, 0x8a, 0x1a, 0x01, 0x34, 0x1f, - 0x21, 0xbf, 0x6a, 0x01, 0x23, 0xb1, 0xa1, 0xad, - 0xd4, 0x01, 0x6f, 0xd7, 0x01, 0xff, 0xe7, 0x61, - 0x5e, 0xee, 0x01, 0xe1, 0xeb, 0x22, 0xb0, 0x23, - 0x03, + 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, }; -static const uint8_t unicode_prop_ID_Continue1_table[660] = { +static const uint8_t unicode_prop_ID_Continue1_table[695] = { 0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47, 0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08, 0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x9e, 0x28, 0xe4, 0x31, 0x29, 0x08, 0x19, 0x89, 0x96, 0x80, 0x9d, 0x9a, 0xda, 0x8a, 0x8e, 0x89, 0xa0, 0x88, 0x88, 0x80, 0x97, 0x18, 0x88, 0x02, - 0x04, 0xaa, 0x82, 0xbb, 0x87, 0xa9, 0x97, 0x80, + 0x04, 0xaa, 0x82, 0xba, 0x88, 0xa9, 0x97, 0x80, 0xa0, 0xb5, 0x10, 0x91, 0x06, 0x89, 0x09, 0x89, 0x90, 0x82, 0xb7, 0x00, 0x31, 0x09, 0x82, 0x88, 0x80, 0x89, 0x09, 0x89, 0x8d, 0x01, 0x82, 0xb7, @@ -496,70 +506,83 @@ static const uint8_t unicode_prop_ID_Continue1_table[660] = { 0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, 0xaf, 0x93, 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18, - 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x3e, 0x81, - 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82, 0x8b, 0x4b, - 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, 0x9f, 0x42, - 0x29, 0x85, 0xe8, 0x81, 0x60, 0x75, 0x84, 0x89, - 0xc4, 0x03, 0x89, 0x9f, 0x81, 0xcf, 0x81, 0x41, - 0x0f, 0x02, 0x03, 0x80, 0x96, 0x23, 0x80, 0xd2, - 0x81, 0xb1, 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c, - 0x8a, 0x9b, 0x87, 0x98, 0x8c, 0xab, 0x83, 0xae, - 0x8d, 0x8e, 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae, - 0x8d, 0x8b, 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1, - 0x00, 0x11, 0x0c, 0x08, 0x80, 0xa8, 0x24, 0x81, - 0x40, 0xeb, 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23, - 0x80, 0x42, 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97, - 0x82, 0x40, 0xbf, 0x89, 0xa4, 0x80, 0x42, 0xbc, - 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, - 0x24, 0x89, 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, - 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, - 0x89, 0x41, 0x70, 0x81, 0xcf, 0x82, 0xc5, 0x8a, - 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a, - 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89, - 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80, - 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 0xd1, - 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b, 0x84, 0x89, - 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, 0x88, 0x80, - 0x89, 0x09, 0x32, 0x84, 0x40, 0xbf, 0x91, 0x88, - 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, 0x40, 0xd4, - 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, 0x8e, 0x89, - 0xd0, 0x8c, 0x87, 0x89, 0xd2, 0x8e, 0x83, 0x89, - 0x40, 0xf1, 0x8e, 0x40, 0xa4, 0x89, 0xc5, 0x28, - 0x09, 0x18, 0x00, 0x81, 0x8b, 0x89, 0xf6, 0x31, - 0x32, 0x80, 0x9b, 0x89, 0xa7, 0x30, 0x1f, 0x80, - 0x88, 0x8a, 0xad, 0x8f, 0x41, 0x94, 0x38, 0x87, - 0x8f, 0x89, 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, - 0x00, 0x08, 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08, - 0x27, 0x89, 0x41, 0x48, 0x83, 0x88, 0x08, 0x80, - 0xaf, 0x32, 0x84, 0x8c, 0x89, 0x54, 0xe5, 0x05, - 0x8e, 0x60, 0x36, 0x09, 0x89, 0xd5, 0x89, 0xa5, - 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00, - 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60, 0x4c, - 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96, 0x42, - 0x1d, 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40, - 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, - 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, - 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, - 0x80, 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63, - 0x80, 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x43, 0xd5, - 0x86, 0xec, 0x34, 0x89, 0x52, 0x95, 0x89, 0x6c, - 0x05, 0x05, 0x40, 0xef, + 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x0b, 0x81, + 0xb0, 0x81, 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82, + 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, + 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, 0xdf, 0x80, + 0x60, 0x75, 0x23, 0x89, 0xc4, 0x03, 0x89, 0x9f, + 0x81, 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80, + 0x96, 0x23, 0x80, 0xd2, 0x81, 0xb1, 0x91, 0x89, + 0x89, 0x85, 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98, + 0x8c, 0xab, 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a, + 0x80, 0x89, 0x89, 0xae, 0x8d, 0x8b, 0x07, 0x09, + 0x89, 0xa0, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, + 0x80, 0xa8, 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09, + 0x89, 0x60, 0x4f, 0x23, 0x80, 0x42, 0xe0, 0x8f, + 0x8f, 0x8f, 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89, + 0xa4, 0x80, 0xa4, 0x80, 0x42, 0x96, 0x80, 0x40, + 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, 0x24, 0x89, + 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80, + 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, 0x89, 0x85, + 0x89, 0x9e, 0x84, 0x41, 0x3c, 0x81, 0xce, 0x83, + 0xc5, 0x8a, 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, + 0x9e, 0x8a, 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, + 0xac, 0x89, 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, + 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, + 0x8b, 0xd1, 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b, + 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, + 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0xc2, 0x88, + 0x00, 0x08, 0x03, 0x04, 0x00, 0x8d, 0x81, 0xd1, + 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, + 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, + 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0x85, 0x93, + 0xb8, 0x8e, 0x83, 0x89, 0x40, 0xf1, 0x8e, 0x40, + 0xa4, 0x89, 0xc5, 0x28, 0x09, 0x18, 0x00, 0x81, + 0x8b, 0x89, 0xf6, 0x31, 0x32, 0x80, 0x9b, 0x89, + 0xa7, 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad, 0x8f, + 0x41, 0x55, 0x89, 0xb4, 0x38, 0x87, 0x8f, 0x89, + 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, + 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08, 0x27, 0x89, + 0x41, 0x48, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, + 0x84, 0x8c, 0x8a, 0x54, 0xe4, 0x05, 0x8e, 0x60, + 0x2c, 0xc7, 0x9b, 0x49, 0x25, 0x89, 0xd5, 0x89, + 0xa5, 0x84, 0xba, 0x86, 0x98, 0x89, 0x42, 0x15, + 0x89, 0x41, 0xd4, 0x00, 0xb6, 0x33, 0xd0, 0x80, + 0x8a, 0x81, 0x60, 0x4c, 0xaa, 0x81, 0x50, 0x50, + 0x89, 0x42, 0x05, 0xad, 0x81, 0x96, 0x42, 0x1d, + 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40, 0x93, + 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83, + 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, + 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, 0x80, + 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63, 0x80, + 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x40, 0xf3, 0x08, + 0x89, 0x42, 0xd4, 0x86, 0xec, 0x34, 0x89, 0x52, + 0x95, 0x89, 0x6c, 0x05, 0x05, 0x40, 0xef, }; -static const uint8_t unicode_prop_ID_Continue1_index[63] = { +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, - 0x41, 0x20, 0x00, 0x0c, 0xa8, 0x80, 0x37, 0xaa, - 0x20, 0x50, 0xfe, 0x20, 0x3a, 0x0d, 0x21, 0x74, - 0x11, 0x01, 0x5a, 0x14, 0x21, 0x44, 0x19, 0x81, - 0x5a, 0x1d, 0xa1, 0xf5, 0x6a, 0x21, 0x45, 0xd2, - 0x41, 0xaf, 0xe2, 0x21, 0xf0, 0x01, 0x0e, + 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, }; -#ifdef CONFIG_ALL_UNICODE +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_cc_table[899] = { +static const uint8_t unicode_prop_White_Space_index[3] = { + 0x01, 0x30, 0x00, +}; + +static const uint8_t unicode_cc_table[916] = { 0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00, 0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03, 0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03, @@ -583,7 +606,7 @@ static const uint8_t unicode_cc_table[899] = { 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xc1, 0xb0, 0x6f, 0xc6, 0x00, 0xdc, 0xc0, 0x88, 0x00, 0xdc, 0x97, 0xc3, 0x80, 0xc8, 0x80, 0xc2, 0x80, 0xc4, - 0xaa, 0x02, 0xdc, 0xb0, 0x0b, 0xc0, 0x02, 0xdc, + 0xaa, 0x02, 0xdc, 0xb0, 0x0a, 0xc1, 0x02, 0xdc, 0xc3, 0xa9, 0xc4, 0x04, 0xdc, 0xcd, 0x80, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0xc2, 0x02, 0xdc, 0x42, 0x1b, 0xc2, 0x00, 0xdc, 0xc1, @@ -641,38 +664,40 @@ static const uint8_t unicode_cc_table[899] = { 0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, 0xc4, 0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0, 0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0, - 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1, - 0x52, 0xc1, 0xb0, 0x1f, 0x02, 0xdc, 0xb0, 0x15, - 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc, - 0xb0, 0x00, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, - 0xb0, 0x8f, 0x00, 0x09, 0xa8, 0x00, 0x09, 0x8d, - 0x00, 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07, - 0xb0, 0x14, 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d, - 0x00, 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00, - 0x07, 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0, - 0x81, 0x00, 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01, - 0x07, 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4, - 0xb0, 0x9c, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, - 0xc0, 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, - 0xca, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, - 0x09, 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, - 0x42, 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, - 0x07, 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07, - 0xb0, 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09, - 0x91, 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, - 0x74, 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80, - 0x01, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78, - 0x01, 0x09, 0xb8, 0x43, 0x7c, 0x04, 0x01, 0xb0, - 0x0a, 0xc6, 0xb4, 0x88, 0x01, 0x06, 0xb8, 0x44, - 0x7b, 0x00, 0x01, 0xb8, 0x0c, 0x95, 0x01, 0xd8, - 0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, 0x87, - 0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, 0xc3, - 0xb0, 0x63, 0xc2, 0xb8, 0x05, 0x8a, 0xc6, 0x80, - 0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, 0xb0, - 0x33, 0xc0, 0xb0, 0x6f, 0xc6, 0xb1, 0x46, 0xc0, - 0xb0, 0x0c, 0xc3, 0xb1, 0xcb, 0x01, 0xe8, 0x00, - 0xdc, 0xc0, 0xb3, 0xaf, 0x06, 0xdc, 0xb0, 0x3c, - 0xc5, 0x00, 0x07, + 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb0, + 0x10, 0xc4, 0xb1, 0x0c, 0xc1, 0xb0, 0x1f, 0x02, + 0xdc, 0xb0, 0x15, 0x01, 0xdc, 0xc2, 0x00, 0xdc, + 0xc0, 0x03, 0xdc, 0xb0, 0x00, 0xc0, 0x00, 0xdc, + 0xc0, 0x00, 0xdc, 0xb0, 0x8f, 0x00, 0x09, 0xa8, + 0x00, 0x09, 0x8d, 0x00, 0x09, 0xb0, 0x08, 0x00, + 0x09, 0x00, 0x07, 0xb0, 0x14, 0xc2, 0xaf, 0x01, + 0x09, 0xb0, 0x0d, 0x00, 0x07, 0xb0, 0x1b, 0x00, + 0x09, 0x88, 0x00, 0x07, 0xb0, 0x39, 0x00, 0x09, + 0x00, 0x07, 0xb0, 0x81, 0x00, 0x07, 0x00, 0x09, + 0xb0, 0x1f, 0x01, 0x07, 0x8f, 0x00, 0x09, 0x97, + 0xc6, 0x82, 0xc4, 0xb0, 0x28, 0x02, 0x09, 0xb0, + 0x40, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, 0xc0, + 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, 0xca, + 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, 0x09, + 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x42, + 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, 0x07, + 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07, 0xb0, + 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09, 0x91, + 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x74, + 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80, 0x01, + 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78, 0x01, + 0x09, 0xb8, 0x39, 0xbb, 0x00, 0x09, 0xb8, 0x01, + 0x8f, 0x04, 0x01, 0xb0, 0x0a, 0xc6, 0xb4, 0x88, + 0x01, 0x06, 0xb8, 0x44, 0x7b, 0x00, 0x01, 0xb8, + 0x0c, 0x95, 0x01, 0xd8, 0x02, 0x01, 0x82, 0x00, + 0xe2, 0x04, 0xd8, 0x87, 0x07, 0xdc, 0x81, 0xc4, + 0x01, 0xdc, 0x9d, 0xc3, 0xb0, 0x63, 0xc2, 0xb8, + 0x05, 0x8a, 0xc6, 0x80, 0xd0, 0x81, 0xc6, 0x80, + 0xc1, 0x80, 0xc4, 0xb0, 0x33, 0xc0, 0xb0, 0x6f, + 0xc6, 0xb1, 0x46, 0xc0, 0xb0, 0x0c, 0xc3, 0xb1, + 0xcb, 0x01, 0xe8, 0x00, 0xdc, 0xc0, 0xb0, 0xcd, + 0xc0, 0x00, 0xdc, 0xb2, 0xaf, 0x06, 0xdc, 0xb0, + 0x3c, 0xc5, 0x00, 0x07, }; static const uint8_t unicode_cc_index[87] = { @@ -683,13 +708,13 @@ static const uint8_t unicode_cc_index[87] = { 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, 0x51, 0x0f, 0x01, 0x73, - 0x11, 0x01, 0x75, 0x13, 0x01, 0x2b, 0x17, 0x21, - 0x3f, 0x1c, 0x21, 0x9e, 0xbc, 0x21, 0x08, 0xe0, - 0x01, 0x44, 0xe9, 0x01, 0x4b, 0xe9, 0x01, + 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, }; -static const uint32_t unicode_decomp_table1[699] = { +static const uint32_t unicode_decomp_table1[709] = { 0x00280081, 0x002a0097, 0x002a8081, 0x002bc097, 0x002c8115, 0x002d0097, 0x002d4081, 0x002e0097, 0x002e4115, 0x002f0199, 0x00302016, 0x00400842, @@ -832,42 +857,45 @@ static const uint32_t unicode_decomp_table1[699] = { 0x3f9c01af, 0x3f9d0085, 0x3f9d852f, 0x3fa03aad, 0x3fbd442f, 0x3fc06f1f, 0x3fd7c11f, 0x3fd85fad, 0x3fe80081, 0x3fe84f1f, 0x3ff0831f, 0x3ff2831f, - 0x3ff4831f, 0x3ff6819f, 0x3ff80783, 0x41e04d83, - 0x41e70f91, 0x44268192, 0x442ac092, 0x444b8112, - 0x44d2c112, 0x452ec212, 0x456e8112, 0x464e0092, - 0x74578392, 0x746ec312, 0x75000d1f, 0x75068d1f, - 0x750d0d1f, 0x7513839f, 0x7515891f, 0x751a0d1f, - 0x75208d1f, 0x75271015, 0x752f439f, 0x7531459f, - 0x75340d1f, 0x753a8d1f, 0x75410395, 0x7543441f, - 0x7545839f, 0x75478d1f, 0x754e0795, 0x7552839f, - 0x75548d1f, 0x755b0d1f, 0x75618d1f, 0x75680d1f, - 0x756e8d1f, 0x75750d1f, 0x757b8d1f, 0x75820d1f, - 0x75888d1f, 0x758f0d1f, 0x75958d1f, 0x759c0d1f, - 0x75a28d1f, 0x75a90103, 0x75aa089f, 0x75ae4081, - 0x75ae839f, 0x75b04081, 0x75b08c9f, 0x75b6c081, - 0x75b7032d, 0x75b8889f, 0x75bcc081, 0x75bd039f, - 0x75bec081, 0x75bf0c9f, 0x75c54081, 0x75c5832d, - 0x75c7089f, 0x75cb4081, 0x75cb839f, 0x75cd4081, - 0x75cd8c9f, 0x75d3c081, 0x75d4032d, 0x75d5889f, - 0x75d9c081, 0x75da039f, 0x75dbc081, 0x75dc0c9f, - 0x75e24081, 0x75e2832d, 0x75e4089f, 0x75e84081, - 0x75e8839f, 0x75ea4081, 0x75ea8c9f, 0x75f0c081, - 0x75f1042d, 0x75f3851f, 0x75f6051f, 0x75f8851f, - 0x75fb051f, 0x75fd851f, 0x780c049f, 0x780e419f, - 0x780f059f, 0x7811c203, 0x7812d0ad, 0x781b0103, - 0x7b80022d, 0x7b814dad, 0x7b884203, 0x7b89c081, - 0x7b8a452d, 0x7b8d0403, 0x7b908081, 0x7b91dc03, - 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, 0x7baac8ad, - 0x7c400097, 0x7c404521, 0x7c440d25, 0x7c4a8087, - 0x7c4ac115, 0x7c4b4117, 0x7c4c0d1f, 0x7c528217, - 0x7c538099, 0x7c53c097, 0x7c5a8197, 0x7c640097, - 0x7c80012f, 0x7c808081, 0x7c841603, 0x7c9004c1, - 0x7c940103, 0x7efc051f, 0xbe0001ac, 0xbe00d110, - 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c, - 0xbe2e3790, 0xbe49ff90, 0xbe69bc10, + 0x3ff4831f, 0x3ff6819f, 0x3ff80783, 0x41724092, + 0x41790092, 0x41e04d83, 0x41e70f91, 0x44268192, + 0x442ac092, 0x444b8112, 0x44d2c112, 0x44e0c192, + 0x44e38092, 0x44e44092, 0x44f14212, 0x452ec212, + 0x456e8112, 0x464e0092, 0x58484412, 0x5b5a0192, + 0x73358d1f, 0x733c051f, 0x74578392, 0x746ec312, + 0x75000d1f, 0x75068d1f, 0x750d0d1f, 0x7513839f, + 0x7515891f, 0x751a0d1f, 0x75208d1f, 0x75271015, + 0x752f439f, 0x7531459f, 0x75340d1f, 0x753a8d1f, + 0x75410395, 0x7543441f, 0x7545839f, 0x75478d1f, + 0x754e0795, 0x7552839f, 0x75548d1f, 0x755b0d1f, + 0x75618d1f, 0x75680d1f, 0x756e8d1f, 0x75750d1f, + 0x757b8d1f, 0x75820d1f, 0x75888d1f, 0x758f0d1f, + 0x75958d1f, 0x759c0d1f, 0x75a28d1f, 0x75a90103, + 0x75aa089f, 0x75ae4081, 0x75ae839f, 0x75b04081, + 0x75b08c9f, 0x75b6c081, 0x75b7032d, 0x75b8889f, + 0x75bcc081, 0x75bd039f, 0x75bec081, 0x75bf0c9f, + 0x75c54081, 0x75c5832d, 0x75c7089f, 0x75cb4081, + 0x75cb839f, 0x75cd4081, 0x75cd8c9f, 0x75d3c081, + 0x75d4032d, 0x75d5889f, 0x75d9c081, 0x75da039f, + 0x75dbc081, 0x75dc0c9f, 0x75e24081, 0x75e2832d, + 0x75e4089f, 0x75e84081, 0x75e8839f, 0x75ea4081, + 0x75ea8c9f, 0x75f0c081, 0x75f1042d, 0x75f3851f, + 0x75f6051f, 0x75f8851f, 0x75fb051f, 0x75fd851f, + 0x780c049f, 0x780e419f, 0x780f059f, 0x7811c203, + 0x7812d0ad, 0x781b0103, 0x7b80022d, 0x7b814dad, + 0x7b884203, 0x7b89c081, 0x7b8a452d, 0x7b8d0403, + 0x7b908081, 0x7b91dc03, 0x7ba0052d, 0x7ba2c8ad, + 0x7ba84483, 0x7baac8ad, 0x7c400097, 0x7c404521, + 0x7c440d25, 0x7c4a8087, 0x7c4ac115, 0x7c4b4117, + 0x7c4c0d1f, 0x7c528217, 0x7c538099, 0x7c53c097, + 0x7c5a8197, 0x7c640097, 0x7c80012f, 0x7c808081, + 0x7c841603, 0x7c9004c1, 0x7c940103, 0x7efc051f, + 0xbe0001ac, 0xbe00d110, 0xbe0947ac, 0xbe0d3910, + 0xbe29872c, 0xbe2d022c, 0xbe2e3790, 0xbe49ff90, + 0xbe69bc10, }; -static const uint16_t unicode_decomp_table2[699] = { +static const uint16_t unicode_decomp_table2[709] = { 0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008, 0x000a, 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3, 0x00c7, 0x00cb, 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8, @@ -939,26 +967,27 @@ static const uint16_t unicode_decomp_table2[699] = { 0x1a77, 0x1a7f, 0x1a9d, 0x1aa2, 0x1ab6, 0x1ac0, 0x1ac6, 0x1ada, 0x1adf, 0x1ae5, 0x1af3, 0x1b23, 0x1b30, 0x1b38, 0x1b3c, 0x1b52, 0x1bc9, 0x1bdb, 0x1bdd, 0x1bdf, 0x3164, 0x1c20, 0x1c22, 0x1c24, - 0x1c26, 0x1c28, 0x1c2a, 0x1c48, 0x1c7e, 0x1cc4, 0x1cd2, 0x1cd7, - 0x1ce0, 0x1ce9, 0x1cfb, 0x1d04, 0x1d09, 0x1d29, 0x1d44, 0x1d46, - 0x1d48, 0x1d4a, 0x1d4c, 0x1d4e, 0x1d50, 0x1d52, 0x1d72, 0x1d74, - 0x1d76, 0x1d78, 0x1d7a, 0x1d81, 0x1d83, 0x1d85, 0x1d87, 0x1d96, - 0x1d98, 0x1d9a, 0x1d9c, 0x1d9e, 0x1da0, 0x1da2, 0x1da4, 0x1da6, - 0x1da8, 0x1daa, 0x1dac, 0x1dae, 0x1db0, 0x1db2, 0x1db6, 0x03f4, - 0x1db8, 0x2207, 0x1dba, 0x2202, 0x1dbc, 0x1dc4, 0x03f4, 0x1dc6, - 0x2207, 0x1dc8, 0x2202, 0x1dca, 0x1dd2, 0x03f4, 0x1dd4, 0x2207, - 0x1dd6, 0x2202, 0x1dd8, 0x1de0, 0x03f4, 0x1de2, 0x2207, 0x1de4, - 0x2202, 0x1de6, 0x1dee, 0x03f4, 0x1df0, 0x2207, 0x1df2, 0x2202, - 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a, - 0x1e0c, 0x1e0e, 0x1e16, 0x1e39, 0x1e3d, 0x1e43, 0x1e60, 0x062d, - 0x1e68, 0x1e74, 0x062c, 0x1e84, 0x1ef4, 0x1f00, 0x1f13, 0x1f25, - 0x1f38, 0x1f3a, 0x1f3e, 0x1f44, 0x1f4a, 0x1f4c, 0x1f50, 0x1f52, - 0x1f5a, 0x1f5d, 0x1f5f, 0x1f65, 0x1f67, 0x30b5, 0x1f6d, 0x1fc5, - 0x1fdb, 0x1fdf, 0x1fe1, 0x1fe6, 0x2033, 0x2044, 0x2145, 0x2155, - 0x215b, 0x2255, 0x2373, + 0x1c26, 0x1c28, 0x1c2a, 0x1c48, 0x1c4d, 0x1c52, 0x1c88, 0x1cce, + 0x1cdc, 0x1ce1, 0x1cea, 0x1cf3, 0x1d01, 0x1d06, 0x1d0b, 0x1d1d, + 0x1d2f, 0x1d38, 0x1d3d, 0x1d61, 0x1d6f, 0x1d71, 0x1d73, 0x1d93, + 0x1dae, 0x1db0, 0x1db2, 0x1db4, 0x1db6, 0x1db8, 0x1dba, 0x1dbc, + 0x1ddc, 0x1dde, 0x1de0, 0x1de2, 0x1de4, 0x1deb, 0x1ded, 0x1def, + 0x1df1, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a, 0x1e0c, + 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c, + 0x1e20, 0x03f4, 0x1e22, 0x2207, 0x1e24, 0x2202, 0x1e26, 0x1e2e, + 0x03f4, 0x1e30, 0x2207, 0x1e32, 0x2202, 0x1e34, 0x1e3c, 0x03f4, + 0x1e3e, 0x2207, 0x1e40, 0x2202, 0x1e42, 0x1e4a, 0x03f4, 0x1e4c, + 0x2207, 0x1e4e, 0x2202, 0x1e50, 0x1e58, 0x03f4, 0x1e5a, 0x2207, + 0x1e5c, 0x2202, 0x1e5e, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, + 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e80, 0x1ea3, 0x1ea7, 0x1ead, + 0x1eca, 0x062d, 0x1ed2, 0x1ede, 0x062c, 0x1eee, 0x1f5e, 0x1f6a, + 0x1f7d, 0x1f8f, 0x1fa2, 0x1fa4, 0x1fa8, 0x1fae, 0x1fb4, 0x1fb6, + 0x1fba, 0x1fbc, 0x1fc4, 0x1fc7, 0x1fc9, 0x1fcf, 0x1fd1, 0x30b5, + 0x1fd7, 0x202f, 0x2045, 0x2049, 0x204b, 0x2050, 0x209d, 0x20ae, + 0x21af, 0x21bf, 0x21c5, 0x22bf, 0x23dd, }; -static const uint8_t unicode_decomp_data[9345] = { +static const uint8_t unicode_decomp_data[9451] = { 0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81, 0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31, 0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41, @@ -1864,273 +1893,286 @@ static const uint8_t unicode_decomp_data[9345] = { 0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, 0x20, 0x00, 0x00, 0x02, 0x25, 0x90, 0x21, 0x91, 0x21, 0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, 0x25, - 0xd0, 0x02, 0xd1, 0x02, 0xe6, 0x00, 0x99, 0x02, - 0x53, 0x02, 0x00, 0x00, 0xa3, 0x02, 0x66, 0xab, - 0xa5, 0x02, 0xa4, 0x02, 0x56, 0x02, 0x57, 0x02, - 0x91, 0x1d, 0x58, 0x02, 0x5e, 0x02, 0xa9, 0x02, - 0x64, 0x02, 0x62, 0x02, 0x60, 0x02, 0x9b, 0x02, - 0x27, 0x01, 0x9c, 0x02, 0x67, 0x02, 0x84, 0x02, - 0xaa, 0x02, 0xab, 0x02, 0x6c, 0x02, 0x04, 0xdf, - 0x8e, 0xa7, 0x6e, 0x02, 0x05, 0xdf, 0x8e, 0x02, - 0x06, 0xdf, 0xf8, 0x00, 0x76, 0x02, 0x77, 0x02, - 0x71, 0x00, 0x7a, 0x02, 0x08, 0xdf, 0x7d, 0x02, - 0x7e, 0x02, 0x80, 0x02, 0xa8, 0x02, 0xa6, 0x02, - 0x67, 0xab, 0xa7, 0x02, 0x88, 0x02, 0x71, 0x2c, - 0x00, 0x00, 0x8f, 0x02, 0xa1, 0x02, 0xa2, 0x02, - 0x98, 0x02, 0xc0, 0x01, 0xc1, 0x01, 0xc2, 0x01, - 0x0a, 0xdf, 0x1e, 0xdf, 0x41, 0x04, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x99, 0x10, 0xba, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, 0xba, 0x10, - 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, 0x05, 0x31, - 0x11, 0x27, 0x11, 0x32, 0x11, 0x27, 0x11, 0x55, - 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, 0x57, 0x13, - 0x55, 0xb9, 0x14, 0xba, 0x14, 0xb9, 0x14, 0xb0, - 0x14, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x14, 0xbd, - 0x14, 0x55, 0x50, 0xb8, 0x15, 0xaf, 0x15, 0xb9, - 0x15, 0xaf, 0x15, 0x55, 0x35, 0x19, 0x30, 0x19, - 0x05, 0x57, 0xd1, 0x65, 0xd1, 0x58, 0xd1, 0x65, - 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, 0xd1, 0x6f, - 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f, 0xd1, 0x71, - 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, 0x55, 0x55, - 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, 0xd1, 0x65, - 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc, 0xd1, 0x6e, - 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, 0xd1, 0x6f, - 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, 0x61, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x69, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, 0x00, 0x4e, - 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, - 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, - 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, 0x00, 0x41, - 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, 0x00, 0x49, - 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, 0x53, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, 0x91, 0x03, + 0xd2, 0x05, 0x07, 0x03, 0x01, 0xda, 0x05, 0x07, + 0x03, 0x01, 0xd0, 0x02, 0xd1, 0x02, 0xe6, 0x00, + 0x99, 0x02, 0x53, 0x02, 0x00, 0x00, 0xa3, 0x02, + 0x66, 0xab, 0xa5, 0x02, 0xa4, 0x02, 0x56, 0x02, + 0x57, 0x02, 0x91, 0x1d, 0x58, 0x02, 0x5e, 0x02, + 0xa9, 0x02, 0x64, 0x02, 0x62, 0x02, 0x60, 0x02, + 0x9b, 0x02, 0x27, 0x01, 0x9c, 0x02, 0x67, 0x02, + 0x84, 0x02, 0xaa, 0x02, 0xab, 0x02, 0x6c, 0x02, + 0x04, 0xdf, 0x8e, 0xa7, 0x6e, 0x02, 0x05, 0xdf, + 0x8e, 0x02, 0x06, 0xdf, 0xf8, 0x00, 0x76, 0x02, + 0x77, 0x02, 0x71, 0x00, 0x7a, 0x02, 0x08, 0xdf, + 0x7d, 0x02, 0x7e, 0x02, 0x80, 0x02, 0xa8, 0x02, + 0xa6, 0x02, 0x67, 0xab, 0xa7, 0x02, 0x88, 0x02, + 0x71, 0x2c, 0x00, 0x00, 0x8f, 0x02, 0xa1, 0x02, + 0xa2, 0x02, 0x98, 0x02, 0xc0, 0x01, 0xc1, 0x01, + 0xc2, 0x01, 0x0a, 0xdf, 0x1e, 0xdf, 0x41, 0x04, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x14, 0x99, 0x10, + 0xba, 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, + 0xba, 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, + 0x05, 0x31, 0x11, 0x27, 0x11, 0x32, 0x11, 0x27, + 0x11, 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, + 0x57, 0x13, 0x55, 0x82, 0x13, 0xc9, 0x13, 0x00, + 0x00, 0x00, 0x00, 0x84, 0x13, 0xbb, 0x13, 0x05, + 0x05, 0x8b, 0x13, 0xc2, 0x13, 0x05, 0x90, 0x13, + 0xc9, 0x13, 0x05, 0xc2, 0x13, 0xc2, 0x13, 0x00, + 0x00, 0x00, 0x00, 0xc2, 0x13, 0xb8, 0x13, 0xc2, + 0x13, 0xc9, 0x13, 0x05, 0x55, 0xb9, 0x14, 0xba, + 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, 0x00, + 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, 0xb8, + 0x15, 0xaf, 0x15, 0xb9, 0x15, 0xaf, 0x15, 0x55, + 0x35, 0x19, 0x30, 0x19, 0x05, 0x1e, 0x61, 0x1e, + 0x61, 0x1e, 0x61, 0x29, 0x61, 0x1e, 0x61, 0x1f, + 0x61, 0x29, 0x61, 0x1f, 0x61, 0x1e, 0x61, 0x20, + 0x61, 0x21, 0x61, 0x1f, 0x61, 0x22, 0x61, 0x1f, + 0x61, 0x21, 0x61, 0x20, 0x61, 0x55, 0x55, 0x55, + 0x55, 0x67, 0x6d, 0x67, 0x6d, 0x63, 0x6d, 0x67, + 0x6d, 0x69, 0x6d, 0x67, 0x6d, 0x55, 0x05, 0x41, + 0x00, 0x30, 0x00, 0x57, 0xd1, 0x65, 0xd1, 0x58, + 0xd1, 0x65, 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, + 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f, + 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, + 0x55, 0x55, 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, + 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc, + 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, + 0xd1, 0x6f, 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, + 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x69, 0x00, + 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, + 0x00, 0x00, 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, + 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, + 0x63, 0x64, 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, + 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, + 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, + 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, + 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, + 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, + 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, + 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, + 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, + 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, - 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, - 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, - 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00, + 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, - 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, 0x4b, 0x04, - 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, 0x30, 0x04, - 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, - 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, 0x25, 0x2f, - 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27, 0x06, 0x00, - 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e, 0x08, 0x03, - 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, - 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, - 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90, 0x77, 0x45, - 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06, - 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, 0x13, 0x00, - 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06, - 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, 0x06, - 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, 0x00, 0x00, - 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06, 0x00, 0x00, - 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x00, 0x00, - 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06, 0x00, 0x00, - 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x00, 0x00, - 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, 0x00, 0x00, - 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x37, 0x06, - 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, 0x45, 0x06, - 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x41, 0x06, - 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06, + 0x30, 0x00, 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, + 0x4b, 0x04, 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, + 0x30, 0x04, 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x0a, 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, + 0x25, 0x2f, 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27, + 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e, + 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c, + 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, + 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90, + 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, + 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, + 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, - 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, 0x6e, 0x06, - 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06, 0x00, 0x01, - 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, 0x10, 0x23, - 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, - 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, - 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, 0x06, 0x2f, - 0x06, 0x00, 0x00, 0x48, 0x06, 0x32, 0x06, 0x2d, - 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a, 0x06, 0x1a, - 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, - 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, - 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00, 0x28, 0x00, - 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, 0x53, 0x00, - 0x15, 0x30, 0x43, 0x52, 0x43, 0x44, 0x57, 0x5a, - 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56, 0x53, 0x44, - 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, 0x43, 0x4d, - 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44, 0x4a, 0x4b, - 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, 0x62, 0x57, - 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, 0x1a, - 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, 0x20, - 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, 0x52, 0x8c, - 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, 0x42, - 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, 0x39, - 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, 0x63, 0x00, - 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, 0x2d, - 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, 0x53, - 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, 0x54, 0x80, - 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, 0x72, - 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, 0x15, - 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, 0x4e, 0x89, - 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, 0xdd, - 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, 0x30, - 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09, 0x22, 0x01, - 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, 0x02, 0x50, - 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50, 0xcf, 0x50, - 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, 0x54, 0x51, - 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, 0xb9, 0x34, - 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05, 0x97, 0x51, - 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, 0xb5, 0x51, - 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, 0xdf, 0x34, - 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52, 0x77, 0x52, - 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, 0x80, 0x00, - 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, 0x02, 0x1d, - 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a, 0x93, 0xac, - 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, 0x70, 0x70, - 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, 0xeb, 0x53, - 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54, 0x38, 0x54, - 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, 0xf6, 0x54, - 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, 0x84, 0x55, - 0x84, 0x55, 0x99, 0x55, 0xab, 0x55, 0xb3, 0x55, - 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, 0x17, 0x57, - 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, 0xee, 0x58, - 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58, 0x8b, 0x57, - 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, 0xe4, 0x14, - 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, 0x1a, 0x59, - 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16, 0xea, 0x16, - 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, 0xd8, 0x59, - 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, 0x08, 0x5b, - 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19, 0xc3, 0x5b, - 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, 0x18, 0x1b, - 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, 0x22, 0x5c, - 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c, 0xc0, 0x5c, - 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, 0xe6, 0x1d, - 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, 0xe1, 0x5d, - 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d, 0x28, 0x5e, - 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, 0x83, 0x21, - 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, 0xb6, 0x5e, - 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e, 0x31, 0x23, - 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, 0x22, 0x5f, - 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, 0x62, 0x5f, - 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f, 0xcd, 0x5f, - 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, 0x3a, 0x39, - 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, 0xc7, 0x60, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x08, - 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, 0x80, 0x28, - 0x80, 0x02, 0x00, 0x00, 0x02, 0x48, 0x61, 0x00, - 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, 0x5c, 0x67, - 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, 0x62, 0x00, - 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d, 0x63, 0xfc, - 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, 0x63, 0xf1, - 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, 0x63, 0x2e, - 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d, 0x64, 0x77, - 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, 0x65, 0x0a, - 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, 0x66, 0x19, - 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4, 0x3a, 0x92, - 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, 0x66, 0xad, - 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, 0x67, 0x21, - 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3, 0x33, 0x49, - 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, 0x68, 0x85, - 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, 0x68, 0x14, - 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3, 0x69, 0xea, - 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, 0x6a, 0x18, - 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, 0x6b, 0x4e, - 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba, 0x6b, 0xbb, - 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, 0x3a, 0x4e, - 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, 0x6c, 0x67, - 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77, 0x6d, 0x41, - 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, 0x6d, 0x1e, - 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, 0x6e, 0x33, - 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, 0x3e, 0xf9, - 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, 0x3f, 0xc6, - 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, 0x70, 0x96, - 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77, 0x70, 0xad, - 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, 0x42, 0x9c, - 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, 0x72, 0x50, - 0x72, 0x08, 0x46, 0x80, 0x72, 0x95, 0x72, 0x35, - 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x02, - 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00, 0x08, 0x0a, - 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, 0x48, 0x7a, - 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, 0x73, 0xb8, - 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c, 0x74, 0x71, - 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, 0x3f, 0x24, - 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, 0x4c, 0x70, - 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1, 0x4f, 0xb8, - 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, 0x40, 0xf4, - 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, 0x51, 0x33, - 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f, 0x77, 0x4a, - 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, 0x40, 0x96, - 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, 0x78, 0xcc, - 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56, 0x79, 0x9a, - 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, 0x79, 0x2f, - 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, 0x7a, 0x7c, - 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee, 0x7a, 0x02, - 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, 0x7b, 0x27, - 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, 0x42, 0xe8, - 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86, 0x5f, 0x63, - 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, 0x7e, 0x45, - 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, 0x62, 0x59, - 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e, 0x63, 0x95, - 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, 0x64, 0x23, - 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, 0x80, 0x5f, - 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03, 0x81, 0x0b, - 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, 0x67, 0xb5, - 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, 0x82, 0x04, - 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91, 0x82, 0x8b, - 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, 0x82, 0xb3, - 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, 0x6b, 0xe5, - 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad, 0x83, 0x23, - 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, 0x84, 0x53, - 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, 0x83, 0x36, - 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00, 0x20, 0x22, - 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, 0x28, 0x00, - 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, 0x22, 0x02, - 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, 0x45, 0xf1, - 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, 0x73, 0x64, - 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61, 0x45, 0xb1, - 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, 0x86, 0x5c, - 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, 0x86, 0x88, - 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79, 0x87, 0x28, - 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, 0x45, 0xe1, - 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, 0x88, 0x63, - 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde, 0x88, 0x35, - 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, 0x78, 0x66, - 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, 0x8a, 0xed, - 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8, 0x7c, 0xab, - 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, 0x8d, 0x2f, - 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, 0x8d, 0xf0, - 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38, 0x8f, 0xd2, - 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, 0x90, 0x11, - 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, 0x92, 0xd7, - 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9, 0x93, 0x15, - 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, 0x49, 0xb7, - 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, 0x96, 0xb2, - 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a, 0x92, 0x6e, - 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, 0x94, 0xb2, - 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, 0x98, 0x29, - 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33, 0x4b, 0x29, - 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, 0x99, 0xce, - 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, 0x9c, 0xfd, - 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67, 0x9d, 0xce, - 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, 0xa2, 0x91, - 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, 0x9e, 0xfe, - 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16, 0x9f, 0x3b, - 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, 0x08, 0xa0, - 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80, 0x00, 0x0a, - 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, 0x2a, 0x00, - 0x80, + 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, + 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06, + 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, + 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, + 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06, + 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, + 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, + 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, + 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06, + 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, + 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, + 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, + 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, + 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, + 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06, + 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, + 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, + 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, + 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, + 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06, 0x32, + 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a, + 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, + 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, + 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00, + 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, + 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43, 0x44, + 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56, + 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, + 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44, + 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, + 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, + 0x4e, 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, + 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, + 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, + 0x52, 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, + 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, + 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, + 0x5d, 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, + 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, + 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, + 0x75, 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, + 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, + 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, + 0x76, 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, + 0x53, 0x30, 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09, + 0x22, 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, + 0x02, 0x50, 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50, + 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, + 0x54, 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, + 0xb9, 0x34, 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05, + 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, + 0xb5, 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, + 0xdf, 0x34, 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52, + 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, + 0x80, 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, + 0x02, 0x1d, 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a, + 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, + 0x70, 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, + 0xeb, 0x53, 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54, + 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, + 0xf6, 0x54, 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, + 0x84, 0x55, 0x84, 0x55, 0x99, 0x55, 0xab, 0x55, + 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, + 0x17, 0x57, 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, + 0xee, 0x58, 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58, + 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, + 0xe4, 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, + 0x1a, 0x59, 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16, + 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, + 0xd8, 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, + 0x08, 0x5b, 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19, + 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, + 0x18, 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, + 0x22, 0x5c, 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c, + 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, + 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, + 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d, + 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, + 0x83, 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, + 0xb6, 0x5e, 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e, + 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, + 0x22, 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, + 0x62, 0x5f, 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f, + 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, + 0x3a, 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, + 0xc7, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, + 0x02, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, + 0x80, 0x28, 0x80, 0x02, 0x00, 0x00, 0x02, 0x48, + 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, + 0x5c, 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, + 0x62, 0x00, 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d, + 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, + 0x63, 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, + 0x63, 0x2e, 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d, + 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, + 0x65, 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, + 0x66, 0x19, 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4, + 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, + 0x66, 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, + 0x67, 0x21, 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3, + 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, + 0x68, 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, + 0x68, 0x14, 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3, + 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, + 0x6a, 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, + 0x6b, 0x4e, 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba, + 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, + 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, + 0x6c, 0x67, 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77, + 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, + 0x6d, 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, + 0x6e, 0x33, 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, + 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, + 0x3f, 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, + 0x70, 0x96, 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77, + 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, + 0x42, 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, + 0x72, 0x50, 0x72, 0x08, 0x46, 0x80, 0x72, 0x95, + 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, + 0x02, 0x02, 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00, + 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, + 0x48, 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, + 0x73, 0xb8, 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c, + 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, + 0x3f, 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, + 0x4c, 0x70, 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1, + 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, + 0x40, 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, + 0x51, 0x33, 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f, + 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, + 0x40, 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, + 0x78, 0xcc, 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56, + 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, + 0x79, 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, + 0x7a, 0x7c, 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee, + 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, + 0x7b, 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, + 0x42, 0xe8, 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86, + 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, + 0x7e, 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, + 0x62, 0x59, 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e, + 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, + 0x64, 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, + 0x80, 0x5f, 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03, + 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, + 0x67, 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, + 0x82, 0x04, 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91, + 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, + 0x82, 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, + 0x6b, 0xe5, 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad, + 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, + 0x84, 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, + 0x83, 0x36, 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00, + 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, + 0x28, 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, + 0x22, 0x02, 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, + 0x45, 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, + 0x73, 0x64, 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61, + 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, + 0x86, 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, + 0x86, 0x88, 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79, + 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, + 0x45, 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, + 0x88, 0x63, 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde, + 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, + 0x78, 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, + 0x8a, 0xed, 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8, + 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, + 0x8d, 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, + 0x8d, 0xf0, 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38, + 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, + 0x90, 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, + 0x92, 0xd7, 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9, + 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, + 0x49, 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, + 0x96, 0xb2, 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a, + 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, + 0x94, 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, + 0x98, 0x29, 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33, + 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, + 0x99, 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, + 0x9c, 0xfd, 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67, + 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, + 0xa2, 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, + 0x9e, 0xfe, 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16, + 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, + 0x08, 0xa0, 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80, + 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, + 0x2a, 0x00, 0x80, }; -static const uint16_t unicode_comp_table[945] = { +static const uint16_t unicode_comp_table[965] = { 0x4a01, 0x49c0, 0x4a02, 0x0280, 0x0281, 0x0282, 0x0283, 0x02c0, 0x02c2, 0x0a00, 0x0284, 0x2442, 0x0285, 0x07c0, 0x0980, 0x0982, 0x2440, 0x2280, 0x02c4, 0x2282, 0x2284, 0x2286, 0x02c6, 0x02c8, @@ -2247,9 +2289,11 @@ static const uint16_t unicode_comp_table[945] = { 0x5704, 0x5706, 0x5708, 0x570a, 0x570c, 0x570e, 0x5710, 0x5712, 0x5714, 0x5716, 0x5740, 0x5742, 0x5744, 0x5780, 0x5781, 0x57c0, 0x57c1, 0x5800, 0x5801, 0x5840, 0x5841, 0x5880, 0x5881, 0x5900, - 0x5901, 0x5902, 0x5903, 0x5940, 0x8f40, 0x8f42, 0x8f80, 0x8fc0, - 0x8fc1, 0x9000, 0x9001, 0x9041, 0x9040, 0x9043, 0x9080, 0x9081, - 0x90c0, + 0x5901, 0x5902, 0x5903, 0x5940, 0x8ec0, 0x8f00, 0x8fc0, 0x8fc2, + 0x9000, 0x9040, 0x9041, 0x9080, 0x9081, 0x90c0, 0x90c2, 0x9100, + 0x9140, 0x9182, 0x9180, 0x9183, 0x91c1, 0x91c0, 0x91c3, 0x9200, + 0x9201, 0x9240, 0x9280, 0x9282, 0x9284, 0x9281, 0x9285, 0x9287, + 0x9286, 0x9283, 0x92c1, 0x92c0, 0x92c2, }; typedef enum { @@ -2335,7 +2379,7 @@ static const char unicode_gc_name_table[] = "C,Other" "\0" ; -static const uint8_t unicode_gc_table[3948] = { +static const uint8_t unicode_gc_table[4070] = { 0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, @@ -2379,8 +2423,8 @@ static const uint8_t unicode_gc_table[3948] = { 0x2d, 0xe5, 0x0e, 0x66, 0x04, 0xe6, 0x01, 0x04, 0x46, 0x04, 0x86, 0x20, 0xf6, 0x07, 0x00, 0xe5, 0x11, 0x46, 0x20, 0x16, 0x00, 0xe5, 0x03, 0x80, - 0xe5, 0x10, 0x0e, 0xa5, 0x00, 0x3b, 0xa0, 0xe6, - 0x00, 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6, + 0xe5, 0x10, 0x0e, 0xa5, 0x00, 0x3b, 0x80, 0xe6, + 0x01, 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6, 0x18, 0x07, 0xe5, 0x2e, 0x06, 0x07, 0x06, 0x05, 0x47, 0xe6, 0x00, 0x67, 0x06, 0x27, 0x05, 0xc6, 0xe5, 0x02, 0x26, 0x36, 0xe9, 0x02, 0x16, 0x04, @@ -2479,82 +2523,82 @@ static const uint8_t unicode_gc_table[3948] = { 0xe9, 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6, 0x06, 0x08, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07, 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, - 0x06, 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6, - 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00, + 0x06, 0x27, 0xe5, 0x00, 0x00, 0x36, 0xe9, 0x02, + 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x56, 0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06, 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, 0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45, 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, - 0xc0, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0, - 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65, - 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, 0x80, - 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2, - 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, 0x0e, - 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00, - 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00, - 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20, - 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20, - 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, - 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61, - 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61, - 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, 0x4e, - 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22, - 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1, - 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, 0x14, - 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01, - 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13, - 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, 0x17, - 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab, - 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12, - 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, 0xe0, - 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04, - 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02, - 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, 0x0c, - 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f, - 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f, - 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, 0x2f, - 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a, - 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c, - 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, 0x17, - 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec, - 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13, - 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, 0x49, - 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac, - 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d, - 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, 0x80, - 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec, - 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef, - 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13, + 0x3f, 0x80, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, + 0xe0, 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, + 0x65, 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, + 0x80, 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, + 0xe2, 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, + 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, + 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, + 0x00, 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, + 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, + 0x20, 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, + 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, + 0x61, 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, + 0x61, 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, + 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, + 0x22, 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, + 0xb1, 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, + 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, + 0x01, 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, + 0x13, 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, + 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, + 0xab, 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, + 0x12, 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, + 0xe0, 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, + 0x04, 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, + 0x02, 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, + 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, + 0x0f, 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, + 0x2f, 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, + 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, + 0x6a, 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, + 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, + 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, + 0xec, 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, + 0x13, 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, + 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, + 0xac, 0xef, 0x40, 0xe0, 0x0e, 0xef, 0x03, 0xe0, + 0x0d, 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, + 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, + 0xec, 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, + 0xef, 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12, - 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec, - 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, 0xac, - 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, 0x61, - 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, 0xdf, - 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41, - 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f, - 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02, - 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16, - 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, 0xc5, - 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, - 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6, - 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, 0x14, - 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36, - 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x96, - 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12, - 0xf6, 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 0xef, - 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80, - 0x4e, 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56, + 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, + 0x12, 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, + 0xec, 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, + 0xac, 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, + 0x61, 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, + 0xdf, 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, + 0x41, 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, + 0x3f, 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, + 0x02, 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, + 0x16, 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, + 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, + 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, + 0xe6, 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, + 0x14, 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, + 0x36, 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, + 0x96, 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, + 0x12, 0xf6, 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12, + 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, + 0xef, 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, + 0x80, 0x4e, 0xe0, 0x12, 0xef, 0x08, 0x17, 0x56, 0x0f, 0x04, 0x05, 0x0a, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, @@ -2563,146 +2607,154 @@ static const uint8_t unicode_gc_table[3948] = { 0xe5, 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11, 0xe5, 0x52, 0x16, 0x44, 0x05, 0x80, 0xe5, 0x23, 0x00, 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02, - 0xe5, 0x18, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08, - 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb, - 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02, - 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5, - 0x99, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d, - 0x04, 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0, - 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84, - 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0, - 0x0c, 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6, - 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5, - 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee, - 0x0f, 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff, - 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04, - 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, - 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, 0x3f, - 0x80, 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0, - 0x10, 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06, - 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26, - 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f, 0x0d, 0x0f, - 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, 0xe5, - 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, 0xe9, - 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, 0x05, 0x16, - 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, 0x00, - 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, 0x03, - 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, 0xe5, 0x27, - 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, 0xf6, 0x05, - 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, 0x06, - 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, 0x00, 0xe5, - 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, 0x01, - 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, 0xe9, - 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, 0xa5, 0x4f, - 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, 0x05, - 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, 0x05, - 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, 0x03, 0x07, - 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, 0xe0, - 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, 0x01, - 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, 0x0e, 0x64, - 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2, 0x48, 0xe5, - 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07, - 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5, 0xab, 0x1c, - 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60, - 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80, - 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e, 0xc2, 0xe0, - 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c, - 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25, - 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee, 0x09, 0xe0, - 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08, - 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0, - 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6, 0x08, 0xd6, - 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31, - 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0xe5, 0x18, 0xef, 0x1e, 0xe0, 0x01, 0x0f, 0xe5, + 0x08, 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, + 0xeb, 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, + 0x02, 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, + 0xe5, 0x99, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, + 0x8d, 0x04, 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, + 0xe0, 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, + 0x84, 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, + 0xe0, 0x0c, 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, + 0xe6, 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, + 0xe5, 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, + 0xee, 0x0f, 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, + 0xff, 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, + 0x04, 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, + 0x61, 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, + 0x5f, 0x3f, 0x20, 0x3f, 0x00, 0x02, 0x00, 0x02, + 0xdf, 0xe0, 0x0d, 0x44, 0x3f, 0x05, 0x24, 0x02, + 0xc5, 0x06, 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, + 0x27, 0x26, 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f, + 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, + 0x27, 0xe5, 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, + 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, + 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, + 0xe6, 0x00, 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, + 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, + 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, + 0xf6, 0x05, 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, + 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, + 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, + 0xe0, 0x01, 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, + 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, + 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, + 0x06, 0x05, 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, + 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, + 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, + 0x06, 0xe0, 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, + 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, + 0x0e, 0x64, 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2, + 0x48, 0xe5, 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27, + 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5, + 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, + 0x29, 0x60, 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78, + 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e, + 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, + 0x02, 0x0c, 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05, + 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee, + 0x09, 0xe0, 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, + 0xef, 0x08, 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, + 0x0f, 0xe0, 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6, + 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, + 0x16, 0x31, 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, 0x56, 0x00, - 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, 0x0d, 0x36, - 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00, - 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, - 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, - 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2, - 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16, - 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, 0xe5, 0x25, - 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20, - 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f, - 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, 0x02, 0x5b, - 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00, - 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20, - 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, 0x80, 0x56, - 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d, - 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x05, - 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25, 0x06, 0xe0, - 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07, - 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0, - 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, 0x0a, 0x80, - 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16, - 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0, - 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, 0x46, 0x20, - 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c, - 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0, - 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00, - 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2, - 0x07, 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5, - 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, - 0xe5, 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22, - 0x00, 0xe4, 0x01, 0xe0, 0x3d, 0xa5, 0x20, 0x05, - 0x00, 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20, - 0xe5, 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f, - 0x2f, 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01, - 0xe0, 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b, - 0xe5, 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80, - 0x16, 0xe0, 0x38, 0xe5, 0x30, 0x60, 0x2b, 0x25, - 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00, - 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5, - 0x15, 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, 0xc0, - 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5, - 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5, - 0x14, 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, 0xe5, - 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00, - 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0, - 0x76, 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, 0x41, - 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b, - 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9, - 0x02, 0xe0, 0x80, 0x9e, 0xeb, 0x17, 0x00, 0xe5, - 0x22, 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x43, - 0x46, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00, - 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e, - 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d, - 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07, - 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60, - 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05, - 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66, - 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02, - 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, - 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, - 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00, - 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, - 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, - 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, 0x05, - 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03, - 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27, - 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, 0xe0, - 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, 0xe5, - 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5, 0x27, - 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, 0xa0, - 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, 0x20, - 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x85, - 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, 0x27, - 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, 0x85, - 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x80, 0x03, - 0xe5, 0x2d, 0x47, 0xe6, 0x00, 0x27, 0x46, 0x07, - 0x06, 0x65, 0x96, 0xe9, 0x02, 0x36, 0x00, 0x16, - 0x06, 0x45, 0xe0, 0x16, 0xe5, 0x28, 0x47, 0xa6, - 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16, - 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e, - 0xe5, 0x27, 0x47, 0x66, 0x20, 0x67, 0x26, 0x07, - 0x26, 0xf6, 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5, - 0x28, 0x47, 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26, - 0x56, 0x05, 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6, - 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06, - 0x27, 0xa6, 0x07, 0x06, 0x05, 0x16, 0xa0, 0xe9, - 0x02, 0xe0, 0x2e, 0xe5, 0x13, 0x20, 0x46, 0x27, + 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, + 0x56, 0x00, 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, + 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, + 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, + 0x1b, 0x00, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, + 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, + 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, + 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, + 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, + 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, + 0xa5, 0x20, 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, + 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, + 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, + 0x12, 0x00, 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, + 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, + 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, + 0xea, 0x2d, 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, + 0xef, 0x05, 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25, + 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, + 0xe0, 0x07, 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, + 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, + 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, + 0x00, 0x16, 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, + 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, + 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, + 0xe2, 0x1c, 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, + 0x2c, 0xe0, 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1, + 0x07, 0x00, 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, + 0x00, 0xe2, 0x07, 0x00, 0xc2, 0x00, 0x22, 0x40, + 0xe5, 0x2c, 0xe0, 0x04, 0xe5, 0x80, 0xaf, 0xe0, + 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5, 0x00, 0xe0, + 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00, 0xe4, 0x01, + 0xe0, 0x3d, 0xa5, 0x20, 0x05, 0x00, 0xe5, 0x24, + 0x00, 0x25, 0x40, 0x05, 0x20, 0xe5, 0x0f, 0x00, + 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f, 0xcb, 0xe5, + 0x17, 0xe0, 0x00, 0xeb, 0x01, 0xe0, 0x28, 0xe5, + 0x0b, 0x00, 0x25, 0x80, 0x8b, 0xe5, 0x0e, 0xab, + 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16, 0xe0, 0x38, + 0xe5, 0x30, 0x60, 0x2b, 0x25, 0xeb, 0x08, 0x20, + 0xeb, 0x26, 0x05, 0x46, 0x00, 0x26, 0x80, 0x66, + 0x65, 0x00, 0x45, 0x00, 0xe5, 0x15, 0x20, 0x46, + 0x60, 0x06, 0xeb, 0x01, 0xc0, 0xf6, 0x01, 0xc0, + 0xe5, 0x15, 0x2b, 0x16, 0xe5, 0x15, 0x4b, 0xe0, + 0x18, 0xe5, 0x00, 0x0f, 0xe5, 0x14, 0x26, 0x60, + 0x8b, 0xd6, 0xe0, 0x01, 0xe5, 0x2e, 0x40, 0xd6, + 0xe5, 0x0e, 0x20, 0xeb, 0x00, 0xe5, 0x0b, 0x80, + 0xeb, 0x00, 0xe5, 0x0a, 0xc0, 0x76, 0xe0, 0x04, + 0xcb, 0xe0, 0x48, 0xe5, 0x41, 0xe0, 0x2f, 0xe1, + 0x2b, 0xe0, 0x05, 0xe2, 0x2b, 0xc0, 0xab, 0xe5, + 0x1c, 0x66, 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xe9, + 0x02, 0x65, 0x04, 0x05, 0xe1, 0x0e, 0x40, 0x86, + 0x11, 0x04, 0xe2, 0x0e, 0xe0, 0x00, 0x2c, 0xe0, + 0x80, 0x48, 0xeb, 0x17, 0x00, 0xe5, 0x22, 0x00, + 0x26, 0x11, 0x20, 0x25, 0xe0, 0x08, 0x45, 0xe0, + 0x2f, 0x66, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, + 0x00, 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, + 0x0e, 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, + 0x0d, 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, + 0x07, 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, + 0x60, 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, + 0x05, 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, + 0x66, 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, + 0x02, 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, + 0xa0, 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, + 0x00, 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, + 0x00, 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, + 0x26, 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, + 0x65, 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, + 0x05, 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, + 0x03, 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, + 0x27, 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, + 0xe0, 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, + 0xe5, 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5, + 0x27, 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, + 0xa0, 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, + 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, + 0x85, 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, + 0x27, 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, + 0x85, 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x03, + 0xe5, 0x02, 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, + 0x1e, 0x00, 0x05, 0x47, 0xa6, 0x00, 0x07, 0x20, + 0x07, 0x00, 0x67, 0x00, 0x27, 0x06, 0x07, 0x06, + 0x05, 0x06, 0x05, 0x36, 0x00, 0x36, 0xe0, 0x00, + 0x26, 0xe0, 0x15, 0xe5, 0x2d, 0x47, 0xe6, 0x00, + 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9, 0x02, + 0x36, 0x00, 0x16, 0x06, 0x45, 0xe0, 0x16, 0xe5, + 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26, 0x07, + 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9, 0x02, + 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66, 0x20, + 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65, 0x26, + 0xe0, 0x1a, 0xe5, 0x28, 0x47, 0xe6, 0x00, 0x27, + 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03, 0xe9, + 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5, 0x23, + 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06, 0x05, + 0x16, 0xa0, 0xe9, 0x02, 0xa0, 0xe9, 0x0c, 0xe0, + 0x14, 0xe5, 0x13, 0x20, 0x06, 0x07, 0x06, 0x27, 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56, 0x0f, 0xc5, 0xe0, 0x80, 0x31, 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1, @@ -2717,7 +2769,8 @@ static const uint8_t unicode_gc_table[3948] = { 0x05, 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05, 0xa6, 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07, 0x26, 0x56, 0x05, 0x96, 0xe0, 0x05, 0xe5, 0x41, - 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x6e, 0xe5, 0x01, + 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x2e, 0xe5, 0x19, + 0x16, 0xe0, 0x06, 0xe9, 0x02, 0xa0, 0xe5, 0x01, 0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, 0xa6, 0x07, 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02, 0xeb, 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6, 0x0e, @@ -2730,106 +2783,112 @@ static const uint8_t unicode_gc_table[3948] = { 0x80, 0xae, 0xe5, 0x0b, 0x26, 0x27, 0x36, 0xc0, 0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, 0xe5, 0x1a, 0x27, 0x86, 0x40, 0x27, 0x06, 0x07, 0x06, 0xf6, - 0x05, 0xe9, 0x02, 0xe0, 0x4e, 0x05, 0xe0, 0x07, - 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09, 0xe0, - 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea, - 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c, - 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05, - 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, 0xe6, - 0x07, 0xe0, 0x8f, 0x22, 0xe5, 0x81, 0xbf, 0xe0, - 0xa1, 0x31, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, - 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00, - 0xe9, 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16, - 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64, - 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, - 0x00, 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x82, - 0x28, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f, 0x76, - 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, 0xe7, - 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38, 0x24, - 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0, 0x06, - 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, 0x4e, - 0xe0, 0x22, 0xe5, 0x01, 0xe0, 0xa2, 0x5f, 0x64, - 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, 0x9b, - 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, 0x05, - 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04, - 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05, - 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, 0x0f, - 0x26, 0x16, 0x7b, 0xe0, 0x91, 0xd4, 0xe6, 0x26, - 0x20, 0xe6, 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0, - 0x34, 0xef, 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f, - 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb, - 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66, - 0xef, 0x35, 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f, - 0xe0, 0x72, 0xeb, 0x0c, 0xe0, 0x04, 0xeb, 0x0c, - 0xe0, 0x04, 0xef, 0x4f, 0xe0, 0x01, 0xeb, 0x11, - 0xe0, 0x7f, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, - 0xc2, 0x00, 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12, - 0x01, 0x00, 0x21, 0x20, 0x01, 0x20, 0x21, 0x20, - 0x61, 0x00, 0xe1, 0x00, 0x62, 0x00, 0x02, 0x00, - 0xc2, 0x00, 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12, - 0x21, 0x00, 0x61, 0x20, 0xe1, 0x00, 0x00, 0xc1, - 0x00, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x00, 0x81, - 0x00, 0x01, 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1, + 0x05, 0xe9, 0x02, 0x06, 0xe0, 0x4d, 0x05, 0xe0, + 0x07, 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09, + 0xe0, 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, + 0xea, 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80, + 0x3c, 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, + 0x05, 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, + 0xe6, 0x07, 0xe0, 0x02, 0xe5, 0x8f, 0x13, 0x80, + 0xe5, 0x81, 0xbf, 0xe0, 0x9a, 0x31, 0xe5, 0x16, + 0xe6, 0x04, 0x47, 0x46, 0xe9, 0x02, 0xe0, 0x86, + 0x3e, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, 0x00, + 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00, 0xe9, + 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16, 0xe0, + 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64, 0x16, + 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, 0x00, + 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x81, 0x28, + 0x44, 0xe5, 0x20, 0x24, 0x56, 0xe9, 0x02, 0xe0, + 0x80, 0x3e, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f, + 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, + 0xe7, 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38, + 0x24, 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0, + 0x06, 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, + 0x4e, 0xe0, 0x21, 0xe5, 0x02, 0xe0, 0xa2, 0x5f, + 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, + 0x9b, 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, + 0x05, 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81, + 0x04, 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, + 0x05, 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, + 0x0f, 0x26, 0x16, 0x7b, 0xe0, 0x8e, 0xd4, 0xef, + 0x80, 0x68, 0xe9, 0x02, 0xa0, 0xef, 0x81, 0x2c, + 0xe0, 0x44, 0xe6, 0x26, 0x20, 0xe6, 0x0f, 0xe0, + 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef, 0x80, 0x6e, + 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, 0x34, 0x27, + 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6, 0x00, 0x2f, + 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35, 0xe0, 0x0d, + 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x72, 0xeb, 0x0c, + 0xe0, 0x04, 0xeb, 0x0c, 0xe0, 0x04, 0xef, 0x4f, + 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, 0xe1, 0x12, + 0xe2, 0x12, 0xe1, 0x12, 0xc2, 0x00, 0xe2, 0x0a, + 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, 0x21, 0x20, + 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, 0xe1, 0x00, + 0x62, 0x00, 0x02, 0x00, 0xc2, 0x00, 0xe2, 0x03, + 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x20, + 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, 0x12, 0x21, + 0x00, 0x61, 0x00, 0x81, 0x00, 0x01, 0x40, 0xc1, + 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, - 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20, - 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, - 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, - 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, - 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, - 0x11, 0x0c, 0xa2, 0x3f, 0x20, 0xe9, 0x2a, 0xef, - 0x81, 0x78, 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef, - 0x00, 0x06, 0xef, 0x06, 0x06, 0x2f, 0x96, 0xe0, - 0x07, 0x86, 0x00, 0xe6, 0x07, 0xe0, 0x83, 0xc8, - 0xe2, 0x02, 0x05, 0xe2, 0x0c, 0xa0, 0xa2, 0xe0, - 0x80, 0x4d, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6, - 0x00, 0x26, 0x00, 0x86, 0x80, 0xe4, 0x36, 0xe0, - 0x19, 0x06, 0xe0, 0x68, 0xe5, 0x25, 0x40, 0xc6, - 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, 0x0f, 0xe0, - 0x80, 0xb8, 0xe5, 0x16, 0x06, 0xe0, 0x09, 0xe5, - 0x24, 0x66, 0xe9, 0x02, 0x80, 0x0d, 0xe0, 0x81, - 0x48, 0xe5, 0x13, 0x04, 0x66, 0xe9, 0x02, 0xe0, - 0x82, 0x5e, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00, - 0xe5, 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb, - 0x01, 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a, - 0xc6, 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0, - 0x82, 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, - 0xe0, 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0, - 0x80, 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, - 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, - 0x65, 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60, - 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, - 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00, - 0x05, 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, - 0x65, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, - 0x09, 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09, - 0xe0, 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, - 0x60, 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, - 0xef, 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d, - 0xe0, 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0, - 0x30, 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, - 0xef, 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, - 0x80, 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82, - 0x50, 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40, - 0xef, 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04, - 0x60, 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef, - 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, - 0xe0, 0x00, 0xef, 0x16, 0x20, 0x2f, 0xe0, 0x46, - 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, 0x06, 0x20, - 0xef, 0x05, 0x40, 0xef, 0x01, 0xc0, 0xef, 0x26, - 0x00, 0xcf, 0xe0, 0x00, 0xef, 0x06, 0x60, 0xef, - 0x01, 0xc0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b, - 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02, 0xe0, - 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0, 0x18, - 0xe5, 0x8f, 0xb2, 0xa0, 0xe5, 0x80, 0x56, 0x20, - 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, 0xa9, - 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0, 0x85, - 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, 0x8f, 0xd8, - 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, 0x16, 0xfb, - 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0, - 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd, - 0xc0, 0xbf, 0x76, 0x20, + 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, 0x0c, 0xe2, + 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, + 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, + 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, + 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0x3f, + 0x20, 0xe9, 0x2a, 0xef, 0x81, 0x78, 0xe6, 0x2f, + 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, 0xef, 0x06, + 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, 0x00, 0xe6, + 0x07, 0xe0, 0x83, 0xc8, 0xe2, 0x02, 0x05, 0xe2, + 0x0c, 0xa0, 0xa2, 0xe0, 0x80, 0x4d, 0xc6, 0x00, + 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, 0x00, 0x86, + 0x80, 0xe4, 0x36, 0xe0, 0x19, 0x06, 0xe0, 0x68, + 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02, + 0x60, 0x05, 0x0f, 0xe0, 0x80, 0xb8, 0xe5, 0x16, + 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, 0xe9, 0x02, + 0x80, 0x0d, 0xe0, 0x81, 0x48, 0xe5, 0x13, 0x04, + 0x66, 0xe9, 0x02, 0xe0, 0x80, 0x4e, 0xe5, 0x16, + 0x26, 0x05, 0xe9, 0x02, 0x60, 0x16, 0xe0, 0x81, + 0x58, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00, 0xe5, + 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb, 0x01, + 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a, 0xc6, + 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0, 0x82, + 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, 0xe0, + 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0, 0x80, + 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, 0x00, + 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, 0x65, + 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60, 0x05, + 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, 0x25, + 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, 0x05, + 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00, 0x05, + 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, 0x65, + 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, 0x09, + 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09, 0xe0, + 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, 0x60, + 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, 0xef, + 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d, 0xe0, + 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0, 0x30, + 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, 0xef, + 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, 0x80, + 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82, 0x50, + 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40, 0xef, + 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04, 0x60, + 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef, 0x30, + 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, 0xe0, + 0x00, 0xef, 0x16, 0x20, 0xef, 0x04, 0x60, 0x2f, + 0xe0, 0x36, 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, + 0x06, 0x20, 0xef, 0x05, 0x40, 0xef, 0x02, 0x80, + 0xef, 0x30, 0xc0, 0xef, 0x07, 0x20, 0xef, 0x03, + 0xa0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b, 0x00, + 0xef, 0x54, 0xe9, 0x02, 0xe0, 0x83, 0x7e, 0xe5, + 0xc0, 0x66, 0x58, 0xe0, 0x18, 0xe5, 0x8f, 0xb2, + 0xa0, 0xe5, 0x80, 0x56, 0x20, 0xe5, 0x95, 0xfa, + 0xe0, 0x06, 0xe5, 0x9c, 0xa9, 0xe0, 0x07, 0xe5, + 0x81, 0xe6, 0xe0, 0x89, 0x1a, 0xe5, 0x81, 0x96, + 0xe0, 0x85, 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, + 0x8f, 0xd8, 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, + 0x16, 0xfb, 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, + 0xe0, 0xc0, 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, + 0x20, 0xfd, 0xc0, 0xbf, 0x76, 0x20, }; typedef enum { @@ -2876,11 +2935,13 @@ typedef enum { UNICODE_SCRIPT_Georgian, UNICODE_SCRIPT_Glagolitic, UNICODE_SCRIPT_Gothic, + UNICODE_SCRIPT_Garay, UNICODE_SCRIPT_Grantha, UNICODE_SCRIPT_Greek, UNICODE_SCRIPT_Gujarati, UNICODE_SCRIPT_Gunjala_Gondi, UNICODE_SCRIPT_Gurmukhi, + UNICODE_SCRIPT_Gurung_Khema, UNICODE_SCRIPT_Han, UNICODE_SCRIPT_Hangul, UNICODE_SCRIPT_Hanifi_Rohingya, @@ -2903,6 +2964,7 @@ typedef enum { UNICODE_SCRIPT_Khojki, UNICODE_SCRIPT_Khitan_Small_Script, UNICODE_SCRIPT_Khudawadi, + UNICODE_SCRIPT_Kirat_Rai, UNICODE_SCRIPT_Lao, UNICODE_SCRIPT_Latin, UNICODE_SCRIPT_Lepcha, @@ -2940,6 +3002,7 @@ typedef enum { UNICODE_SCRIPT_Nyiakeng_Puachue_Hmong, UNICODE_SCRIPT_Ogham, UNICODE_SCRIPT_Ol_Chiki, + UNICODE_SCRIPT_Ol_Onal, UNICODE_SCRIPT_Old_Hungarian, UNICODE_SCRIPT_Old_Italic, UNICODE_SCRIPT_Old_North_Arabian, @@ -2971,6 +3034,7 @@ typedef enum { UNICODE_SCRIPT_Sora_Sompeng, UNICODE_SCRIPT_Soyombo, UNICODE_SCRIPT_Sundanese, + UNICODE_SCRIPT_Sunuwar, UNICODE_SCRIPT_Syloti_Nagri, UNICODE_SCRIPT_Syriac, UNICODE_SCRIPT_Tagalog, @@ -2988,7 +3052,9 @@ typedef enum { UNICODE_SCRIPT_Tifinagh, UNICODE_SCRIPT_Tirhuta, UNICODE_SCRIPT_Tangsa, + UNICODE_SCRIPT_Todhri, UNICODE_SCRIPT_Toto, + UNICODE_SCRIPT_Tulu_Tigalari, UNICODE_SCRIPT_Ugaritic, UNICODE_SCRIPT_Vai, UNICODE_SCRIPT_Vithkuqi, @@ -3043,11 +3109,13 @@ static const char unicode_script_name_table[] = "Georgian,Geor" "\0" "Glagolitic,Glag" "\0" "Gothic,Goth" "\0" + "Garay,Gara" "\0" "Grantha,Gran" "\0" "Greek,Grek" "\0" "Gujarati,Gujr" "\0" "Gunjala_Gondi,Gong" "\0" "Gurmukhi,Guru" "\0" + "Gurung_Khema,Gukh" "\0" "Han,Hani" "\0" "Hangul,Hang" "\0" "Hanifi_Rohingya,Rohg" "\0" @@ -3070,6 +3138,7 @@ static const char unicode_script_name_table[] = "Khojki,Khoj" "\0" "Khitan_Small_Script,Kits" "\0" "Khudawadi,Sind" "\0" + "Kirat_Rai,Krai" "\0" "Lao,Laoo" "\0" "Latin,Latn" "\0" "Lepcha,Lepc" "\0" @@ -3107,6 +3176,7 @@ static const char unicode_script_name_table[] = "Nyiakeng_Puachue_Hmong,Hmnp" "\0" "Ogham,Ogam" "\0" "Ol_Chiki,Olck" "\0" + "Ol_Onal,Onao" "\0" "Old_Hungarian,Hung" "\0" "Old_Italic,Ital" "\0" "Old_North_Arabian,Narb" "\0" @@ -3138,6 +3208,7 @@ static const char unicode_script_name_table[] = "Sora_Sompeng,Sora" "\0" "Soyombo,Soyo" "\0" "Sundanese,Sund" "\0" + "Sunuwar,Sunu" "\0" "Syloti_Nagri,Sylo" "\0" "Syriac,Syrc" "\0" "Tagalog,Tglg" "\0" @@ -3155,7 +3226,9 @@ static const char unicode_script_name_table[] = "Tifinagh,Tfng" "\0" "Tirhuta,Tirh" "\0" "Tangsa,Tnsa" "\0" + "Todhri,Todr" "\0" "Toto,Toto" "\0" + "Tulu_Tigalari,Tutg" "\0" "Ugaritic,Ugar" "\0" "Vai,Vaii" "\0" "Vithkuqi,Vith" "\0" @@ -3166,87 +3239,87 @@ static const char unicode_script_name_table[] = "Zanabazar_Square,Zanb" "\0" ; -static const uint8_t unicode_script_table[2720] = { - 0xc0, 0x19, 0x99, 0x47, 0x85, 0x19, 0x99, 0x47, - 0xae, 0x19, 0x80, 0x47, 0x8e, 0x19, 0x80, 0x47, - 0x84, 0x19, 0x96, 0x47, 0x80, 0x19, 0x9e, 0x47, - 0x80, 0x19, 0xe1, 0x60, 0x47, 0xa6, 0x19, 0x84, - 0x47, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0, - 0x0f, 0x38, 0x83, 0x2c, 0x80, 0x19, 0x82, 0x2c, - 0x01, 0x83, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x03, - 0x80, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x80, 0x19, - 0x82, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x93, 0x2c, - 0x00, 0xbe, 0x2c, 0x8d, 0x1a, 0x8f, 0x2c, 0xe0, - 0x24, 0x1d, 0x81, 0x38, 0xe0, 0x48, 0x1d, 0x00, +static const uint8_t unicode_script_table[2803] = { + 0xc0, 0x19, 0x99, 0x4a, 0x85, 0x19, 0x99, 0x4a, + 0xae, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x80, 0x4a, + 0x84, 0x19, 0x96, 0x4a, 0x80, 0x19, 0x9e, 0x4a, + 0x80, 0x19, 0xe1, 0x60, 0x4a, 0xa6, 0x19, 0x84, + 0x4a, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0, + 0x0f, 0x3a, 0x83, 0x2d, 0x80, 0x19, 0x82, 0x2d, + 0x01, 0x83, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x03, + 0x80, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x80, 0x19, + 0x82, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x93, 0x2d, + 0x00, 0xbe, 0x2d, 0x8d, 0x1a, 0x8f, 0x2d, 0xe0, + 0x24, 0x1d, 0x81, 0x3a, 0xe0, 0x48, 0x1d, 0x00, 0xa5, 0x05, 0x01, 0xb1, 0x05, 0x01, 0x82, 0x05, - 0x00, 0xb6, 0x35, 0x07, 0x9a, 0x35, 0x03, 0x85, - 0x35, 0x0a, 0x84, 0x04, 0x80, 0x19, 0x85, 0x04, + 0x00, 0xb6, 0x37, 0x07, 0x9a, 0x37, 0x03, 0x85, + 0x37, 0x0a, 0x84, 0x04, 0x80, 0x19, 0x85, 0x04, 0x80, 0x19, 0x8d, 0x04, 0x80, 0x19, 0x82, 0x04, 0x80, 0x19, 0x9f, 0x04, 0x80, 0x19, 0x89, 0x04, - 0x8a, 0x38, 0x99, 0x04, 0x80, 0x38, 0xe0, 0x0b, - 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x8b, 0x00, - 0xbb, 0x8b, 0x01, 0x82, 0x8b, 0xaf, 0x04, 0xb1, - 0x95, 0x0d, 0xba, 0x66, 0x01, 0x82, 0x66, 0xad, - 0x7f, 0x01, 0x8e, 0x7f, 0x00, 0x9b, 0x52, 0x01, - 0x80, 0x52, 0x00, 0x8a, 0x8b, 0x04, 0x9e, 0x04, - 0x00, 0x81, 0x04, 0x05, 0xc9, 0x04, 0x80, 0x19, - 0x9c, 0x04, 0xd0, 0x20, 0x83, 0x38, 0x8e, 0x20, + 0x8a, 0x3a, 0x99, 0x04, 0x80, 0x3a, 0xe0, 0x0b, + 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x90, 0x00, + 0xbb, 0x90, 0x01, 0x82, 0x90, 0xaf, 0x04, 0xb1, + 0x9a, 0x0d, 0xba, 0x69, 0x01, 0x82, 0x69, 0xad, + 0x83, 0x01, 0x8e, 0x83, 0x00, 0x9b, 0x55, 0x01, + 0x80, 0x55, 0x00, 0x8a, 0x90, 0x04, 0x9e, 0x04, + 0x00, 0x81, 0x04, 0x04, 0xca, 0x04, 0x80, 0x19, + 0x9c, 0x04, 0xd0, 0x20, 0x83, 0x3a, 0x8e, 0x20, 0x81, 0x19, 0x99, 0x20, 0x83, 0x0b, 0x00, 0x87, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x95, 0x0b, 0x00, 0x86, 0x0b, 0x00, 0x80, 0x0b, 0x02, 0x83, 0x0b, 0x01, 0x88, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x83, 0x0b, 0x07, 0x80, 0x0b, 0x03, 0x81, 0x0b, 0x00, - 0x84, 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x2f, - 0x00, 0x85, 0x2f, 0x03, 0x81, 0x2f, 0x01, 0x95, - 0x2f, 0x00, 0x86, 0x2f, 0x00, 0x81, 0x2f, 0x00, - 0x81, 0x2f, 0x00, 0x81, 0x2f, 0x01, 0x80, 0x2f, - 0x00, 0x84, 0x2f, 0x03, 0x81, 0x2f, 0x01, 0x82, - 0x2f, 0x02, 0x80, 0x2f, 0x06, 0x83, 0x2f, 0x00, - 0x80, 0x2f, 0x06, 0x90, 0x2f, 0x09, 0x82, 0x2d, - 0x00, 0x88, 0x2d, 0x00, 0x82, 0x2d, 0x00, 0x95, - 0x2d, 0x00, 0x86, 0x2d, 0x00, 0x81, 0x2d, 0x00, - 0x84, 0x2d, 0x01, 0x89, 0x2d, 0x00, 0x82, 0x2d, - 0x00, 0x82, 0x2d, 0x01, 0x80, 0x2d, 0x0e, 0x83, - 0x2d, 0x01, 0x8b, 0x2d, 0x06, 0x86, 0x2d, 0x00, - 0x82, 0x74, 0x00, 0x87, 0x74, 0x01, 0x81, 0x74, - 0x01, 0x95, 0x74, 0x00, 0x86, 0x74, 0x00, 0x81, - 0x74, 0x00, 0x84, 0x74, 0x01, 0x88, 0x74, 0x01, - 0x81, 0x74, 0x01, 0x82, 0x74, 0x06, 0x82, 0x74, - 0x03, 0x81, 0x74, 0x00, 0x84, 0x74, 0x01, 0x91, - 0x74, 0x09, 0x81, 0x92, 0x00, 0x85, 0x92, 0x02, - 0x82, 0x92, 0x00, 0x83, 0x92, 0x02, 0x81, 0x92, - 0x00, 0x80, 0x92, 0x00, 0x81, 0x92, 0x02, 0x81, - 0x92, 0x02, 0x82, 0x92, 0x02, 0x8b, 0x92, 0x03, - 0x84, 0x92, 0x02, 0x82, 0x92, 0x00, 0x83, 0x92, - 0x01, 0x80, 0x92, 0x05, 0x80, 0x92, 0x0d, 0x94, - 0x92, 0x04, 0x8c, 0x94, 0x00, 0x82, 0x94, 0x00, - 0x96, 0x94, 0x00, 0x8f, 0x94, 0x01, 0x88, 0x94, - 0x00, 0x82, 0x94, 0x00, 0x83, 0x94, 0x06, 0x81, - 0x94, 0x00, 0x82, 0x94, 0x01, 0x80, 0x94, 0x01, - 0x83, 0x94, 0x01, 0x89, 0x94, 0x06, 0x88, 0x94, - 0x8c, 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x96, 0x3d, - 0x00, 0x89, 0x3d, 0x00, 0x84, 0x3d, 0x01, 0x88, - 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x83, 0x3d, 0x06, - 0x81, 0x3d, 0x05, 0x81, 0x3d, 0x00, 0x83, 0x3d, - 0x01, 0x89, 0x3d, 0x00, 0x82, 0x3d, 0x0b, 0x8c, - 0x51, 0x00, 0x82, 0x51, 0x00, 0xb2, 0x51, 0x00, - 0x82, 0x51, 0x00, 0x85, 0x51, 0x03, 0x8f, 0x51, - 0x01, 0x99, 0x51, 0x00, 0x82, 0x85, 0x00, 0x91, - 0x85, 0x02, 0x97, 0x85, 0x00, 0x88, 0x85, 0x00, - 0x80, 0x85, 0x01, 0x86, 0x85, 0x02, 0x80, 0x85, - 0x03, 0x85, 0x85, 0x00, 0x80, 0x85, 0x00, 0x87, - 0x85, 0x05, 0x89, 0x85, 0x01, 0x82, 0x85, 0x0b, - 0xb9, 0x96, 0x03, 0x80, 0x19, 0x9b, 0x96, 0x24, - 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46, - 0x00, 0x97, 0x46, 0x00, 0x80, 0x46, 0x00, 0x96, - 0x46, 0x01, 0x84, 0x46, 0x00, 0x80, 0x46, 0x00, - 0x86, 0x46, 0x00, 0x89, 0x46, 0x01, 0x83, 0x46, - 0x1f, 0xc7, 0x97, 0x00, 0xa3, 0x97, 0x03, 0xa6, - 0x97, 0x00, 0xa3, 0x97, 0x00, 0x8e, 0x97, 0x00, - 0x86, 0x97, 0x83, 0x19, 0x81, 0x97, 0x24, 0xe0, - 0x3f, 0x60, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, + 0x84, 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x30, + 0x00, 0x85, 0x30, 0x03, 0x81, 0x30, 0x01, 0x95, + 0x30, 0x00, 0x86, 0x30, 0x00, 0x81, 0x30, 0x00, + 0x81, 0x30, 0x00, 0x81, 0x30, 0x01, 0x80, 0x30, + 0x00, 0x84, 0x30, 0x03, 0x81, 0x30, 0x01, 0x82, + 0x30, 0x02, 0x80, 0x30, 0x06, 0x83, 0x30, 0x00, + 0x80, 0x30, 0x06, 0x90, 0x30, 0x09, 0x82, 0x2e, + 0x00, 0x88, 0x2e, 0x00, 0x82, 0x2e, 0x00, 0x95, + 0x2e, 0x00, 0x86, 0x2e, 0x00, 0x81, 0x2e, 0x00, + 0x84, 0x2e, 0x01, 0x89, 0x2e, 0x00, 0x82, 0x2e, + 0x00, 0x82, 0x2e, 0x01, 0x80, 0x2e, 0x0e, 0x83, + 0x2e, 0x01, 0x8b, 0x2e, 0x06, 0x86, 0x2e, 0x00, + 0x82, 0x78, 0x00, 0x87, 0x78, 0x01, 0x81, 0x78, + 0x01, 0x95, 0x78, 0x00, 0x86, 0x78, 0x00, 0x81, + 0x78, 0x00, 0x84, 0x78, 0x01, 0x88, 0x78, 0x01, + 0x81, 0x78, 0x01, 0x82, 0x78, 0x06, 0x82, 0x78, + 0x03, 0x81, 0x78, 0x00, 0x84, 0x78, 0x01, 0x91, + 0x78, 0x09, 0x81, 0x97, 0x00, 0x85, 0x97, 0x02, + 0x82, 0x97, 0x00, 0x83, 0x97, 0x02, 0x81, 0x97, + 0x00, 0x80, 0x97, 0x00, 0x81, 0x97, 0x02, 0x81, + 0x97, 0x02, 0x82, 0x97, 0x02, 0x8b, 0x97, 0x03, + 0x84, 0x97, 0x02, 0x82, 0x97, 0x00, 0x83, 0x97, + 0x01, 0x80, 0x97, 0x05, 0x80, 0x97, 0x0d, 0x94, + 0x97, 0x04, 0x8c, 0x99, 0x00, 0x82, 0x99, 0x00, + 0x96, 0x99, 0x00, 0x8f, 0x99, 0x01, 0x88, 0x99, + 0x00, 0x82, 0x99, 0x00, 0x83, 0x99, 0x06, 0x81, + 0x99, 0x00, 0x82, 0x99, 0x01, 0x80, 0x99, 0x01, + 0x83, 0x99, 0x01, 0x89, 0x99, 0x06, 0x88, 0x99, + 0x8c, 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x96, 0x3f, + 0x00, 0x89, 0x3f, 0x00, 0x84, 0x3f, 0x01, 0x88, + 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x83, 0x3f, 0x06, + 0x81, 0x3f, 0x05, 0x81, 0x3f, 0x00, 0x83, 0x3f, + 0x01, 0x89, 0x3f, 0x00, 0x82, 0x3f, 0x0b, 0x8c, + 0x54, 0x00, 0x82, 0x54, 0x00, 0xb2, 0x54, 0x00, + 0x82, 0x54, 0x00, 0x85, 0x54, 0x03, 0x8f, 0x54, + 0x01, 0x99, 0x54, 0x00, 0x82, 0x89, 0x00, 0x91, + 0x89, 0x02, 0x97, 0x89, 0x00, 0x88, 0x89, 0x00, + 0x80, 0x89, 0x01, 0x86, 0x89, 0x02, 0x80, 0x89, + 0x03, 0x85, 0x89, 0x00, 0x80, 0x89, 0x00, 0x87, + 0x89, 0x05, 0x89, 0x89, 0x01, 0x82, 0x89, 0x0b, + 0xb9, 0x9b, 0x03, 0x80, 0x19, 0x9b, 0x9b, 0x24, + 0x81, 0x49, 0x00, 0x80, 0x49, 0x00, 0x84, 0x49, + 0x00, 0x97, 0x49, 0x00, 0x80, 0x49, 0x00, 0x96, + 0x49, 0x01, 0x84, 0x49, 0x00, 0x80, 0x49, 0x00, + 0x86, 0x49, 0x00, 0x89, 0x49, 0x01, 0x83, 0x49, + 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, 0x31, 0xc8, 0x27, 0x00, 0x83, + 0x28, 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, @@ -3254,366 +3327,430 @@ static const uint8_t unicode_script_table[2720] = { 0x8e, 0x27, 0x00, 0xb8, 0x27, 0x00, 0x83, 0x27, 0x01, 0xc2, 0x27, 0x01, 0x9f, 0x27, 0x02, 0x99, 0x27, 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01, - 0xe2, 0x1f, 0x12, 0x9c, 0x69, 0x02, 0xca, 0x7e, - 0x82, 0x19, 0x8a, 0x7e, 0x06, 0x95, 0x8c, 0x08, - 0x80, 0x8c, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93, - 0x11, 0x0b, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00, - 0x81, 0x8d, 0x0b, 0xdd, 0x42, 0x01, 0x89, 0x42, - 0x05, 0x89, 0x42, 0x05, 0x81, 0x5d, 0x81, 0x19, - 0x80, 0x5d, 0x80, 0x19, 0x93, 0x5d, 0x05, 0xd8, - 0x5d, 0x06, 0xaa, 0x5d, 0x04, 0xc5, 0x12, 0x09, - 0x9e, 0x49, 0x00, 0x8b, 0x49, 0x03, 0x8b, 0x49, - 0x03, 0x80, 0x49, 0x02, 0x8b, 0x49, 0x9d, 0x8e, - 0x01, 0x84, 0x8e, 0x0a, 0xab, 0x64, 0x03, 0x99, - 0x64, 0x05, 0x8a, 0x64, 0x02, 0x81, 0x64, 0x9f, - 0x42, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8f, - 0x00, 0x9c, 0x8f, 0x01, 0x8a, 0x8f, 0x05, 0x89, - 0x8f, 0x05, 0x8d, 0x8f, 0x01, 0x9e, 0x38, 0x30, - 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x89, - 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x48, 0x02, - 0x8e, 0x48, 0x02, 0x82, 0x48, 0xaf, 0x6a, 0x88, - 0x1d, 0x06, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87, - 0x89, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38, - 0x80, 0x19, 0x86, 0x38, 0x83, 0x19, 0x80, 0x38, - 0x85, 0x19, 0x80, 0x38, 0x82, 0x19, 0x81, 0x38, - 0x80, 0x19, 0x04, 0xa5, 0x47, 0x84, 0x2c, 0x80, - 0x1d, 0xb0, 0x47, 0x84, 0x2c, 0x83, 0x47, 0x84, - 0x2c, 0x8c, 0x47, 0x80, 0x1d, 0xc5, 0x47, 0x80, - 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x47, 0x95, 0x2c, - 0x01, 0x85, 0x2c, 0x01, 0xa5, 0x2c, 0x01, 0x85, - 0x2c, 0x01, 0x87, 0x2c, 0x00, 0x80, 0x2c, 0x00, - 0x80, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x9e, 0x2c, - 0x01, 0xb4, 0x2c, 0x00, 0x8e, 0x2c, 0x00, 0x8d, - 0x2c, 0x01, 0x85, 0x2c, 0x00, 0x92, 0x2c, 0x01, - 0x82, 0x2c, 0x00, 0x88, 0x2c, 0x00, 0x8b, 0x19, - 0x81, 0x38, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80, - 0x47, 0x01, 0x8a, 0x19, 0x80, 0x47, 0x8e, 0x19, - 0x00, 0x8c, 0x47, 0x02, 0xa0, 0x19, 0x0e, 0xa0, - 0x38, 0x0e, 0xa5, 0x19, 0x80, 0x2c, 0x82, 0x19, - 0x81, 0x47, 0x85, 0x19, 0x80, 0x47, 0x9a, 0x19, - 0x80, 0x47, 0x90, 0x19, 0xa8, 0x47, 0x82, 0x19, - 0x03, 0xe2, 0x36, 0x19, 0x18, 0x8a, 0x19, 0x14, - 0xe3, 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, - 0x19, 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19, - 0xdf, 0x29, 0x9f, 0x47, 0xe0, 0x13, 0x1a, 0x04, - 0x86, 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, - 0x80, 0x28, 0x01, 0xb7, 0x98, 0x06, 0x81, 0x98, - 0x0d, 0x80, 0x98, 0x96, 0x27, 0x08, 0x86, 0x27, + 0xe2, 0x1f, 0x12, 0x9c, 0x6c, 0x02, 0xca, 0x82, + 0x82, 0x19, 0x8a, 0x82, 0x06, 0x95, 0x91, 0x08, + 0x80, 0x91, 0x94, 0x35, 0x81, 0x19, 0x08, 0x93, + 0x11, 0x0b, 0x8c, 0x92, 0x00, 0x82, 0x92, 0x00, + 0x81, 0x92, 0x0b, 0xdd, 0x44, 0x01, 0x89, 0x44, + 0x05, 0x89, 0x44, 0x05, 0x81, 0x60, 0x81, 0x19, + 0x80, 0x60, 0x80, 0x19, 0x93, 0x60, 0x05, 0xd8, + 0x60, 0x06, 0xaa, 0x60, 0x04, 0xc5, 0x12, 0x09, + 0x9e, 0x4c, 0x00, 0x8b, 0x4c, 0x03, 0x8b, 0x4c, + 0x03, 0x80, 0x4c, 0x02, 0x8b, 0x4c, 0x9d, 0x93, + 0x01, 0x84, 0x93, 0x0a, 0xab, 0x67, 0x03, 0x99, + 0x67, 0x05, 0x8a, 0x67, 0x02, 0x81, 0x67, 0x9f, + 0x44, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x94, + 0x00, 0x9c, 0x94, 0x01, 0x8a, 0x94, 0x05, 0x89, + 0x94, 0x05, 0x8d, 0x94, 0x01, 0x9e, 0x3a, 0x30, + 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, + 0x07, 0x82, 0x3a, 0x80, 0x19, 0x8c, 0x3a, 0x80, + 0x19, 0x86, 0x3a, 0x83, 0x19, 0x80, 0x3a, 0x85, + 0x19, 0x80, 0x3a, 0x82, 0x19, 0x81, 0x3a, 0x80, + 0x19, 0x04, 0xa5, 0x4a, 0x84, 0x2d, 0x80, 0x1d, + 0xb0, 0x4a, 0x84, 0x2d, 0x83, 0x4a, 0x84, 0x2d, + 0x8c, 0x4a, 0x80, 0x1d, 0xc5, 0x4a, 0x80, 0x2d, + 0xbf, 0x3a, 0xe0, 0x9f, 0x4a, 0x95, 0x2d, 0x01, + 0x85, 0x2d, 0x01, 0xa5, 0x2d, 0x01, 0x85, 0x2d, + 0x01, 0x87, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x80, + 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x9e, 0x2d, 0x01, + 0xb4, 0x2d, 0x00, 0x8e, 0x2d, 0x00, 0x8d, 0x2d, + 0x01, 0x85, 0x2d, 0x00, 0x92, 0x2d, 0x01, 0x82, + 0x2d, 0x00, 0x88, 0x2d, 0x00, 0x8b, 0x19, 0x81, + 0x3a, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80, 0x4a, + 0x01, 0x8a, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x00, + 0x8c, 0x4a, 0x02, 0xa0, 0x19, 0x0e, 0xa0, 0x3a, + 0x0e, 0xa5, 0x19, 0x80, 0x2d, 0x82, 0x19, 0x81, + 0x4a, 0x85, 0x19, 0x80, 0x4a, 0x9a, 0x19, 0x80, + 0x4a, 0x90, 0x19, 0xa8, 0x4a, 0x82, 0x19, 0x03, + 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, + 0x80, 0x9d, 0x96, 0x27, 0x08, 0x86, 0x27, 0x00, + 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, - 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, - 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d, - 0xdd, 0x19, 0x21, 0x99, 0x30, 0x00, 0xd8, 0x30, - 0x0b, 0xe0, 0x75, 0x30, 0x19, 0x8b, 0x19, 0x03, - 0x84, 0x19, 0x80, 0x30, 0x80, 0x19, 0x80, 0x30, - 0x98, 0x19, 0x88, 0x30, 0x83, 0x38, 0x81, 0x31, - 0x87, 0x19, 0x83, 0x30, 0x83, 0x19, 0x00, 0xd5, - 0x36, 0x01, 0x81, 0x38, 0x81, 0x19, 0x82, 0x36, - 0x80, 0x19, 0xd9, 0x3e, 0x81, 0x19, 0x82, 0x3e, - 0x04, 0xaa, 0x0d, 0x00, 0xdd, 0x31, 0x00, 0x8f, - 0x19, 0x9f, 0x0d, 0xa3, 0x19, 0x0b, 0x8f, 0x3e, - 0x9e, 0x31, 0x00, 0xbf, 0x19, 0x9e, 0x31, 0xd0, - 0x19, 0xae, 0x3e, 0x80, 0x19, 0xd7, 0x3e, 0xe0, - 0x47, 0x19, 0xf0, 0x09, 0x5f, 0x30, 0xbf, 0x19, - 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa2, 0x02, - 0xb6, 0xa2, 0x08, 0xaf, 0x4c, 0xe0, 0xcb, 0x9d, - 0x13, 0xdf, 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19, - 0xe0, 0x05, 0x47, 0x82, 0x19, 0xbf, 0x47, 0x04, - 0x81, 0x47, 0x00, 0x80, 0x47, 0x00, 0x84, 0x47, - 0x17, 0x8d, 0x47, 0xac, 0x8a, 0x02, 0x89, 0x19, - 0x05, 0xb7, 0x7a, 0x07, 0xc5, 0x80, 0x07, 0x8b, - 0x80, 0x05, 0x9f, 0x20, 0xad, 0x40, 0x80, 0x19, - 0x80, 0x40, 0xa3, 0x7d, 0x0a, 0x80, 0x7d, 0x9c, - 0x31, 0x02, 0xcd, 0x3b, 0x00, 0x80, 0x19, 0x89, - 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x60, 0x00, 0xb6, - 0x16, 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01, - 0x83, 0x16, 0x9f, 0x60, 0xc2, 0x90, 0x17, 0x84, - 0x90, 0x96, 0x57, 0x09, 0x85, 0x27, 0x01, 0x85, - 0x27, 0x01, 0x85, 0x27, 0x08, 0x86, 0x27, 0x00, - 0x86, 0x27, 0x00, 0xaa, 0x47, 0x80, 0x19, 0x88, - 0x47, 0x80, 0x2c, 0x83, 0x47, 0x81, 0x19, 0x03, - 0xcf, 0x17, 0xad, 0x57, 0x01, 0x89, 0x57, 0x05, - 0xf0, 0x1b, 0x43, 0x31, 0x0b, 0x96, 0x31, 0x03, - 0xb0, 0x31, 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x30, - 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x47, 0x0b, - 0x84, 0x05, 0x04, 0x99, 0x35, 0x00, 0x84, 0x35, - 0x00, 0x80, 0x35, 0x00, 0x81, 0x35, 0x00, 0x81, - 0x35, 0x00, 0x89, 0x35, 0xe0, 0x12, 0x04, 0x0f, - 0xe1, 0x0a, 0x04, 0x81, 0x19, 0xcf, 0x04, 0x01, - 0xb5, 0x04, 0x06, 0x80, 0x04, 0x1f, 0x8f, 0x04, - 0x8f, 0x38, 0x89, 0x19, 0x05, 0x8d, 0x38, 0x81, - 0x1d, 0xa2, 0x19, 0x00, 0x92, 0x19, 0x00, 0x83, - 0x19, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04, - 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x47, - 0x85, 0x19, 0x99, 0x47, 0x8a, 0x19, 0x89, 0x3e, - 0x80, 0x19, 0xac, 0x3e, 0x81, 0x19, 0x9e, 0x31, - 0x02, 0x85, 0x31, 0x01, 0x85, 0x31, 0x01, 0x85, - 0x31, 0x01, 0x82, 0x31, 0x02, 0x86, 0x19, 0x00, - 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4b, - 0x00, 0x99, 0x4b, 0x00, 0x92, 0x4b, 0x00, 0x81, - 0x4b, 0x00, 0x8e, 0x4b, 0x01, 0x8d, 0x4b, 0x21, - 0xe0, 0x1a, 0x4b, 0x04, 0x82, 0x19, 0x03, 0xac, - 0x19, 0x02, 0x88, 0x19, 0xce, 0x2c, 0x00, 0x8c, - 0x19, 0x02, 0x80, 0x2c, 0x2e, 0xac, 0x19, 0x80, - 0x38, 0x60, 0x21, 0x9c, 0x4d, 0x02, 0xb0, 0x13, - 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6c, - 0x08, 0x82, 0x6c, 0x9a, 0x2a, 0x04, 0xaa, 0x6e, - 0x04, 0x9d, 0x9c, 0x00, 0x80, 0x9c, 0xa3, 0x6f, - 0x03, 0x8d, 0x6f, 0x29, 0xcf, 0x1f, 0xaf, 0x82, - 0x9d, 0x76, 0x01, 0x89, 0x76, 0x05, 0xa3, 0x75, - 0x03, 0xa3, 0x75, 0x03, 0xa7, 0x25, 0x07, 0xb3, - 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9e, 0x00, 0x8e, - 0x9e, 0x00, 0x86, 0x9e, 0x00, 0x81, 0x9e, 0x00, - 0x8a, 0x9e, 0x00, 0x8e, 0x9e, 0x00, 0x86, 0x9e, - 0x00, 0x81, 0x9e, 0x42, 0xe0, 0xd6, 0x4a, 0x08, - 0x95, 0x4a, 0x09, 0x87, 0x4a, 0x17, 0x85, 0x47, - 0x00, 0xa9, 0x47, 0x00, 0x88, 0x47, 0x44, 0x85, - 0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, 0x00, - 0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, 0x1c, - 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x78, 0x9e, - 0x61, 0x07, 0x88, 0x61, 0x2f, 0x92, 0x34, 0x00, - 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x7b, 0x02, - 0x80, 0x7b, 0x99, 0x4e, 0x04, 0x80, 0x4e, 0x3f, - 0x9f, 0x5a, 0x97, 0x59, 0x03, 0x93, 0x59, 0x01, - 0xad, 0x59, 0x83, 0x41, 0x00, 0x81, 0x41, 0x04, - 0x87, 0x41, 0x00, 0x82, 0x41, 0x00, 0x9c, 0x41, - 0x01, 0x82, 0x41, 0x03, 0x89, 0x41, 0x06, 0x88, - 0x41, 0x06, 0x9f, 0x71, 0x9f, 0x6d, 0x1f, 0xa6, - 0x53, 0x03, 0x8b, 0x53, 0x08, 0xb5, 0x06, 0x02, - 0x86, 0x06, 0x95, 0x3a, 0x01, 0x87, 0x3a, 0x92, - 0x39, 0x04, 0x87, 0x39, 0x91, 0x7c, 0x06, 0x83, - 0x7c, 0x0b, 0x86, 0x7c, 0x4f, 0xc8, 0x72, 0x36, - 0xb2, 0x6b, 0x0c, 0xb2, 0x6b, 0x06, 0x85, 0x6b, - 0xa7, 0x32, 0x07, 0x89, 0x32, 0x60, 0xc5, 0x9e, - 0x04, 0x00, 0xa9, 0xa1, 0x00, 0x82, 0xa1, 0x01, - 0x81, 0xa1, 0x4a, 0x82, 0x04, 0xa7, 0x70, 0x07, - 0xa9, 0x86, 0x15, 0x99, 0x73, 0x25, 0x9b, 0x18, - 0x13, 0x96, 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3, - 0x0e, 0x08, 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80, - 0x3c, 0x01, 0x98, 0x87, 0x06, 0x89, 0x87, 0x05, - 0xb4, 0x15, 0x00, 0x91, 0x15, 0x07, 0xa6, 0x50, - 0x08, 0xdf, 0x81, 0x00, 0x93, 0x85, 0x0a, 0x91, - 0x43, 0x00, 0xae, 0x43, 0x3d, 0x86, 0x5f, 0x00, - 0x80, 0x5f, 0x00, 0x83, 0x5f, 0x00, 0x8e, 0x5f, - 0x00, 0x8a, 0x5f, 0x05, 0xba, 0x45, 0x04, 0x89, - 0x45, 0x05, 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01, - 0x81, 0x2b, 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b, - 0x00, 0x81, 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80, - 0x38, 0x88, 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82, - 0x2b, 0x01, 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04, - 0x86, 0x2b, 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b, - 0x60, 0x2a, 0xdb, 0x65, 0x00, 0x84, 0x65, 0x1d, - 0xc7, 0x99, 0x07, 0x89, 0x99, 0x60, 0x45, 0xb5, - 0x83, 0x01, 0xa5, 0x83, 0x21, 0xc4, 0x5c, 0x0a, - 0x89, 0x5c, 0x05, 0x8c, 0x5d, 0x12, 0xb9, 0x91, - 0x05, 0x89, 0x91, 0x35, 0x9a, 0x02, 0x01, 0x8e, + 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d, 0xdd, + 0x19, 0x21, 0x99, 0x32, 0x00, 0xd8, 0x32, 0x0b, + 0xe0, 0x75, 0x32, 0x19, 0x94, 0x19, 0x80, 0x32, + 0x80, 0x19, 0x80, 0x32, 0x98, 0x19, 0x88, 0x32, + 0x83, 0x3a, 0x81, 0x33, 0x87, 0x19, 0x83, 0x32, + 0x83, 0x19, 0x00, 0xd5, 0x38, 0x01, 0x81, 0x3a, + 0x81, 0x19, 0x82, 0x38, 0x80, 0x19, 0xd9, 0x40, + 0x81, 0x19, 0x82, 0x40, 0x04, 0xaa, 0x0d, 0x00, + 0xdd, 0x33, 0x00, 0x8f, 0x19, 0x9f, 0x0d, 0xa5, + 0x19, 0x08, 0x80, 0x19, 0x8f, 0x40, 0x9e, 0x33, + 0x00, 0xbf, 0x19, 0x9e, 0x33, 0xd0, 0x19, 0xae, + 0x40, 0x80, 0x19, 0xd7, 0x40, 0xe0, 0x47, 0x19, + 0xf0, 0x09, 0x5f, 0x32, 0xbf, 0x19, 0xf0, 0x41, + 0x9f, 0x32, 0xe4, 0x2c, 0xa9, 0x02, 0xb6, 0xa9, + 0x08, 0xaf, 0x4f, 0xe0, 0xcb, 0xa4, 0x13, 0xdf, + 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19, 0xe0, 0x05, + 0x4a, 0x82, 0x19, 0xc2, 0x4a, 0x01, 0x81, 0x4a, + 0x00, 0x80, 0x4a, 0x00, 0x87, 0x4a, 0x14, 0x8d, + 0x4a, 0xac, 0x8f, 0x02, 0x89, 0x19, 0x05, 0xb7, + 0x7e, 0x07, 0xc5, 0x84, 0x07, 0x8b, 0x84, 0x05, + 0x9f, 0x20, 0xad, 0x42, 0x80, 0x19, 0x80, 0x42, + 0xa3, 0x81, 0x0a, 0x80, 0x81, 0x9c, 0x33, 0x02, + 0xcd, 0x3d, 0x00, 0x80, 0x19, 0x89, 0x3d, 0x03, + 0x81, 0x3d, 0x9e, 0x63, 0x00, 0xb6, 0x16, 0x08, + 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01, 0x83, 0x16, + 0x9f, 0x63, 0xc2, 0x95, 0x17, 0x84, 0x95, 0x96, + 0x5a, 0x09, 0x85, 0x27, 0x01, 0x85, 0x27, 0x01, + 0x85, 0x27, 0x08, 0x86, 0x27, 0x00, 0x86, 0x27, + 0x00, 0xaa, 0x4a, 0x80, 0x19, 0x88, 0x4a, 0x80, + 0x2d, 0x83, 0x4a, 0x81, 0x19, 0x03, 0xcf, 0x17, + 0xad, 0x5a, 0x01, 0x89, 0x5a, 0x05, 0xf0, 0x1b, + 0x43, 0x33, 0x0b, 0x96, 0x33, 0x03, 0xb0, 0x33, + 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x32, 0x01, 0xe0, + 0x09, 0x32, 0x25, 0x86, 0x4a, 0x0b, 0x84, 0x05, + 0x04, 0x99, 0x37, 0x00, 0x84, 0x37, 0x00, 0x80, + 0x37, 0x00, 0x81, 0x37, 0x00, 0x81, 0x37, 0x00, + 0x89, 0x37, 0xe0, 0x12, 0x04, 0x0f, 0xe1, 0x0a, + 0x04, 0x81, 0x19, 0xcf, 0x04, 0x01, 0xb5, 0x04, + 0x06, 0x80, 0x04, 0x1f, 0x8f, 0x04, 0x8f, 0x3a, + 0x89, 0x19, 0x05, 0x8d, 0x3a, 0x81, 0x1d, 0xa2, + 0x19, 0x00, 0x92, 0x19, 0x00, 0x83, 0x19, 0x03, + 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04, 0x01, 0x80, + 0x19, 0x00, 0x9f, 0x19, 0x99, 0x4a, 0x85, 0x19, + 0x99, 0x4a, 0x8a, 0x19, 0x89, 0x40, 0x80, 0x19, + 0xac, 0x40, 0x81, 0x19, 0x9e, 0x33, 0x02, 0x85, + 0x33, 0x01, 0x85, 0x33, 0x01, 0x85, 0x33, 0x01, + 0x82, 0x33, 0x02, 0x86, 0x19, 0x00, 0x86, 0x19, + 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4e, 0x00, 0x99, + 0x4e, 0x00, 0x92, 0x4e, 0x00, 0x81, 0x4e, 0x00, + 0x8e, 0x4e, 0x01, 0x8d, 0x4e, 0x21, 0xe0, 0x1a, + 0x4e, 0x04, 0x82, 0x19, 0x03, 0xac, 0x19, 0x02, + 0x88, 0x19, 0xce, 0x2d, 0x00, 0x8c, 0x19, 0x02, + 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, + 0xa3, 0x00, 0x80, 0xa3, 0xa3, 0x73, 0x03, 0x8d, + 0x73, 0x29, 0xcf, 0x1f, 0xaf, 0x86, 0x9d, 0x7a, + 0x01, 0x89, 0x7a, 0x05, 0xa3, 0x79, 0x03, 0xa3, + 0x79, 0x03, 0xa7, 0x25, 0x07, 0xb3, 0x14, 0x0a, + 0x80, 0x14, 0x8a, 0xa5, 0x00, 0x8e, 0xa5, 0x00, + 0x86, 0xa5, 0x00, 0x81, 0xa5, 0x00, 0x8a, 0xa5, + 0x00, 0x8e, 0xa5, 0x00, 0x86, 0xa5, 0x00, 0x81, + 0xa5, 0x02, 0xb3, 0xa0, 0x0b, 0xe0, 0xd6, 0x4d, + 0x08, 0x95, 0x4d, 0x09, 0x87, 0x4d, 0x17, 0x85, + 0x4a, 0x00, 0xa9, 0x4a, 0x00, 0x88, 0x4a, 0x44, + 0x85, 0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, + 0x00, 0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, + 0x1c, 0x95, 0x39, 0x00, 0x88, 0x39, 0x9f, 0x7c, + 0x9e, 0x64, 0x07, 0x88, 0x64, 0x2f, 0x92, 0x36, + 0x00, 0x81, 0x36, 0x04, 0x84, 0x36, 0x9b, 0x7f, + 0x02, 0x80, 0x7f, 0x99, 0x51, 0x04, 0x80, 0x51, + 0x3f, 0x9f, 0x5d, 0x97, 0x5c, 0x03, 0x93, 0x5c, + 0x01, 0xad, 0x5c, 0x83, 0x43, 0x00, 0x81, 0x43, + 0x04, 0x87, 0x43, 0x00, 0x82, 0x43, 0x00, 0x9c, + 0x43, 0x01, 0x82, 0x43, 0x03, 0x89, 0x43, 0x06, + 0x88, 0x43, 0x06, 0x9f, 0x75, 0x9f, 0x71, 0x1f, + 0xa6, 0x56, 0x03, 0x8b, 0x56, 0x08, 0xb5, 0x06, + 0x02, 0x86, 0x06, 0x95, 0x3c, 0x01, 0x87, 0x3c, + 0x92, 0x3b, 0x04, 0x87, 0x3b, 0x91, 0x80, 0x06, + 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, + 0x6f, 0x9e, 0x04, 0x00, 0xa9, 0xa8, 0x00, 0x82, + 0xa8, 0x01, 0x81, 0xa8, 0x0f, 0x82, 0x04, 0x36, + 0x83, 0x04, 0xa7, 0x74, 0x07, 0xa9, 0x8a, 0x15, + 0x99, 0x77, 0x25, 0x9b, 0x18, 0x13, 0x96, 0x26, + 0x08, 0xcd, 0x0e, 0x03, 0xa3, 0x0e, 0x08, 0x80, + 0x0e, 0xc2, 0x3e, 0x09, 0x80, 0x3e, 0x01, 0x98, + 0x8b, 0x06, 0x89, 0x8b, 0x05, 0xb4, 0x15, 0x00, + 0x91, 0x15, 0x07, 0xa6, 0x53, 0x08, 0xdf, 0x85, + 0x00, 0x93, 0x89, 0x0a, 0x91, 0x45, 0x00, 0xae, + 0x45, 0x3d, 0x86, 0x62, 0x00, 0x80, 0x62, 0x00, + 0x83, 0x62, 0x00, 0x8e, 0x62, 0x00, 0x8a, 0x62, + 0x05, 0xba, 0x47, 0x04, 0x89, 0x47, 0x05, 0x83, + 0x2c, 0x00, 0x87, 0x2c, 0x01, 0x81, 0x2c, 0x01, + 0x95, 0x2c, 0x00, 0x86, 0x2c, 0x00, 0x81, 0x2c, + 0x00, 0x84, 0x2c, 0x00, 0x80, 0x3a, 0x88, 0x2c, + 0x01, 0x81, 0x2c, 0x01, 0x82, 0x2c, 0x01, 0x80, + 0x2c, 0x05, 0x80, 0x2c, 0x04, 0x86, 0x2c, 0x01, + 0x86, 0x2c, 0x02, 0x84, 0x2c, 0x0a, 0x89, 0xa2, + 0x00, 0x80, 0xa2, 0x01, 0x80, 0xa2, 0x00, 0xa5, + 0xa2, 0x00, 0x89, 0xa2, 0x00, 0x80, 0xa2, 0x01, + 0x80, 0xa2, 0x00, 0x83, 0xa2, 0x00, 0x89, 0xa2, + 0x00, 0x81, 0xa2, 0x07, 0x81, 0xa2, 0x1c, 0xdb, + 0x68, 0x00, 0x84, 0x68, 0x1d, 0xc7, 0x9e, 0x07, + 0x89, 0x9e, 0x60, 0x45, 0xb5, 0x87, 0x01, 0xa5, + 0x87, 0x21, 0xc4, 0x5f, 0x0a, 0x89, 0x5f, 0x05, + 0x8c, 0x60, 0x12, 0xb9, 0x96, 0x05, 0x89, 0x96, + 0x05, 0x93, 0x63, 0x1b, 0x9a, 0x02, 0x01, 0x8e, 0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22, - 0x60, 0x03, 0xd2, 0xa0, 0x0b, 0x80, 0xa0, 0x86, + 0x60, 0x03, 0xd2, 0xa7, 0x0b, 0x80, 0xa7, 0x86, 0x21, 0x01, 0x80, 0x21, 0x01, 0x87, 0x21, 0x00, 0x81, 0x21, 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21, 0x01, 0x8b, 0x21, 0x08, 0x89, 0x21, 0x45, 0x87, - 0x63, 0x01, 0xad, 0x63, 0x01, 0x8a, 0x63, 0x1a, - 0xc7, 0xa3, 0x07, 0xd2, 0x88, 0x0c, 0x8f, 0x12, - 0xb8, 0x79, 0x06, 0x89, 0x20, 0x60, 0x95, 0x88, - 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09, - 0x9c, 0x0c, 0x02, 0x9f, 0x54, 0x01, 0x95, 0x54, - 0x00, 0x8d, 0x54, 0x48, 0x86, 0x55, 0x00, 0x81, - 0x55, 0x00, 0xab, 0x55, 0x02, 0x80, 0x55, 0x00, - 0x81, 0x55, 0x00, 0x88, 0x55, 0x07, 0x89, 0x55, - 0x05, 0x85, 0x2e, 0x00, 0x81, 0x2e, 0x00, 0xa4, - 0x2e, 0x00, 0x81, 0x2e, 0x00, 0x85, 0x2e, 0x06, - 0x89, 0x2e, 0x60, 0xd5, 0x98, 0x4f, 0x06, 0x90, - 0x3f, 0x00, 0xa8, 0x3f, 0x02, 0x9b, 0x3f, 0x55, - 0x80, 0x4c, 0x0e, 0xb1, 0x92, 0x0c, 0x80, 0x92, - 0xe3, 0x39, 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b, - 0x00, 0x84, 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69, - 0xeb, 0xe0, 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24, - 0x6f, 0x49, 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58, - 0xe1, 0xd8, 0x08, 0x06, 0x9e, 0x5e, 0x00, 0x89, - 0x5e, 0x03, 0x81, 0x5e, 0xce, 0x9a, 0x00, 0x89, - 0x9a, 0x05, 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09, - 0xc5, 0x77, 0x09, 0x89, 0x77, 0x00, 0x86, 0x77, - 0x00, 0x94, 0x77, 0x04, 0x92, 0x77, 0x62, 0x4f, - 0xda, 0x56, 0x60, 0x04, 0xca, 0x5b, 0x03, 0xb8, - 0x5b, 0x06, 0x90, 0x5b, 0x3f, 0x80, 0x93, 0x80, - 0x67, 0x81, 0x30, 0x80, 0x44, 0x0a, 0x81, 0x30, - 0x0d, 0xf0, 0x07, 0x97, 0x93, 0x07, 0xe2, 0x9f, - 0x93, 0xe1, 0x75, 0x44, 0x29, 0x88, 0x93, 0x70, - 0x12, 0x86, 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00, - 0x81, 0x3e, 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36, - 0x82, 0x3e, 0x0e, 0x80, 0x36, 0x1c, 0x82, 0x36, - 0x01, 0x80, 0x3e, 0x0d, 0x83, 0x3e, 0x07, 0xe1, - 0x2b, 0x67, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04, - 0x8c, 0x23, 0x02, 0x88, 0x23, 0x06, 0x89, 0x23, - 0x01, 0x83, 0x23, 0x83, 0x19, 0x70, 0x01, 0xfb, - 0xad, 0x38, 0x01, 0x96, 0x38, 0x08, 0xe0, 0x13, - 0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, 0xa6, 0x19, - 0x01, 0xbd, 0x19, 0x82, 0x38, 0x90, 0x19, 0x87, - 0x38, 0x81, 0x19, 0x86, 0x38, 0x9d, 0x19, 0x83, - 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x19, - 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, 0xd6, 0x19, - 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, 0x19, 0x00, - 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, 0x80, 0x19, - 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, 0x00, 0x8b, - 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, 0x19, 0x00, - 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, 0x87, 0x19, - 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, 0x00, 0x83, - 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, 0x19, 0x02, - 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, 0x01, 0xe0, - 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, 0x2b, 0x84, - 0x0e, 0x84, 0x84, 0x00, 0x8e, 0x84, 0x63, 0xef, - 0x9e, 0x47, 0x05, 0x85, 0x47, 0x60, 0x74, 0x86, - 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, 0x29, 0x00, - 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, 0xbd, 0x1d, - 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, 0x68, 0x02, - 0x8d, 0x68, 0x01, 0x89, 0x68, 0x03, 0x81, 0x68, - 0x60, 0xdf, 0x9e, 0x9b, 0x10, 0xb9, 0x9f, 0x04, - 0x80, 0x9f, 0x61, 0x6f, 0xa9, 0x62, 0x62, 0x85, - 0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, 0x27, - 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x58, 0x01, - 0x8f, 0x58, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01, - 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, 0x4b, - 0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a, - 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, - 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, 0x04, - 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, 0x80, - 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, - 0x80, 0x04, 0x00, 0x82, 0x04, 0x00, 0x81, 0x04, - 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x80, - 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, - 0x80, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, - 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, 0x83, - 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00, - 0x89, 0x04, 0x00, 0x90, 0x04, 0x04, 0x82, 0x04, - 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, 0x81, - 0x04, 0x60, 0xad, 0xab, 0x19, 0x03, 0xe0, 0x03, - 0x19, 0x0b, 0x8e, 0x19, 0x01, 0x8e, 0x19, 0x00, - 0x8e, 0x19, 0x00, 0xa4, 0x19, 0x09, 0xe0, 0x4d, - 0x19, 0x37, 0x99, 0x19, 0x80, 0x36, 0x81, 0x19, - 0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, 0x81, - 0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, 0x77, - 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, 0x02, - 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, 0x8b, - 0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, 0x03, - 0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, 0x19, - 0x07, 0x9d, 0x19, 0x01, 0x81, 0x19, 0x4d, 0xe0, - 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x8c, 0x19, - 0x02, 0x88, 0x19, 0x06, 0xad, 0x19, 0x00, 0x86, - 0x19, 0x07, 0x8d, 0x19, 0x03, 0x88, 0x19, 0x06, - 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, 0xb6, - 0x19, 0x24, 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96, - 0x7f, 0x30, 0x1f, 0xef, 0xd9, 0x30, 0x05, 0xe0, - 0x7d, 0x30, 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d, - 0xf0, 0x0c, 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd, - 0x30, 0x65, 0x81, 0xf0, 0x02, 0xea, 0x30, 0x04, - 0xef, 0xff, 0x30, 0x7a, 0xcb, 0xf0, 0x80, 0x19, - 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0, 0x8f, 0x38, + 0x66, 0x01, 0xad, 0x66, 0x01, 0x8a, 0x66, 0x1a, + 0xc7, 0xaa, 0x07, 0xd2, 0x8c, 0x0c, 0x8f, 0x12, + 0xb8, 0x7d, 0x06, 0x89, 0x20, 0x60, 0x55, 0xa1, + 0x8e, 0x0d, 0x89, 0x8e, 0x05, 0x88, 0x0c, 0x00, + 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09, 0x9c, 0x0c, + 0x02, 0x9f, 0x57, 0x01, 0x95, 0x57, 0x00, 0x8d, + 0x57, 0x48, 0x86, 0x58, 0x00, 0x81, 0x58, 0x00, + 0xab, 0x58, 0x02, 0x80, 0x58, 0x00, 0x81, 0x58, + 0x00, 0x88, 0x58, 0x07, 0x89, 0x58, 0x05, 0x85, + 0x2f, 0x00, 0x81, 0x2f, 0x00, 0xa4, 0x2f, 0x00, + 0x81, 0x2f, 0x00, 0x85, 0x2f, 0x06, 0x89, 0x2f, + 0x60, 0xd5, 0x98, 0x52, 0x06, 0x90, 0x41, 0x00, + 0xa8, 0x41, 0x02, 0x9c, 0x41, 0x54, 0x80, 0x4f, + 0x0e, 0xb1, 0x97, 0x0c, 0x80, 0x97, 0xe3, 0x39, + 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b, 0x00, 0x84, + 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69, 0xeb, 0xe0, + 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24, 0x09, 0xef, + 0x3a, 0x24, 0x04, 0xe1, 0xe6, 0x03, 0x70, 0x0a, + 0x58, 0xb9, 0x31, 0x66, 0x65, 0xe1, 0xd8, 0x08, + 0x06, 0x9e, 0x61, 0x00, 0x89, 0x61, 0x03, 0x81, + 0x61, 0xce, 0x9f, 0x00, 0x89, 0x9f, 0x05, 0x9d, + 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x7b, 0x09, + 0x89, 0x7b, 0x00, 0x86, 0x7b, 0x00, 0x94, 0x7b, + 0x04, 0x92, 0x7b, 0x61, 0x4f, 0xb9, 0x48, 0x60, + 0x65, 0xda, 0x59, 0x60, 0x04, 0xca, 0x5e, 0x03, + 0xb8, 0x5e, 0x06, 0x90, 0x5e, 0x3f, 0x80, 0x98, + 0x80, 0x6a, 0x81, 0x32, 0x80, 0x46, 0x0a, 0x81, + 0x32, 0x0d, 0xf0, 0x07, 0x97, 0x98, 0x07, 0xe2, + 0x9f, 0x98, 0xe1, 0x75, 0x46, 0x28, 0x80, 0x46, + 0x88, 0x98, 0x70, 0x12, 0x86, 0x83, 0x40, 0x00, + 0x86, 0x40, 0x00, 0x81, 0x40, 0x00, 0x80, 0x40, + 0xe0, 0xbe, 0x38, 0x82, 0x40, 0x0e, 0x80, 0x38, + 0x1c, 0x82, 0x38, 0x01, 0x80, 0x40, 0x0d, 0x83, + 0x40, 0x07, 0xe1, 0x2b, 0x6a, 0x68, 0xa3, 0xe0, + 0x0a, 0x23, 0x04, 0x8c, 0x23, 0x02, 0x88, 0x23, + 0x06, 0x89, 0x23, 0x01, 0x83, 0x23, 0x83, 0x19, + 0x6e, 0xfb, 0xe0, 0x99, 0x19, 0x05, 0xe1, 0x53, + 0x19, 0x4b, 0xad, 0x3a, 0x01, 0x96, 0x3a, 0x08, + 0xe0, 0x13, 0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, + 0xa6, 0x19, 0x01, 0xbd, 0x19, 0x82, 0x3a, 0x90, + 0x19, 0x87, 0x3a, 0x81, 0x19, 0x86, 0x3a, 0x9d, + 0x19, 0x83, 0x3a, 0xbc, 0x19, 0x14, 0xc5, 0x2d, + 0x60, 0x19, 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, + 0xd6, 0x19, 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, + 0x19, 0x00, 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, + 0x80, 0x19, 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, + 0x00, 0x8b, 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, + 0x19, 0x00, 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, + 0x87, 0x19, 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, + 0x00, 0x83, 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, + 0x19, 0x02, 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, + 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, + 0xbd, 0x1d, 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, + 0x6b, 0x02, 0x8d, 0x6b, 0x01, 0x89, 0x6b, 0x03, + 0x81, 0x6b, 0x60, 0xdf, 0x9e, 0xa1, 0x10, 0xb9, + 0xa6, 0x04, 0x80, 0xa6, 0x61, 0x6f, 0xa9, 0x65, + 0x60, 0x75, 0xaa, 0x6e, 0x03, 0x80, 0x6e, 0x61, + 0x7f, 0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, + 0x27, 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x5b, + 0x01, 0x8f, 0x5b, 0x28, 0xcb, 0x01, 0x03, 0x89, + 0x01, 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, + 0x4b, 0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, + 0x9a, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, + 0x01, 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, + 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, + 0x80, 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, + 0x00, 0x80, 0x04, 0x00, 0x82, 0x04, 0x00, 0x81, + 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, + 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, + 0x00, 0x80, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, + 0x04, 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, + 0x83, 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, + 0x00, 0x89, 0x04, 0x00, 0x90, 0x04, 0x04, 0x82, + 0x04, 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, + 0x81, 0x04, 0x60, 0xad, 0xab, 0x19, 0x03, 0xe0, + 0x03, 0x19, 0x0b, 0x8e, 0x19, 0x01, 0x8e, 0x19, + 0x00, 0x8e, 0x19, 0x00, 0xa4, 0x19, 0x09, 0xe0, + 0x4d, 0x19, 0x37, 0x99, 0x19, 0x80, 0x38, 0x81, + 0x19, 0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, + 0x81, 0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, + 0x77, 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, + 0x02, 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, + 0x8b, 0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, + 0x03, 0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, + 0x19, 0x07, 0x9d, 0x19, 0x01, 0x8b, 0x19, 0x03, + 0x81, 0x19, 0x3d, 0xe0, 0xf3, 0x19, 0x0b, 0x8d, + 0x19, 0x01, 0x8c, 0x19, 0x02, 0x89, 0x19, 0x04, + 0xb7, 0x19, 0x06, 0x8e, 0x19, 0x01, 0x8a, 0x19, + 0x05, 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, + 0xe0, 0x05, 0x19, 0x63, 0xa5, 0xf0, 0x96, 0x7f, + 0x32, 0x1f, 0xef, 0xd9, 0x32, 0x05, 0xe0, 0x7d, + 0x32, 0x01, 0xf0, 0x06, 0x21, 0x32, 0x0d, 0xf0, + 0x0c, 0xd0, 0x32, 0x0e, 0xe2, 0x0d, 0x32, 0x69, + 0x41, 0xe1, 0xbd, 0x32, 0x65, 0x81, 0xf0, 0x02, + 0xea, 0x32, 0x04, 0xef, 0xff, 0x32, 0x7a, 0xcb, + 0xf0, 0x80, 0x19, 0x1d, 0xdf, 0x19, 0x60, 0x1f, + 0xe0, 0x8f, 0x3a, }; -static const uint8_t unicode_script_ext_table[828] = { - 0x82, 0xc1, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00, - 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x47, - 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6e, 0x00, - 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x47, 0x00, - 0x02, 0x1d, 0x29, 0x81, 0x03, 0x00, 0x00, 0x06, - 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, 0x0d, 0x00, - 0x00, 0x06, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, - 0x00, 0x03, 0x04, 0x8b, 0x95, 0x01, 0x00, 0x00, - 0x07, 0x01, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, - 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x52, 0x53, - 0x73, 0x7c, 0x32, 0x86, 0x8b, 0x09, 0x00, 0x0a, - 0x02, 0x04, 0x8b, 0x09, 0x00, 0x09, 0x03, 0x04, - 0x95, 0xa1, 0x05, 0x00, 0x00, 0x02, 0x04, 0x8b, - 0x62, 0x00, 0x00, 0x02, 0x04, 0x32, 0x81, 0xfb, - 0x00, 0x00, 0x0d, 0x0b, 0x20, 0x2b, 0x2d, 0x2f, - 0x3d, 0x47, 0x51, 0x74, 0x81, 0x92, 0x94, 0x99, - 0x00, 0x0c, 0x0b, 0x20, 0x2b, 0x2d, 0x2f, 0x3d, - 0x47, 0x51, 0x74, 0x92, 0x94, 0x99, 0x10, 0x00, - 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b, - 0x2d, 0x2f, 0x3d, 0x50, 0x51, 0x63, 0x74, 0x45, - 0x85, 0x8a, 0x91, 0x92, 0x94, 0x99, 0x00, 0x15, - 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b, 0x2d, 0x2f, - 0x3d, 0x49, 0x50, 0x51, 0x63, 0x74, 0x45, 0x85, - 0x8a, 0x91, 0x92, 0x94, 0x99, 0x09, 0x04, 0x20, - 0x22, 0x3c, 0x50, 0x75, 0x00, 0x09, 0x03, 0x0b, - 0x15, 0x8a, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5f, - 0x75, 0x00, 0x09, 0x02, 0x2d, 0x43, 0x80, 0x75, - 0x00, 0x0d, 0x02, 0x2b, 0x92, 0x80, 0x71, 0x00, - 0x09, 0x02, 0x3d, 0x63, 0x82, 0xcf, 0x00, 0x09, - 0x03, 0x15, 0x60, 0x8e, 0x80, 0x30, 0x00, 0x00, - 0x02, 0x28, 0x47, 0x85, 0xb8, 0x00, 0x01, 0x04, - 0x11, 0x33, 0x8d, 0x8c, 0x80, 0x4a, 0x00, 0x01, - 0x02, 0x5d, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x5d, - 0x7a, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20, - 0x2b, 0x3d, 0x00, 0x01, 0x20, 0x00, 0x04, 0x0b, - 0x20, 0x2b, 0x3d, 0x00, 0x02, 0x20, 0x2b, 0x00, - 0x01, 0x20, 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02, - 0x20, 0x81, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02, - 0x20, 0x81, 0x00, 0x06, 0x20, 0x3d, 0x51, 0x74, - 0x92, 0x94, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20, - 0x81, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x81, - 0x00, 0x02, 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00, - 0x02, 0x20, 0x63, 0x00, 0x02, 0x0b, 0x20, 0x01, - 0x01, 0x20, 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01, - 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x63, - 0x74, 0x94, 0x99, 0x00, 0x02, 0x20, 0x2b, 0x00, - 0x03, 0x20, 0x2b, 0x3d, 0x01, 0x02, 0x0b, 0x20, - 0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, 0x2b, 0x00, - 0x01, 0x63, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c, - 0x35, 0x00, 0x00, 0x02, 0x1d, 0x8b, 0x00, 0x00, - 0x00, 0x01, 0x8b, 0x81, 0xb3, 0x00, 0x00, 0x02, - 0x47, 0x5d, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20, - 0x2b, 0x47, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d, - 0x29, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x31, - 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x05, 0x0d, 0x31, - 0x30, 0x36, 0x3e, 0x01, 0x00, 0x00, 0x01, 0x30, - 0x00, 0x00, 0x09, 0x06, 0x0d, 0x31, 0x30, 0x36, - 0x3e, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31, - 0x30, 0x36, 0x3e, 0x07, 0x06, 0x0d, 0x31, 0x30, - 0x36, 0x3e, 0xa2, 0x03, 0x05, 0x0d, 0x31, 0x30, - 0x36, 0x3e, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x30, - 0x01, 0x00, 0x00, 0x05, 0x0d, 0x31, 0x30, 0x36, - 0x3e, 0x04, 0x02, 0x36, 0x3e, 0x00, 0x00, 0x00, - 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x03, 0x00, - 0x01, 0x03, 0x30, 0x36, 0x3e, 0x01, 0x01, 0x30, - 0x58, 0x00, 0x03, 0x02, 0x36, 0x3e, 0x02, 0x00, - 0x00, 0x02, 0x36, 0x3e, 0x59, 0x00, 0x00, 0x06, - 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x02, - 0x36, 0x3e, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x30, - 0x1f, 0x00, 0x23, 0x01, 0x30, 0x3b, 0x00, 0x27, - 0x01, 0x30, 0x37, 0x00, 0x30, 0x01, 0x30, 0x0e, - 0x00, 0x0b, 0x01, 0x30, 0x32, 0x00, 0x00, 0x01, - 0x30, 0x57, 0x00, 0x18, 0x01, 0x30, 0x09, 0x00, - 0x04, 0x01, 0x30, 0x5f, 0x00, 0x1e, 0x01, 0x30, - 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, 0x29, - 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x47, 0x80, - 0xa7, 0x00, 0x02, 0x0e, 0x20, 0x22, 0x2d, 0x2f, - 0x43, 0x3d, 0x3c, 0x50, 0x51, 0x5c, 0x63, 0x45, - 0x91, 0x99, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f, - 0x43, 0x3d, 0x3c, 0x50, 0x5c, 0x63, 0x45, 0x91, - 0x99, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x43, - 0x3c, 0x50, 0x5c, 0x45, 0x91, 0x99, 0x80, 0x36, - 0x00, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x00, 0x00, - 0x02, 0x20, 0x92, 0x39, 0x00, 0x00, 0x03, 0x40, - 0x47, 0x60, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10, - 0x3b, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, 0x04, - 0x66, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x95, - 0x09, 0x00, 0x00, 0x02, 0x04, 0x95, 0x46, 0x00, - 0x01, 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x80, - 0x99, 0x00, 0x04, 0x06, 0x0d, 0x31, 0x30, 0x36, - 0x3e, 0xa2, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e, - 0x2c, 0x00, 0x01, 0x02, 0x36, 0x3e, 0x80, 0xdf, - 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4b, 0x00, 0x02, - 0x1c, 0x4b, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x4a, - 0x4b, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4b, 0x81, - 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, 0x75, - 0x00, 0x00, 0x02, 0x53, 0x73, 0x87, 0x8d, 0x00, - 0x00, 0x02, 0x2b, 0x92, 0x00, 0x00, 0x00, 0x02, - 0x2b, 0x92, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x92, - 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x92, 0x00, - 0x00, 0x00, 0x02, 0x2b, 0x92, 0xc0, 0x5c, 0x4b, - 0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, 0x11, - 0x01, 0x30, 0x9e, 0x5d, 0x00, 0x01, 0x01, 0x30, - 0xce, 0xcd, 0x2d, 0x00, +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, + 0x4a, 0x51, 0x53, 0x72, 0x86, 0x81, 0x83, 0x00, + 0x00, 0x07, 0x0b, 0x1d, 0x20, 0x4a, 0x4f, 0x9b, + 0xa1, 0x09, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x00, + 0x00, 0x02, 0x02, 0x0d, 0x4a, 0x00, 0x00, 0x00, + 0x02, 0x4a, 0x4f, 0x08, 0x00, 0x00, 0x02, 0x4a, + 0x9b, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x25, + 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, + 0x90, 0x9b, 0x00, 0x0b, 0x14, 0x17, 0x1a, 0x1d, + 0x2a, 0x2d, 0x4a, 0x79, 0x90, 0x9d, 0xa0, 0x00, + 0x06, 0x1a, 0x25, 0x29, 0x2a, 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, + 0x4a, 0x72, 0x90, 0x93, 0x00, 0x02, 0x4a, 0x9d, + 0x00, 0x03, 0x23, 0x4a, 0x90, 0x00, 0x04, 0x17, + 0x1d, 0x4a, 0x79, 0x00, 0x03, 0x17, 0x4a, 0x93, + 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x02, 0x27, 0x4a, + 0x00, 0x00, 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x03, + 0x1d, 0x4a, 0xa0, 0x00, 0x00, 0x00, 0x04, 0x2d, + 0x4a, 0x72, 0xa0, 0x0b, 0x00, 0x00, 0x02, 0x4a, + 0x90, 0x01, 0x00, 0x00, 0x05, 0x17, 0x23, 0x40, + 0x4a, 0x90, 0x00, 0x04, 0x17, 0x23, 0x4a, 0x90, + 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, + 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, + 0x9a, 0xa8, 0x00, 0x03, 0x04, 0x90, 0x9a, 0x01, + 0x00, 0x00, 0x08, 0x01, 0x04, 0x2b, 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, + 0x09, 0x03, 0x04, 0x9a, 0xa8, 0x05, 0x00, 0x00, + 0x02, 0x04, 0x90, 0x62, 0x00, 0x00, 0x02, 0x04, + 0x34, 0x81, 0xfb, 0x00, 0x00, 0x0d, 0x0b, 0x20, + 0x2c, 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x85, + 0x97, 0x99, 0x9e, 0x00, 0x0c, 0x0b, 0x20, 0x2c, + 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x97, 0x99, + 0x9e, 0x10, 0x00, 0x00, 0x15, 0x0b, 0x20, 0x22, + 0x2f, 0x58, 0x2c, 0x2e, 0x30, 0x3f, 0x53, 0x54, + 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96, 0x97, + 0x99, 0x9e, 0x00, 0x17, 0x0b, 0x20, 0x22, 0x2f, + 0x58, 0x2c, 0x2e, 0x31, 0x30, 0x3f, 0x4c, 0x53, + 0x54, 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96, + 0x97, 0x99, 0x9e, 0x09, 0x04, 0x20, 0x22, 0x3e, + 0x53, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x15, 0x8f, + 0x75, 0x00, 0x09, 0x02, 0x30, 0x62, 0x75, 0x00, + 0x09, 0x02, 0x2e, 0x45, 0x80, 0x75, 0x00, 0x0d, + 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, + 0x82, 0x46, 0x00, 0x01, 0x04, 0x11, 0x35, 0x92, + 0x91, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x60, 0x7e, + 0x00, 0x00, 0x00, 0x02, 0x60, 0x7e, 0x84, 0x49, + 0x00, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f, 0x00, + 0x01, 0x20, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f, + 0x00, 0x03, 0x20, 0x2c, 0x3f, 0x00, 0x01, 0x20, + 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85, + 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85, + 0x00, 0x06, 0x20, 0x3f, 0x54, 0x78, 0x97, 0x99, + 0x00, 0x01, 0x20, 0x01, 0x02, 0x20, 0x85, 0x01, + 0x01, 0x20, 0x00, 0x02, 0x20, 0x85, 0x00, 0x02, + 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00, 0x02, 0x20, + 0x66, 0x00, 0x02, 0x0b, 0x20, 0x01, 0x01, 0x20, + 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01, 0x20, 0x00, + 0x0b, 0x0b, 0x20, 0x2c, 0x3f, 0x54, 0x66, 0x78, + 0x89, 0x99, 0x9e, 0xa2, 0x00, 0x02, 0x20, 0x2c, + 0x00, 0x04, 0x20, 0x2c, 0x3f, 0xa2, 0x01, 0x02, + 0x0b, 0x20, 0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, + 0x2c, 0x00, 0x01, 0x66, 0x80, 0x44, 0x00, 0x01, + 0x01, 0x2d, 0x35, 0x00, 0x00, 0x03, 0x1d, 0x4a, + 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, + 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, + 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, 0x0f, 0x02, 0x32, 0x98, 0x00, 0x00, 0x00, + 0x07, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, 0xa9, + 0x00, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, + 0x7e, 0xa9, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38, + 0x40, 0x01, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, + 0x01, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, + 0x9c, 0xa9, 0x01, 0x09, 0x0d, 0x33, 0x32, 0x38, + 0x40, 0x4f, 0x60, 0x9c, 0xa9, 0x05, 0x06, 0x0d, + 0x33, 0x32, 0x38, 0x40, 0xa9, 0x00, 0x00, 0x00, + 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x07, 0x06, + 0x0d, 0x33, 0x32, 0x38, 0x40, 0xa9, 0x03, 0x05, + 0x0d, 0x33, 0x32, 0x38, 0x40, 0x09, 0x00, 0x03, + 0x02, 0x0d, 0x32, 0x01, 0x00, 0x00, 0x05, 0x0d, + 0x33, 0x32, 0x38, 0x40, 0x04, 0x02, 0x38, 0x40, + 0x00, 0x00, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38, + 0x40, 0x03, 0x00, 0x01, 0x03, 0x32, 0x38, 0x40, + 0x01, 0x01, 0x32, 0x58, 0x00, 0x03, 0x02, 0x38, + 0x40, 0x02, 0x00, 0x00, 0x02, 0x38, 0x40, 0x59, + 0x00, 0x00, 0x06, 0x0d, 0x33, 0x32, 0x38, 0x40, + 0xa9, 0x00, 0x02, 0x38, 0x40, 0x80, 0x12, 0x00, + 0x0f, 0x01, 0x32, 0x1f, 0x00, 0x25, 0x01, 0x32, + 0x08, 0x00, 0x00, 0x02, 0x32, 0x98, 0x2f, 0x00, + 0x27, 0x01, 0x32, 0x37, 0x00, 0x30, 0x01, 0x32, + 0x0e, 0x00, 0x0b, 0x01, 0x32, 0x32, 0x00, 0x00, + 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, + 0x80, 0xa7, 0x00, 0x02, 0x10, 0x20, 0x22, 0x2e, + 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x54, 0x5f, 0x66, + 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x02, 0x0f, 0x20, + 0x22, 0x2e, 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x5f, + 0x66, 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x01, 0x0b, + 0x20, 0x22, 0x2e, 0x30, 0x45, 0x3e, 0x53, 0x5f, + 0x47, 0x96, 0x9e, 0x00, 0x0c, 0x20, 0x22, 0x2e, + 0x30, 0x45, 0x3e, 0x53, 0x5f, 0x85, 0x47, 0x96, + 0x9e, 0x00, 0x0b, 0x20, 0x22, 0x2e, 0x30, 0x45, + 0x3e, 0x53, 0x5f, 0x47, 0x96, 0x9e, 0x80, 0x36, + 0x00, 0x00, 0x03, 0x0b, 0x20, 0xa2, 0x00, 0x00, + 0x00, 0x02, 0x20, 0x97, 0x39, 0x00, 0x00, 0x03, + 0x42, 0x4a, 0x63, 0x80, 0x1f, 0x00, 0x00, 0x02, + 0x10, 0x3d, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, + 0x04, 0x69, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, + 0x9a, 0x09, 0x00, 0x00, 0x02, 0x04, 0x9a, 0x46, + 0x00, 0x01, 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40, + 0x80, 0x99, 0x00, 0x04, 0x06, 0x0d, 0x33, 0x32, + 0x38, 0x40, 0xa9, 0x09, 0x00, 0x00, 0x02, 0x38, + 0x40, 0x2c, 0x00, 0x01, 0x02, 0x38, 0x40, 0x80, + 0xdf, 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4e, 0x00, + 0x02, 0x1c, 0x4e, 0x03, 0x00, 0x2c, 0x03, 0x1c, + 0x4d, 0x4e, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4e, + 0x81, 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, + 0x75, 0x00, 0x00, 0x02, 0x56, 0x77, 0x87, 0x8d, + 0x00, 0x00, 0x02, 0x2c, 0x97, 0x00, 0x00, 0x00, + 0x02, 0x2c, 0x97, 0x36, 0x00, 0x01, 0x02, 0x2c, + 0x97, 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2c, 0x97, + 0x00, 0x00, 0x00, 0x02, 0x2c, 0x97, 0xc0, 0x5c, + 0x4b, 0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, + 0x11, 0x01, 0x32, 0x9e, 0x5d, 0x00, 0x01, 0x01, + 0x32, 0xce, 0xcd, 0x2d, 0x00, }; static const uint8_t unicode_prop_Hyphen_table[28] = { @@ -3651,61 +3788,63 @@ static const uint8_t unicode_prop_Other_Math_table[200] = { 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, }; -static const uint8_t unicode_prop_Other_Alphabetic_table[428] = { - 0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01, - 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f, - 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80, - 0x9d, 0x8f, 0xe5, 0x8a, 0xe4, 0x0a, 0x88, 0x02, - 0x03, 0x40, 0xa6, 0x8b, 0x16, 0x85, 0x93, 0xb5, - 0x09, 0x8e, 0x01, 0x22, 0x89, 0x81, 0x9c, 0x82, - 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80, 0x89, 0x81, - 0x9c, 0x82, 0xb9, 0x23, 0x09, 0x0b, 0x80, 0x9d, - 0x0a, 0x80, 0x8a, 0x82, 0xb9, 0x38, 0x10, 0x81, - 0x94, 0x81, 0x95, 0x13, 0x82, 0xb9, 0x31, 0x09, - 0x81, 0x88, 0x81, 0x89, 0x81, 0x9d, 0x80, 0xba, - 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x84, 0xb8, - 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9c, 0x82, - 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x8e, - 0x80, 0x8b, 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89, - 0x80, 0x89, 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00, - 0x87, 0x91, 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80, - 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2, - 0x92, 0x88, 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00, - 0x0b, 0x96, 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c, - 0x8b, 0x00, 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d, - 0x81, 0x9d, 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40, - 0xbb, 0x81, 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88, - 0x40, 0xdd, 0x84, 0xb8, 0x89, 0x81, 0x93, 0xc9, - 0x81, 0x8a, 0x82, 0xb0, 0x84, 0xaf, 0x8e, 0xbb, - 0x82, 0x9d, 0x88, 0x09, 0xb8, 0x8a, 0xb1, 0x92, - 0x41, 0xaf, 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5, - 0x9f, 0x60, 0x78, 0x73, 0x87, 0xa1, 0x81, 0x41, - 0x61, 0x07, 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1, - 0x8f, 0x00, 0xb8, 0x80, 0xa5, 0x84, 0x9b, 0x8b, - 0xac, 0x83, 0xaf, 0x8b, 0xa4, 0x80, 0xc2, 0x8d, - 0x8b, 0x07, 0x81, 0xac, 0x82, 0xb1, 0x00, 0x11, - 0x0c, 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87, - 0x60, 0x4f, 0x32, 0x80, 0x48, 0x56, 0x84, 0x46, - 0x85, 0x10, 0x0c, 0x83, 0x43, 0x13, 0x83, 0x41, - 0x82, 0x81, 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac, - 0x81, 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc, - 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, - 0x8c, 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08, - 0x40, 0x9c, 0x89, 0x96, 0x83, 0xb9, 0x31, 0x09, - 0x81, 0x89, 0x80, 0x89, 0x81, 0x40, 0xd0, 0x8c, - 0x02, 0xe9, 0x91, 0x40, 0xec, 0x31, 0x86, 0x9c, - 0x81, 0xd1, 0x8e, 0x00, 0xe9, 0x8a, 0xe6, 0x8d, - 0x41, 0x00, 0x8c, 0x40, 0xf6, 0x28, 0x09, 0x0a, - 0x00, 0x80, 0x40, 0x8d, 0x31, 0x2b, 0x80, 0x9b, - 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, 0xad, 0x8d, - 0x41, 0x96, 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d, - 0xf9, 0x2a, 0x00, 0x08, 0x10, 0x02, 0x80, 0xc1, - 0x20, 0x08, 0x83, 0x41, 0x5b, 0x83, 0x88, 0x08, - 0x80, 0xaf, 0x32, 0x82, 0x60, 0x50, 0x0d, 0x00, - 0xb6, 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, - 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, - 0xe3, 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99, - 0x85, 0x99, 0x85, 0x99, +static const uint8_t unicode_prop_Other_Alphabetic_table[443] = { + 0x43, 0x44, 0x80, 0x9c, 0x8c, 0x42, 0x3f, 0x8d, + 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, + 0x06, 0x8f, 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, + 0xa2, 0x80, 0x9d, 0x8f, 0xe5, 0x8a, 0xe4, 0x0a, + 0x88, 0x02, 0x03, 0xe9, 0x80, 0xbb, 0x8b, 0x16, + 0x85, 0x93, 0xb5, 0x09, 0x8e, 0x01, 0x22, 0x89, + 0x81, 0x9c, 0x82, 0xb9, 0x31, 0x09, 0x81, 0x89, + 0x80, 0x89, 0x81, 0x9c, 0x82, 0xb9, 0x23, 0x09, + 0x0b, 0x80, 0x9d, 0x0a, 0x80, 0x8a, 0x82, 0xb9, + 0x38, 0x10, 0x81, 0x94, 0x81, 0x95, 0x13, 0x82, + 0xb9, 0x31, 0x09, 0x81, 0x88, 0x81, 0x89, 0x81, + 0x9d, 0x80, 0xba, 0x22, 0x10, 0x82, 0x89, 0x80, + 0xa7, 0x84, 0xb8, 0x30, 0x10, 0x17, 0x81, 0x8a, + 0x81, 0x9c, 0x82, 0xb9, 0x30, 0x10, 0x17, 0x81, + 0x8a, 0x81, 0x8e, 0x80, 0x8b, 0x83, 0xb9, 0x30, + 0x10, 0x82, 0x89, 0x80, 0x89, 0x81, 0x9c, 0x82, + 0xca, 0x28, 0x00, 0x87, 0x91, 0x81, 0xbc, 0x01, + 0x86, 0x91, 0x80, 0xe2, 0x01, 0x28, 0x81, 0x8f, + 0x80, 0x40, 0xa2, 0x92, 0x88, 0x8a, 0x80, 0xa3, + 0xed, 0x8b, 0x00, 0x0b, 0x96, 0x1b, 0x10, 0x11, + 0x32, 0x83, 0x8c, 0x8b, 0x00, 0x89, 0x83, 0x46, + 0x73, 0x81, 0x9d, 0x81, 0x9d, 0x81, 0x9d, 0x81, + 0xc1, 0x92, 0x40, 0xbb, 0x81, 0xa1, 0x80, 0xf5, + 0x8b, 0x83, 0x88, 0x40, 0xdd, 0x84, 0xb8, 0x89, + 0x81, 0x93, 0xc9, 0x81, 0x8a, 0x82, 0xb0, 0x84, + 0xaf, 0x8e, 0xbb, 0x82, 0x9d, 0x88, 0x09, 0xb8, + 0x8a, 0xb1, 0x92, 0x41, 0x9b, 0xa1, 0x46, 0xc0, + 0xb3, 0x48, 0xf5, 0x9f, 0x60, 0x78, 0x73, 0x87, + 0xa1, 0x81, 0x41, 0x61, 0x07, 0x80, 0x96, 0x84, + 0xd7, 0x81, 0xb1, 0x8f, 0x00, 0xb8, 0x80, 0xa5, + 0x84, 0x9b, 0x8b, 0xac, 0x83, 0xaf, 0x8b, 0xa4, + 0x80, 0xc2, 0x8d, 0x8b, 0x07, 0x81, 0xac, 0x82, + 0xb1, 0x00, 0x11, 0x0c, 0x80, 0xab, 0x24, 0x80, + 0x40, 0xec, 0x87, 0x60, 0x4f, 0x32, 0x80, 0x48, + 0x56, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0x43, + 0x13, 0x83, 0xc0, 0x80, 0x41, 0x40, 0x81, 0xce, + 0x80, 0x41, 0x02, 0x82, 0xb4, 0x8d, 0xac, 0x81, + 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc, 0x82, + 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, 0x8c, + 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08, 0x40, + 0x9c, 0x89, 0x96, 0x83, 0xb9, 0x31, 0x09, 0x81, + 0x89, 0x80, 0x89, 0x81, 0xd3, 0x88, 0x00, 0x08, + 0x03, 0x01, 0xe6, 0x8c, 0x02, 0xe9, 0x91, 0x40, + 0xec, 0x31, 0x86, 0x9c, 0x81, 0xd1, 0x8e, 0x00, + 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c, 0x40, + 0xf6, 0x28, 0x09, 0x0a, 0x00, 0x80, 0x40, 0x8d, + 0x31, 0x2b, 0x80, 0x9b, 0x89, 0xa9, 0x20, 0x83, + 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, 0x38, 0x86, + 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, + 0x10, 0x02, 0x80, 0xc1, 0x20, 0x08, 0x83, 0x41, + 0x5b, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, 0x82, + 0x60, 0x41, 0xdc, 0x90, 0x4e, 0x1f, 0x00, 0xb6, + 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, 0x60, + 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, + 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99, 0x85, + 0x99, 0x85, 0x99, }; static const uint8_t unicode_prop_Other_Lowercase_table[69] = { @@ -3725,16 +3864,21 @@ static const uint8_t unicode_prop_Other_Uppercase_table[15] = { 0xcc, 0x5f, 0x99, 0x85, 0x99, 0x85, 0x99, }; -static const uint8_t unicode_prop_Other_Grapheme_Extend_table[65] = { +static const uint8_t unicode_prop_Other_Grapheme_Extend_table[112] = { 0x49, 0xbd, 0x80, 0x97, 0x80, 0x41, 0x65, 0x80, - 0x97, 0x80, 0xe5, 0x80, 0x97, 0x80, 0x40, 0xe9, - 0x80, 0x91, 0x81, 0xe6, 0x80, 0x97, 0x80, 0xf6, - 0x80, 0x8e, 0x80, 0x4d, 0x54, 0x80, 0x44, 0xd5, - 0x80, 0x50, 0x20, 0x81, 0x60, 0xcf, 0x6d, 0x81, - 0x53, 0x9d, 0x80, 0x97, 0x80, 0x41, 0x57, 0x80, - 0x8b, 0x80, 0x40, 0xf0, 0x80, 0x43, 0x7f, 0x80, - 0x60, 0xb8, 0x33, 0x07, 0x84, 0x6c, 0x2e, 0xac, - 0xdf, + 0x97, 0x80, 0xe5, 0x80, 0x97, 0x80, 0x40, 0xe7, + 0x00, 0x03, 0x08, 0x81, 0x88, 0x81, 0xe6, 0x80, + 0x97, 0x80, 0xf6, 0x80, 0x8e, 0x80, 0x49, 0x34, + 0x80, 0x9d, 0x80, 0x43, 0xff, 0x04, 0x00, 0x04, + 0x81, 0xe4, 0x80, 0xc6, 0x81, 0x44, 0x17, 0x80, + 0x50, 0x20, 0x81, 0x60, 0x79, 0x22, 0x80, 0xeb, + 0x80, 0x60, 0x55, 0xdc, 0x81, 0x52, 0x1f, 0x80, + 0xf3, 0x80, 0x41, 0x07, 0x80, 0x8d, 0x80, 0x88, + 0x80, 0xdf, 0x80, 0x88, 0x01, 0x00, 0x14, 0x80, + 0x40, 0xdf, 0x80, 0x8b, 0x80, 0x40, 0xf0, 0x80, + 0x41, 0x05, 0x80, 0x42, 0x78, 0x80, 0x8b, 0x80, + 0x46, 0x02, 0x80, 0x60, 0x50, 0xad, 0x81, 0x60, + 0x61, 0x72, 0x0d, 0x85, 0x6c, 0x2e, 0xac, 0xdf, }; static const uint8_t unicode_prop_Other_Default_Ignorable_Code_Point_table[32] = { @@ -3749,9 +3893,10 @@ static const uint8_t unicode_prop_Other_ID_Start_table[11] = { 0x4f, 0x6b, 0x81, }; -static const uint8_t unicode_prop_Other_ID_Continue_table[12] = { +static const uint8_t unicode_prop_Other_ID_Continue_table[22] = { 0x40, 0xb6, 0x80, 0x42, 0xce, 0x80, 0x4f, 0xe0, - 0x88, 0x46, 0x67, 0x80, + 0x88, 0x46, 0x67, 0x80, 0x46, 0x30, 0x81, 0x50, + 0xec, 0x80, 0x60, 0xce, 0x68, 0x80, }; static const uint8_t unicode_prop_Prepended_Concatenation_Mark_table[19] = { @@ -3786,7 +3931,7 @@ static const uint8_t unicode_prop_Changes_When_Casefolded1_table[29] = { 0x89, 0x10, 0x81, 0x8d, 0x80, }; -static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = { +static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[450] = { 0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12, 0x10, 0x82, 0xf3, 0x80, 0x8b, 0x80, 0x40, 0x84, 0x01, 0x01, 0x80, 0xa2, 0x01, 0x80, 0x40, 0xbb, @@ -3828,21 +3973,22 @@ static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = { 0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, 0x08, 0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d, 0x0a, 0x16, 0x06, 0x80, 0x88, 0x47, 0x87, 0x20, - 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x54, - 0xb9, 0x86, 0x8d, 0x87, 0xbf, 0x85, 0x42, 0x3e, - 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, - 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, - 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, - 0x53, 0x81, 0x41, 0x23, 0x81, 0xb1, 0x48, 0x2f, - 0xbd, 0x4d, 0x91, 0x18, 0x9a, 0x01, 0x00, 0x08, - 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, - 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, - 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, - 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f, 0x99, - 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, 0xab, 0x83, - 0x88, 0x31, 0x49, 0x9d, 0x89, 0x60, 0xfc, 0x05, - 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff, + 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x50, + 0x31, 0xa3, 0x44, 0x63, 0x86, 0x8d, 0x87, 0xbf, + 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08, + 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, + 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, + 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81, + 0xb1, 0x48, 0x2f, 0xbd, 0x4d, 0x91, 0x18, 0x9a, + 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, + 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, + 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, + 0x04, 0x80, 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e, + 0x80, 0x9f, 0x99, 0x82, 0xa2, 0x80, 0xee, 0x82, + 0x8c, 0xab, 0x83, 0x88, 0x31, 0x49, 0x9d, 0x89, + 0x60, 0xfc, 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1, + 0x4f, 0xff, }; static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = { @@ -3854,14 +4000,15 @@ static const uint8_t unicode_prop_Bidi_Control_table[10] = { 0xb6, 0x83, }; -static const uint8_t unicode_prop_Dash_table[55] = { +static const uint8_t unicode_prop_Dash_table[58] = { 0xac, 0x80, 0x45, 0x5b, 0x80, 0xb2, 0x80, 0x4e, 0x40, 0x80, 0x44, 0x04, 0x80, 0x48, 0x08, 0x85, 0xbc, 0x80, 0xa6, 0x80, 0x8e, 0x80, 0x41, 0x85, 0x80, 0x4c, 0x03, 0x01, 0x80, 0x9e, 0x0b, 0x80, 0x9b, 0x80, 0x41, 0xbd, 0x80, 0x92, 0x80, 0xee, 0x80, 0x60, 0xcd, 0x8f, 0x81, 0xa4, 0x80, 0x89, - 0x80, 0x40, 0xa8, 0x80, 0x4f, 0x9e, 0x80, + 0x80, 0x40, 0xa8, 0x80, 0x4e, 0x5f, 0x80, 0x41, + 0x3d, 0x80, }; static const uint8_t unicode_prop_Deprecated_table[23] = { @@ -3870,7 +4017,7 @@ static const uint8_t unicode_prop_Deprecated_table[23] = { 0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80, }; -static const uint8_t unicode_prop_Diacritic_table[399] = { +static const uint8_t unicode_prop_Diacritic_table[438] = { 0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b, 0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0, @@ -3883,59 +4030,66 @@ static const uint8_t unicode_prop_Diacritic_table[399] = { 0x8f, 0x80, 0xae, 0x82, 0xbb, 0x80, 0x8f, 0x06, 0x80, 0xf6, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xec, 0x81, 0x8f, 0x80, 0xfb, - 0x80, 0xfb, 0x28, 0x80, 0xea, 0x80, 0x8c, 0x84, - 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, 0x81, 0xc1, - 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, 0x81, 0xa7, - 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, 0x81, 0x42, - 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x40, 0xb2, 0x8a, - 0x88, 0x80, 0x41, 0x5a, 0x82, 0x41, 0x38, 0x39, - 0x80, 0xaf, 0x8e, 0x81, 0x8a, 0xe7, 0x80, 0x8e, - 0x80, 0xa5, 0x88, 0xb5, 0x81, 0x40, 0x89, 0x81, - 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a, 0xb1, - 0xbe, 0xd8, 0x8b, 0xa4, 0x8a, 0x41, 0xbc, 0x00, - 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c, - 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80, 0x41, - 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, 0x75, - 0x71, 0x80, 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1, - 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, 0x81, 0x40, - 0xc9, 0x80, 0x9a, 0x91, 0xb8, 0x83, 0xa3, 0x80, - 0xde, 0x80, 0x8b, 0x80, 0xa3, 0x80, 0x40, 0x94, - 0x82, 0xc0, 0x83, 0xb2, 0x80, 0xe3, 0x84, 0x88, - 0x82, 0xff, 0x81, 0x60, 0x4f, 0x2f, 0x80, 0x43, - 0x00, 0x8f, 0x41, 0x0d, 0x00, 0x80, 0xae, 0x80, - 0xac, 0x81, 0xc2, 0x80, 0x42, 0xfb, 0x80, 0x44, - 0x9e, 0x28, 0xa9, 0x80, 0x88, 0x43, 0x29, 0x81, - 0x42, 0x3a, 0x85, 0x41, 0xd4, 0x82, 0xc5, 0x8a, - 0xb0, 0x83, 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7, - 0x81, 0xf7, 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88, - 0x82, 0xe7, 0x81, 0x40, 0xb1, 0x81, 0xd0, 0x80, - 0x8f, 0x80, 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02, - 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80, - 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41, - 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80, - 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41, - 0x01, 0x00, 0x81, 0xd0, 0x80, 0x56, 0xae, 0x8e, - 0x60, 0x36, 0x99, 0x84, 0xba, 0x86, 0x44, 0x57, - 0x90, 0xcf, 0x81, 0x60, 0x3f, 0xfd, 0x18, 0x30, - 0x81, 0x5f, 0x00, 0xad, 0x81, 0x96, 0x42, 0x1f, - 0x12, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x4e, 0x81, - 0xbd, 0x40, 0xc1, 0x86, 0x41, 0x76, 0x80, 0xbc, - 0x83, 0x45, 0xdf, 0x86, 0xec, 0x10, 0x82, + 0x80, 0xee, 0x80, 0x8b, 0x28, 0x80, 0xea, 0x80, + 0x8c, 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, + 0x81, 0xc1, 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, + 0x81, 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, + 0x81, 0x42, 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x9d, + 0x80, 0x40, 0x93, 0x8a, 0x88, 0x80, 0x41, 0x5a, + 0x82, 0x41, 0x23, 0x80, 0x93, 0x39, 0x80, 0xaf, + 0x8e, 0x81, 0x8a, 0xe7, 0x80, 0x8e, 0x80, 0xa5, + 0x88, 0xb5, 0x81, 0xb9, 0x80, 0x8a, 0x81, 0xc1, + 0x81, 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a, + 0xb1, 0xbe, 0xd8, 0x8b, 0xa4, 0x8a, 0x41, 0xbc, + 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82, + 0x8c, 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80, + 0x41, 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, + 0x75, 0x71, 0x80, 0x8b, 0x08, 0x80, 0x9b, 0x81, + 0xd1, 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, 0x81, + 0x8b, 0x80, 0xa4, 0x80, 0x40, 0x96, 0x80, 0x9a, + 0x91, 0xb8, 0x83, 0xa3, 0x80, 0xde, 0x80, 0x8b, + 0x80, 0xa3, 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83, + 0xb2, 0x80, 0xe3, 0x84, 0x88, 0x82, 0xff, 0x81, + 0x60, 0x4f, 0x2f, 0x80, 0x43, 0x00, 0x8f, 0x41, + 0x0d, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, + 0x80, 0x42, 0xfb, 0x80, 0x44, 0x9e, 0x28, 0xa9, + 0x80, 0x88, 0x42, 0x7c, 0x13, 0x80, 0x40, 0xa4, + 0x81, 0x42, 0x3a, 0x85, 0xa5, 0x80, 0x99, 0x84, + 0x41, 0x8e, 0x82, 0xc5, 0x8a, 0xb0, 0x83, 0x40, + 0xbf, 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7, 0x81, + 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7, 0x81, + 0x40, 0xb1, 0x81, 0xcf, 0x81, 0x8f, 0x80, 0x97, + 0x32, 0x84, 0xd8, 0x10, 0x81, 0x8c, 0x81, 0xde, + 0x02, 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, + 0x80, 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, + 0x41, 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, + 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, + 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, 0x41, 0xa8, + 0x81, 0x96, 0x80, 0x54, 0xeb, 0x8e, 0x60, 0x2c, + 0xd8, 0x80, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x42, + 0x33, 0x81, 0x42, 0x21, 0x90, 0xcf, 0x81, 0x60, + 0x3f, 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, 0xad, + 0x81, 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, 0x86, + 0x9d, 0x83, 0x4e, 0x81, 0xbd, 0x40, 0xc1, 0x86, + 0x41, 0x76, 0x80, 0xbc, 0x83, 0x42, 0xfd, 0x81, + 0x42, 0xdf, 0x86, 0xec, 0x10, 0x82, }; -static const uint8_t unicode_prop_Extender_table[92] = { +static const uint8_t unicode_prop_Extender_table[111] = { 0x40, 0xb6, 0x80, 0x42, 0x17, 0x81, 0x43, 0x6d, - 0x80, 0x41, 0xb8, 0x80, 0x43, 0x59, 0x80, 0x42, - 0xef, 0x80, 0xfe, 0x80, 0x49, 0x42, 0x80, 0xb7, - 0x80, 0x42, 0x62, 0x80, 0x41, 0x8d, 0x80, 0xc3, - 0x80, 0x53, 0x88, 0x80, 0xaa, 0x84, 0xe6, 0x81, - 0xdc, 0x82, 0x60, 0x6f, 0x15, 0x80, 0x45, 0xf5, - 0x80, 0x43, 0xc1, 0x80, 0x95, 0x80, 0x40, 0x88, - 0x80, 0xeb, 0x80, 0x94, 0x81, 0x60, 0x54, 0x7a, - 0x80, 0x48, 0x0f, 0x81, 0x4b, 0xd9, 0x80, 0x42, - 0x67, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8, + 0x80, 0x41, 0xb8, 0x80, 0x42, 0x75, 0x80, 0x40, + 0x88, 0x80, 0xd8, 0x80, 0x42, 0xef, 0x80, 0xfe, + 0x80, 0x49, 0x42, 0x80, 0xb7, 0x80, 0x42, 0x62, + 0x80, 0x41, 0x8d, 0x80, 0xc3, 0x80, 0x53, 0x88, + 0x80, 0xaa, 0x84, 0xe6, 0x81, 0xdc, 0x82, 0x60, + 0x6f, 0x15, 0x80, 0x45, 0xf5, 0x80, 0x43, 0xc1, + 0x80, 0x95, 0x80, 0x40, 0x88, 0x80, 0xeb, 0x80, + 0x94, 0x81, 0x60, 0x54, 0x7a, 0x80, 0x48, 0x0f, + 0x81, 0x45, 0xca, 0x80, 0x9a, 0x03, 0x80, 0x44, + 0xc6, 0x80, 0x41, 0x24, 0x80, 0xf3, 0x81, 0x41, + 0xf1, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8, 0x81, 0x44, 0x9b, 0x08, 0x80, 0x60, 0x71, 0x57, - 0x81, 0x48, 0x05, 0x82, + 0x81, 0x44, 0xb0, 0x80, 0x43, 0x53, 0x82, }; static const uint8_t unicode_prop_Hex_Digit_table[12] = { @@ -3943,24 +4097,28 @@ static const uint8_t unicode_prop_Hex_Digit_table[12] = { 0x89, 0x35, 0x99, 0x85, }; -static const uint8_t unicode_prop_IDS_Binary_Operator_table[5] = { - 0x60, 0x2f, 0xef, 0x09, 0x87, +static const uint8_t unicode_prop_IDS_Unary_Operator_table[4] = { + 0x60, 0x2f, 0xfd, 0x81, +}; + +static const uint8_t unicode_prop_IDS_Binary_Operator_table[8] = { + 0x60, 0x2f, 0xef, 0x09, 0x89, 0x41, 0xf0, 0x80, }; static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = { 0x60, 0x2f, 0xf1, 0x81, }; -static const uint8_t unicode_prop_Ideographic_table[69] = { +static const uint8_t unicode_prop_Ideographic_table[72] = { 0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82, 0x43, 0xc4, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff, 0x60, 0x58, 0xff, 0x41, 0x6d, 0x81, 0xe9, 0x60, 0x75, 0x09, 0x80, 0x9a, 0x57, 0xf7, 0x87, 0x44, - 0xd5, 0xa9, 0x88, 0x60, 0x24, 0x66, 0x41, 0x8b, + 0xd5, 0xa8, 0x89, 0x60, 0x24, 0x66, 0x41, 0x8b, 0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, - 0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1, - 0x53, 0x4a, 0x84, 0x50, 0x5f, + 0x5d, 0x30, 0x8e, 0x42, 0x6d, 0x49, 0xa1, 0x42, + 0x1d, 0x45, 0xe1, 0x53, 0x4a, 0x84, 0x50, 0x5f, }; static const uint8_t unicode_prop_Join_Control_table[4] = { @@ -3972,6 +4130,11 @@ static const uint8_t unicode_prop_Logical_Order_Exception_table[15] = { 0x80, 0x60, 0x90, 0xf9, 0x09, 0x00, 0x81, }; +static const uint8_t unicode_prop_Modifier_Combining_Mark_table[16] = { + 0x46, 0x53, 0x09, 0x80, 0x40, 0x82, 0x05, 0x02, + 0x81, 0x41, 0xe0, 0x08, 0x12, 0x80, 0x9e, 0x80, +}; + static const uint8_t unicode_prop_Noncharacter_Code_Point_table[71] = { 0x60, 0xfd, 0xcf, 0x9f, 0x42, 0x0d, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, @@ -4016,32 +4179,34 @@ static const uint8_t unicode_prop_Regional_Indicator_table[4] = { 0x61, 0xf1, 0xe5, 0x99, }; -static const uint8_t unicode_prop_Sentence_Terminal_table[196] = { +static const uint8_t unicode_prop_Sentence_Terminal_table[213] = { 0xa0, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0x45, 0x48, 0x80, 0x40, 0x92, 0x82, 0x40, 0xb3, 0x80, 0xaa, 0x82, 0x40, 0xf5, 0x80, 0xbc, 0x00, 0x02, 0x81, 0x41, 0x24, 0x81, 0x46, 0xe3, 0x81, 0x43, 0x15, 0x03, 0x81, 0x43, 0x04, 0x80, 0x40, 0xc5, 0x81, - 0x40, 0xcb, 0x04, 0x80, 0x41, 0x39, 0x81, 0x41, - 0x61, 0x83, 0x40, 0xad, 0x09, 0x81, 0x9c, 0x81, - 0x40, 0xbb, 0x81, 0xc0, 0x81, 0x43, 0xbb, 0x81, - 0x88, 0x82, 0x4d, 0xe3, 0x80, 0x8c, 0x80, 0x95, - 0x81, 0x41, 0xac, 0x80, 0x60, 0x74, 0xfb, 0x80, - 0x41, 0x0d, 0x81, 0x40, 0xe2, 0x02, 0x80, 0x41, - 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x97, - 0x81, 0x40, 0x92, 0x82, 0x40, 0x8f, 0x81, 0x40, - 0xf8, 0x80, 0x60, 0x52, 0x65, 0x02, 0x81, 0x40, - 0xa8, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0xc0, 0x80, - 0x4a, 0xf3, 0x81, 0x44, 0xfc, 0x84, 0xab, 0x83, - 0x40, 0xbc, 0x81, 0xf4, 0x83, 0xfe, 0x82, 0x40, - 0x80, 0x0d, 0x80, 0x8f, 0x81, 0xd7, 0x08, 0x81, - 0xeb, 0x80, 0x41, 0xa0, 0x81, 0x41, 0x74, 0x0c, - 0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, - 0x00, 0x80, 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41, - 0xa3, 0x81, 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60, - 0x4b, 0x28, 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81, - 0x8a, 0x80, 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05, - 0x80, 0x5d, 0xe7, 0x80, + 0x40, 0x9c, 0x81, 0xac, 0x04, 0x80, 0x41, 0x39, + 0x81, 0x41, 0x61, 0x83, 0x40, 0xa1, 0x81, 0x89, + 0x09, 0x81, 0x9c, 0x82, 0x40, 0xba, 0x81, 0xc0, + 0x81, 0x43, 0xa3, 0x80, 0x96, 0x81, 0x88, 0x82, + 0x4c, 0xae, 0x82, 0x41, 0x31, 0x80, 0x8c, 0x80, + 0x95, 0x81, 0x41, 0xac, 0x80, 0x60, 0x74, 0xfb, + 0x80, 0x41, 0x0d, 0x81, 0x40, 0xe2, 0x02, 0x80, + 0x41, 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, + 0x97, 0x81, 0x40, 0x92, 0x82, 0x40, 0x8f, 0x81, + 0x40, 0xf8, 0x80, 0x60, 0x52, 0x25, 0x01, 0x81, + 0xba, 0x02, 0x81, 0x40, 0xa8, 0x80, 0x8b, 0x80, + 0x8f, 0x80, 0xc0, 0x80, 0x4a, 0xf3, 0x81, 0x44, + 0xfc, 0x84, 0xab, 0x83, 0x40, 0xbc, 0x81, 0xf4, + 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, 0x80, 0x8f, + 0x81, 0xd7, 0x08, 0x81, 0xeb, 0x80, 0x41, 0x29, + 0x81, 0xf4, 0x81, 0x41, 0x74, 0x0c, 0x8e, 0xe8, + 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80, + 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41, 0xa3, 0x81, + 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60, 0x4b, 0x28, + 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81, 0x8a, 0x80, + 0x42, 0x28, 0x81, 0x41, 0x27, 0x80, 0x60, 0x4e, + 0x05, 0x80, 0x5d, 0xe7, 0x80, }; static const uint8_t unicode_prop_Soft_Dotted_table[79] = { @@ -4057,47 +4222,49 @@ static const uint8_t unicode_prop_Soft_Dotted_table[79] = { 0x85, 0x80, 0x41, 0x30, 0x81, 0x99, 0x80, }; -static const uint8_t unicode_prop_Terminal_Punctuation_table[248] = { +static const uint8_t unicode_prop_Terminal_Punctuation_table[264] = { 0xa0, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80, 0x43, 0x3d, 0x07, 0x80, 0x42, 0x00, 0x80, 0xb8, 0x80, 0xc7, 0x80, 0x8d, 0x00, 0x82, 0x40, 0xb3, 0x80, 0xaa, 0x8a, 0x00, 0x40, 0xea, 0x81, 0xb5, - 0x8e, 0x9e, 0x80, 0x41, 0x04, 0x81, 0x44, 0xf3, - 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36, 0x81, - 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb, 0x82, - 0xc6, 0x81, 0x40, 0x9c, 0x12, 0x80, 0xa6, 0x19, - 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83, 0x40, - 0xad, 0x08, 0x82, 0x9c, 0x81, 0x40, 0xbb, 0x84, - 0xbd, 0x81, 0x43, 0xbb, 0x81, 0x88, 0x82, 0x4d, - 0xe3, 0x80, 0x8c, 0x03, 0x80, 0x89, 0x00, 0x0a, + 0x28, 0x87, 0x9e, 0x80, 0x41, 0x04, 0x81, 0x44, + 0xf3, 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36, + 0x81, 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb, + 0x82, 0xc6, 0x81, 0x40, 0x9c, 0x12, 0x80, 0xa6, + 0x19, 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83, + 0x40, 0xa1, 0x81, 0x89, 0x08, 0x82, 0x9c, 0x82, + 0x40, 0xba, 0x84, 0xbd, 0x81, 0x43, 0xa3, 0x80, + 0x96, 0x81, 0x88, 0x82, 0x4c, 0xae, 0x82, 0x41, + 0x31, 0x80, 0x8c, 0x03, 0x80, 0x89, 0x00, 0x0a, 0x81, 0x41, 0xab, 0x81, 0x60, 0x74, 0xfa, 0x81, 0x41, 0x0c, 0x82, 0x40, 0xe2, 0x84, 0x41, 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x96, 0x82, 0x40, 0x92, 0x82, 0xfe, 0x80, 0x8f, 0x81, 0x40, - 0xf8, 0x80, 0x60, 0x52, 0x63, 0x10, 0x83, 0x40, - 0xa8, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80, - 0xc0, 0x01, 0x80, 0x44, 0x39, 0x80, 0xaf, 0x80, - 0x44, 0x85, 0x80, 0x40, 0xc6, 0x80, 0x41, 0x35, - 0x81, 0x40, 0x97, 0x85, 0xc3, 0x85, 0xd8, 0x83, - 0x43, 0xb7, 0x84, 0xab, 0x83, 0x40, 0xbc, 0x86, - 0xef, 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, 0x80, - 0x8f, 0x81, 0xd7, 0x84, 0xeb, 0x80, 0x41, 0xa0, - 0x82, 0x8b, 0x81, 0x41, 0x65, 0x1a, 0x8e, 0xe8, - 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80, - 0x40, 0xfa, 0x81, 0xd6, 0x0b, 0x81, 0x41, 0x9d, - 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0xc9, 0x81, - 0x45, 0x2a, 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40, - 0x84, 0x80, 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51, + 0xf8, 0x80, 0x60, 0x52, 0x25, 0x01, 0x81, 0xb8, + 0x10, 0x83, 0x40, 0xa8, 0x80, 0x89, 0x00, 0x80, + 0x8a, 0x0a, 0x80, 0xc0, 0x01, 0x80, 0x44, 0x39, + 0x80, 0xaf, 0x80, 0x44, 0x85, 0x80, 0x40, 0xc6, + 0x80, 0x41, 0x35, 0x81, 0x40, 0x97, 0x85, 0xc3, + 0x85, 0xd8, 0x83, 0x43, 0xb7, 0x84, 0xab, 0x83, + 0x40, 0xbc, 0x86, 0xef, 0x83, 0xfe, 0x82, 0x40, + 0x80, 0x0d, 0x80, 0x8f, 0x81, 0xd7, 0x84, 0xeb, + 0x80, 0x41, 0x29, 0x81, 0xf4, 0x82, 0x8b, 0x81, + 0x41, 0x65, 0x1a, 0x8e, 0xe8, 0x81, 0x40, 0xf8, + 0x82, 0x42, 0x04, 0x00, 0x80, 0x40, 0xfa, 0x81, + 0xd6, 0x0b, 0x81, 0x41, 0x9d, 0x82, 0xac, 0x80, + 0x42, 0x84, 0x81, 0xc9, 0x81, 0x45, 0x2a, 0x84, + 0x60, 0x45, 0xf8, 0x81, 0x40, 0x84, 0x80, 0xc0, + 0x82, 0x89, 0x80, 0x42, 0x28, 0x81, 0x41, 0x26, 0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83, }; -static const uint8_t unicode_prop_Unified_Ideograph_table[45] = { +static const uint8_t unicode_prop_Unified_Ideograph_table[48] = { 0x60, 0x33, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff, 0x60, 0x5a, 0x0d, 0x08, 0x00, 0x81, 0x89, 0x00, 0x00, 0x09, 0x82, 0x61, 0x05, 0xd5, 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd, - 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x54, 0x1e, - 0x53, 0x4a, 0x84, 0x50, 0x5f, + 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e, 0x42, + 0x6d, 0x51, 0xa1, 0x53, 0x4a, 0x84, 0x50, 0x5f, }; static const uint8_t unicode_prop_Variation_Selector_table[13] = { @@ -4105,12 +4272,6 @@ 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, @@ -4118,7 +4279,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = { 0x89, 0x81, 0xb5, 0x81, 0x8d, 0x81, 0x40, 0xb0, 0x80, 0x40, 0xbf, 0x1a, 0x2a, 0x02, 0x0a, 0x18, 0x18, 0x00, 0x03, 0x88, 0x20, 0x80, 0x91, 0x23, - 0x88, 0x08, 0x00, 0x39, 0x9e, 0x0b, 0x20, 0x88, + 0x88, 0x08, 0x00, 0x38, 0x9f, 0x0b, 0x20, 0x88, 0x09, 0x92, 0x21, 0x88, 0x21, 0x0b, 0x97, 0x81, 0x8f, 0x3b, 0x93, 0x0e, 0x81, 0x44, 0x3c, 0x8d, 0xc9, 0x01, 0x18, 0x08, 0x14, 0x1c, 0x12, 0x8d, @@ -4136,7 +4297,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = { 0x80, 0xb8, 0x80, 0xb8, 0x80, }; -static const uint8_t unicode_prop_Emoji_table[239] = { +static const uint8_t unicode_prop_Emoji_table[238] = { 0xa2, 0x05, 0x04, 0x89, 0xee, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81, @@ -4165,8 +4326,8 @@ static const uint8_t unicode_prop_Emoji_table[239] = { 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x83, 0x89, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, 0x80, - 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88, 0x86, 0xad, - 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86, 0x88, + 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, 0x84, 0xb7, + 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88, }; static const uint8_t unicode_prop_Emoji_Component_table[28] = { @@ -4192,7 +4353,7 @@ static const uint8_t unicode_prop_Emoji_Modifier_Base_table[71] = { 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88, }; -static const uint8_t unicode_prop_Emoji_Presentation_table[145] = { +static const uint8_t unicode_prop_Emoji_Presentation_table[144] = { 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, 0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b, 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, @@ -4209,9 +4370,8 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[145] = { 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, 0x88, - 0x86, 0xad, 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86, - 0x88, + 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, + 0x84, 0xb7, 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88, }; static const uint8_t unicode_prop_Extended_Pictographic_table[156] = { @@ -4271,11 +4431,13 @@ typedef enum { UNICODE_PROP_Diacritic, UNICODE_PROP_Extender, UNICODE_PROP_Hex_Digit, + UNICODE_PROP_IDS_Unary_Operator, UNICODE_PROP_IDS_Binary_Operator, UNICODE_PROP_IDS_Trinary_Operator, UNICODE_PROP_Ideographic, UNICODE_PROP_Join_Control, UNICODE_PROP_Logical_Order_Exception, + UNICODE_PROP_Modifier_Combining_Mark, UNICODE_PROP_Noncharacter_Code_Point, UNICODE_PROP_Pattern_Syntax, UNICODE_PROP_Pattern_White_Space, @@ -4312,12 +4474,15 @@ typedef enum { UNICODE_PROP_Grapheme_Base, UNICODE_PROP_Grapheme_Extend, UNICODE_PROP_ID_Continue, + UNICODE_PROP_ID_Compat_Math_Start, + UNICODE_PROP_ID_Compat_Math_Continue, 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; @@ -4329,11 +4494,13 @@ static const char unicode_prop_name_table[] = "Diacritic,Dia" "\0" "Extender,Ext" "\0" "Hex_Digit,Hex" "\0" + "IDS_Unary_Operator,IDSU" "\0" "IDS_Binary_Operator,IDSB" "\0" "IDS_Trinary_Operator,IDST" "\0" "Ideographic,Ideo" "\0" "Join_Control,Join_C" "\0" "Logical_Order_Exception,LOE" "\0" + "Modifier_Combining_Mark,MCM" "\0" "Noncharacter_Code_Point,NChar" "\0" "Pattern_Syntax,Pat_Syn" "\0" "Pattern_White_Space,Pat_WS" "\0" @@ -4370,6 +4537,8 @@ static const char unicode_prop_name_table[] = "Grapheme_Base,Gr_Base" "\0" "Grapheme_Extend,Gr_Ext" "\0" "ID_Continue,IDC" "\0" + "ID_Compat_Math_Start" "\0" + "ID_Compat_Math_Continue" "\0" "Lowercase,Lower" "\0" "Math" "\0" "Uppercase,Upper" "\0" @@ -4401,11 +4570,13 @@ static const uint8_t * const unicode_prop_table[] = { unicode_prop_Diacritic_table, unicode_prop_Extender_table, unicode_prop_Hex_Digit_table, + unicode_prop_IDS_Unary_Operator_table, unicode_prop_IDS_Binary_Operator_table, unicode_prop_IDS_Trinary_Operator_table, unicode_prop_Ideographic_table, unicode_prop_Join_Control_table, unicode_prop_Logical_Order_Exception_table, + unicode_prop_Modifier_Combining_Mark_table, unicode_prop_Noncharacter_Code_Point_table, unicode_prop_Pattern_Syntax_table, unicode_prop_Pattern_White_Space_table, @@ -4454,11 +4625,13 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Diacritic_table), countof(unicode_prop_Extender_table), countof(unicode_prop_Hex_Digit_table), + countof(unicode_prop_IDS_Unary_Operator_table), countof(unicode_prop_IDS_Binary_Operator_table), countof(unicode_prop_IDS_Trinary_Operator_table), countof(unicode_prop_Ideographic_table), countof(unicode_prop_Join_Control_table), countof(unicode_prop_Logical_Order_Exception_table), + countof(unicode_prop_Modifier_Combining_Mark_table), countof(unicode_prop_Noncharacter_Code_Point_table), countof(unicode_prop_Pattern_Syntax_table), countof(unicode_prop_Pattern_White_Space_table), @@ -4483,4 +4656,3 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Case_Ignorable_table), }; -#endif /* CONFIG_ALL_UNICODE */ diff --git a/libunicode.c b/libunicode.c index 0712a6c..e68b0ca 100644 --- a/libunicode.c +++ b/libunicode.c @@ -1,6 +1,6 @@ /* * Unicode utilities - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -31,6 +31,7 @@ #include "libunicode.h" #include "libunicode-table.h" +// note: stored as 4 bit tag, not much room left enum { RUN_TYPE_U, RUN_TYPE_L, @@ -149,9 +150,9 @@ static int lre_case_conv_entry(uint32_t *res, uint32_t c, int conv_type, uint32_ } /* conv_type: - 0 = to upper + 0 = to upper 1 = to lower - 2 = case folding (= to lower with modifications) + 2 = case folding (= to lower with modifications) */ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) { @@ -168,7 +169,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) } else { uint32_t v, code, len; int idx, idx_min, idx_max; - + idx_min = 0; idx_max = countof(case_conv_table1) - 1; while (idx_min <= idx_max) { @@ -262,11 +263,7 @@ int lre_canonicalize(uint32_t c, BOOL is_unicode) static uint32_t get_le24(const uint8_t *ptr) { -#if defined(__x86__) || defined(__x86_64__) - return *(uint16_t *)ptr | (ptr[2] << 16); -#else return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16); -#endif } #define UNICODE_INDEX_BLOCK_LEN 32 @@ -311,7 +308,7 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table, uint32_t code, b, bit; int pos; const uint8_t *p; - + pos = get_index_pos(&code, c, index_table, index_table_len); if (pos < 0) return FALSE; /* outside the table */ @@ -344,7 +341,7 @@ BOOL lre_is_cased(uint32_t c) { uint32_t v, code, len; int idx, idx_min, idx_max; - + idx_min = 0; idx_max = countof(case_conv_table1) - 1; while (idx_min <= idx_max) { @@ -403,7 +400,7 @@ int cr_realloc(CharRange *cr, int size) { int new_size; uint32_t *new_buf; - + if (size > cr->size) { new_size = max_int(size, cr->size * 3 / 2); new_buf = cr->realloc_func(cr->mem_opaque, cr->points, @@ -430,7 +427,7 @@ static void cr_compress(CharRange *cr) { int i, j, k, len; uint32_t *pt; - + pt = cr->points; len = cr->len; i = 0; @@ -460,7 +457,7 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, { int a_idx, b_idx, is_in; uint32_t v; - + a_idx = 0; b_idx = 0; for(;;) { @@ -533,8 +530,6 @@ int cr_invert(CharRange *cr) return 0; } -#ifdef CONFIG_ALL_UNICODE - BOOL lre_is_id_start(uint32_t c) { return lre_is_in_table(c, unicode_prop_ID_Start_table, @@ -550,6 +545,13 @@ 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 { @@ -761,7 +763,7 @@ 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; - + idx_min = 0; idx_max = countof(unicode_decomp_table1) - 1; while (idx_min <= idx_max) { @@ -791,7 +793,7 @@ static int unicode_compose_pair(uint32_t c0, uint32_t c1) uint32_t code, len, type, v, idx1, d_idx, d_offset, ch; int idx_min, idx_max, idx, d; uint32_t pair[2]; - + idx_min = 0; idx_max = countof(unicode_comp_table) - 1; while (idx_min <= idx_max) { @@ -827,7 +829,7 @@ static int unicode_get_cc(uint32_t c) uint32_t code, n, type, cc, c1, b; int pos; const uint8_t *p; - + pos = get_index_pos(&code, c, unicode_cc_index, sizeof(unicode_cc_index) / 3); if (pos < 0) @@ -876,7 +878,7 @@ static int unicode_get_cc(uint32_t c) static void sort_cc(int *buf, int len) { int i, j, k, cc, cc1, start, ch1; - + for(i = 0; i < len; i++) { cc = unicode_get_cc(buf[i]); if (cc != 0) { @@ -897,13 +899,6 @@ 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; } } @@ -915,7 +910,7 @@ static void to_nfd_rec(DynBuf *dbuf, uint32_t c, v; int i, l; uint32_t res[UNICODE_DECOMP_LEN_MAX]; - + for(i = 0; i < src_len; i++) { c = src[i]; if (c >= 0xac00 && c < 0xd7a4) { @@ -960,7 +955,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len; BOOL is_compat; DynBuf dbuf_s, *dbuf = &dbuf_s; - + is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); @@ -988,15 +983,15 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, } buf = (int *)dbuf->buf; buf_len = dbuf->size / sizeof(int); - + sort_cc(buf, buf_len); - + if (buf_len <= 1 || (n_type & 1) != 0) { /* NFD / NFKD */ *pdst = (uint32_t *)buf; return buf_len; } - + i = 1; out_len = 1; while (i < buf_len) { @@ -1033,7 +1028,7 @@ static int unicode_find_name(const char *name_table, const char *name) const char *p, *r; int pos; size_t name_len, len; - + p = name_table; pos = 0; name_len = strlen(name); @@ -1063,16 +1058,16 @@ int unicode_script(CharRange *cr, int script_idx; const uint8_t *p, *p_end; uint32_t c, c1, b, n, v, v_len, i, type; - CharRange cr1_s, *cr1; - CharRange cr2_s, *cr2 = &cr2_s; + CharRange cr1_s = { 0 }, *cr1 = NULL; + CharRange cr2_s = { 0 }, *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); if (is_ext) { @@ -1350,7 +1345,7 @@ static int point_cmp(const void *p1, const void *p2, void *arg) 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; @@ -1389,7 +1384,7 @@ 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); @@ -1404,7 +1399,7 @@ int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode) 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 */ @@ -1488,7 +1483,7 @@ static int unicode_prop_ops(CharRange *cr, ...) CharRange stack[POP_STACK_LEN_MAX]; int stack_len, op, ret, i; uint32_t a; - + va_start(ap, cr); stack_len = 0; for(;;) { @@ -1574,7 +1569,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name) { int gc_idx; uint32_t gc_mask; - + gc_idx = unicode_find_name(unicode_gc_name_table, gc_name); if (gc_idx < 0) return -2; @@ -1592,7 +1587,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name) int unicode_prop(CharRange *cr, const char *prop_name) { int prop_idx, ret; - + prop_idx = unicode_find_name(unicode_prop_name_table, prop_name); if (prop_idx < 0) return -2; @@ -1731,42 +1726,6 @@ 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, @@ -1775,7 +1734,6 @@ 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; @@ -1784,5 +1742,3 @@ int unicode_prop(CharRange *cr, const char *prop_name) } return ret; } - -#endif /* CONFIG_ALL_UNICODE */ diff --git a/libunicode.h b/libunicode.h index 8abacb0..ae20a49 100644 --- a/libunicode.h +++ b/libunicode.h @@ -1,6 +1,6 @@ /* * Unicode utilities - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,12 +24,14 @@ #ifndef LIBUNICODE_H #define LIBUNICODE_H +#include #include -#define LRE_BOOL int /* for documentation purposes */ +#ifdef __cplusplus +extern "C" { +#endif -/* define it to include all the unicode tables (40KB larger) */ -#define CONFIG_ALL_UNICODE +#define LRE_BOOL int /* for documentation purposes */ #define LRE_CC_RES_LEN_MAX 3 @@ -101,13 +103,11 @@ 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); -#ifdef CONFIG_ALL_UNICODE - LRE_BOOL lre_is_id_start(uint32_t c); LRE_BOOL lre_is_id_continue(uint32_t c); +LRE_BOOL lre_is_white_space(uint32_t c); int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, UnicodeNormalizationEnum n_type, @@ -120,8 +120,10 @@ int unicode_script(CharRange *cr, int unicode_general_category(CharRange *cr, const char *gc_name); int unicode_prop(CharRange *cr, const char *prop_name); -#endif /* CONFIG_ALL_UNICODE */ - #undef LRE_BOOL +#ifdef __cplusplus +} /* extern "C" { */ +#endif + #endif /* LIBUNICODE_H */ diff --git a/list.h b/list.h index 5c18234..b8dd716 100644 --- a/list.h +++ b/list.h @@ -1,6 +1,6 @@ /* * Linux klist like system - * + * * Copyright (c) 2016-2017 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -28,6 +28,10 @@ #include #endif +#ifdef __cplusplus +extern "C" { +#endif + struct list_head { struct list_head *prev; struct list_head *next; @@ -45,7 +49,7 @@ static inline void init_list_head(struct list_head *head) } /* insert 'el' between 'prev' and 'next' */ -static inline void __list_add(struct list_head *el, +static inline void __list_add(struct list_head *el, struct list_head *prev, struct list_head *next) { prev->next = el; @@ -96,4 +100,8 @@ 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/qjs.c b/qjs.c index 6e9d7e2..e31f94b 100644 --- a/qjs.c +++ b/qjs.c @@ -1,7 +1,6 @@ /* * QuickJS stand alone interpreter - * - * Copyright (c) 2024 Sneed Group + * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon * @@ -29,26 +28,81 @@ #include #include #include +#if !defined(_MSC_VER) #include +#endif #include #include #include -#if defined(__APPLE__) -#include -#elif defined(__linux__) -#include -#endif #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; -#ifdef CONFIG_BIGNUM -extern const uint8_t qjsc_qjscalc[]; -extern const uint32_t qjsc_qjscalc_size; -static int bignum_ext; -#endif +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; + } + js_module_set_import_meta(ctx, obj, FALSE, TRUE); + 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) @@ -65,6 +119,7 @@ static int eval_buf(JSContext *ctx, const void *buf, int buf_len, 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); } @@ -83,7 +138,7 @@ 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); @@ -91,7 +146,7 @@ static int eval_file(JSContext *ctx, const char *filename, int module) } if (module < 0) { - module = (has_suffix(filename, ".mjs") || + module = (js__has_suffix(filename, ".mjs") || JS_DetectModule((const char *)buf, buf_len)); } if (module) @@ -99,7 +154,8 @@ static int eval_file(JSContext *ctx, const char *filename, int module) else eval_flags = JS_EVAL_TYPE_GLOBAL; - //POLYFILLS FOR QJS FILES BEGIN + + //POLYFILLS FOR QJS FILES BEGIN const char *pf = "globalThis.global = globalThis;\n" "global.console.error = console.log\n" "global.console.warn = console.log\n" @@ -118,19 +174,70 @@ static int eval_file(JSContext *ctx, const char *filename, int module) " globalThis.loadFile = std.loadFile;\n" " globalThis.printf = console.log;\n" " globalThis.evalFile = std.loadScript;\n" - " globalThis.require = std.loadScript;\n" + //" globalThis.require = std.loadScript;\n" " globalThis.getURL = std.urlGet;\n" "} else {\n" " console.error('std is not defined.');\n" "}\n"; - eval_buf(ctx, pf, strlen(pf), "", JS_EVAL_TYPE_MODULE); 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, JSValue this_val, + int argc, JSValue *argv) +{ + JS_RunGC(JS_GetRuntime(ctx)); + return JS_UNDEFINED; +} + +static JSValue js_navigator_get_userAgent(JSContext *ctx, JSValue 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) { @@ -138,26 +245,30 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt) ctx = JS_NewContext(rt); if (!ctx) return NULL; -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - JS_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, TRUE); - } -#endif /* system modules */ - js_init_module_std(ctx, "std"); - js_init_module_os(ctx, "os"); + 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; } -#if defined(__APPLE__) -#define MALLOC_OVERHEAD 0 -#else -#define MALLOC_OVERHEAD 8 -#endif - struct trace_malloc_data { uint8_t *base; }; @@ -168,31 +279,14 @@ static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, 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__) - 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 +#if defined(_WIN32) && !defined(__clang__) /* 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, ...) + js_trace_malloc_printf(void *opaque, const char *fmt, ...) { va_list ap; int c; @@ -207,8 +301,8 @@ __attribute__((format(printf, 2, 3))) printf("NULL"); } else { printf("H%+06lld.%zd", - js_trace_malloc_ptr_offset(ptr, s->opaque), - js_trace_malloc_usable_size(ptr)); + js_trace_malloc_ptr_offset(ptr, opaque), + js__malloc_usable_size(ptr)); } fmt++; continue; @@ -230,77 +324,83 @@ 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) +static void *js_trace_calloc(void *opaque, size_t count, 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; - } + ptr = calloc(count, size); + js_trace_malloc_printf(opaque, "C %zd %zd -> %p\n", count, size, ptr); return ptr; } -static void js_trace_free(JSMallocState *s, void *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(s, "F %p\n", ptr); - s->malloc_count--; - s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + js_trace_malloc_printf(opaque, "F %p\n", ptr); free(ptr); } -static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size) +static void *js_trace_realloc(void *opaque, 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); - + js_trace_malloc_printf(opaque, "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; - } + 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_trace_malloc_usable_size, + 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 version " CONFIG_VERSION "\n" + printf("QuickJS-ng DoneJS Edition version %s\n" "usage: " PROG_NAME " [options] [file [args]]\n" "-h --help list options\n" "-e --eval EXPR evaluate EXPR\n" @@ -308,17 +408,17 @@ void help(void) "-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" -#ifdef CONFIG_BIGNUM - " --bignum enable the bignum extensions (BigFloat, BigDecimal)\n" - " --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n" -#endif + " --std make 'std', 'os' and 'bjson' available to 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\n" - " --stack-size n limit the stack size to 'n' bytes\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" " --unhandled-rejection dump unhandled promise rejections\n" - "-q --quit just instantiate the interpreter and quit\n"); + "-q --quit just instantiate the interpreter and quit\n", JS_GetVersion()); exit(1); } @@ -326,48 +426,55 @@ int main(int argc, char **argv) { JSRuntime *rt; JSContext *ctx; + JSValue ret = JS_UNDEFINED; struct trace_malloc_data trace_data = { NULL }; - int optind; + int optind = 1; + 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; //we don't need this anymore, we ignore this and always load std libs + int load_std = 0; int dump_unhandled_promise_rejection = 0; - size_t memory_limit = 0; char *include_list[32]; int i, include_count = 0; -#ifdef CONFIG_BIGNUM - int load_jscalc; -#endif - size_t stack_size = 0; - -#ifdef CONFIG_BIGNUM - /* load jscalc runtime if invoked as 'qjscalc' */ - { - const char *p, *exename; - exename = argv[0]; - p = strrchr(exename, '/'); - if (p) - exename = p + 1; - load_jscalc = !strcmp(exename, "qjscalc"); + int64_t memory_limit = -1; + int64_t stack_size = -1; + + /* save for later */ + qjs__argc = argc; + qjs__argv = argv; + + if (is_standalone(argv[0])) { + standalone = 1; + goto start; } -#endif - + + 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 */ - optind = 1; while (optind < argc && *argv[optind] == '-') { char *arg = argv[optind] + 1; const char *longopt = ""; + char *opt_arg = NULL; /* a single - is not an option, it also stops argument scanning */ if (!*arg) break; optind++; if (*arg == '-') { longopt = arg + 1; + opt_arg = strchr(longopt, '='); + if (opt_arg) + *opt_arg++ = '\0'; arg += strlen(arg); /* -- stops argument scanning */ if (!*longopt) @@ -375,23 +482,25 @@ int main(int argc, char **argv) } for (; *arg || *longopt; longopt = "") { char opt = *arg; - if (opt) + if (opt) { arg++; + if (!opt_arg && *arg) + opt_arg = arg; + } if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { help(); continue; } if (opt == 'e' || !strcmp(longopt, "eval")) { - if (*arg) { - expr = arg; - break; + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "qjs: missing expression for -e\n"); + exit(1); + } + opt_arg = argv[optind++]; } - if (optind < argc) { - expr = argv[optind++]; - break; - } - fprintf(stderr, "qjs: missing expression for -e\n"); - exit(2); + expr = opt_arg; + break; } if (opt == 'I' || !strcmp(longopt, "include")) { if (optind >= argc) { @@ -421,47 +530,80 @@ int main(int argc, char **argv) dump_memory++; continue; } + if (opt == 'D' || !strcmp(longopt, "dump-flags")) { + dump_flags = opt_arg ? strtol(opt_arg, NULL, 16) : 0; + break; + } if (opt == 'T' || !strcmp(longopt, "trace")) { trace_memory++; continue; } - //if (!strcmp(longopt, "std")) { - //load_std = 1; - //continue; - //} + if (!strcmp(longopt, "std")) { + load_std = 1; + continue; + } if (!strcmp(longopt, "unhandled-rejection")) { dump_unhandled_promise_rejection = 1; continue; } -#ifdef CONFIG_BIGNUM - if (!strcmp(longopt, "bignum")) { - bignum_ext = 1; - continue; - } - if (!strcmp(longopt, "qjscalc")) { - load_jscalc = 1; - continue; - } -#endif if (opt == 'q' || !strcmp(longopt, "quit")) { empty_run++; continue; } if (!strcmp(longopt, "memory-limit")) { - if (optind >= argc) { - fprintf(stderr, "expecting memory limit"); - exit(1); + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "expecting memory limit"); + exit(1); + } + opt_arg = argv[optind++]; } - memory_limit = (size_t)strtod(argv[optind++], NULL); - continue; + memory_limit = parse_limit(opt_arg); + break; } if (!strcmp(longopt, "stack-size")) { - if (optind >= argc) { - fprintf(stderr, "expecting stack size"); - exit(1); + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "expecting stack size"); + exit(1); + } + opt_arg = argv[optind++]; } - stack_size = (size_t)strtod(argv[optind++], NULL); - continue; + stack_size = parse_limit(opt_arg); + break; + } + if (opt == 'c' || !strcmp(longopt, "compile")) { + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "qjs: missing file for -c\n"); + exit(1); + } + opt_arg = argv[optind++]; + } + compile_file = opt_arg; + break; + } + if (opt == 'o' || !strcmp(longopt, "out")) { + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "qjs: missing file for -o\n"); + exit(1); + } + opt_arg = argv[optind++]; + } + out = opt_arg; + break; + } + if (!strcmp(longopt, "exe")) { + if (!opt_arg) { + if (optind >= argc) { + fprintf(stderr, "qjs: missing file for --exe\n"); + exit(1); + } + opt_arg = argv[optind++]; + } + exe = opt_arg; + break; } if (opt) { fprintf(stderr, "qjs: unknown option '-%c'\n", opt); @@ -472,25 +614,31 @@ int main(int argc, char **argv) } } -#ifdef CONFIG_BIGNUM - if (load_jscalc) - bignum_ext = 1; -#endif + 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, memory_limit); - if (stack_size != 0) - JS_SetMaxStackSize(rt, stack_size); + 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); @@ -506,35 +654,58 @@ int main(int argc, char **argv) JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); } - + if (!empty_run) { -#ifdef CONFIG_BIGNUM - if (load_jscalc) { - js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0); - } -#endif js_std_add_helpers(ctx, argc - optind, argv + optind); - /* make 'std' and 'os' visible to all code */ - //if (load_std) { - const char *str = "import * as std from 'std';\n" - "import * as os from 'os';\n" + /* 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], module)) + if (eval_file(ctx, include_list[i], 0)) goto fail; } - if (expr) { + 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] = JS_NewString(ctx, exe != NULL ? exe : argv[0]); + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, args[0]); + JS_FreeValue(ctx, args[1]); + JS_FreeValue(ctx, args[2]); + } else if (expr) { if (eval_buf(ctx, expr, strlen(expr), "", 0)) goto fail; - } else - if (optind >= argc) { + } else if (optind >= argc) { /* interactive mode */ interactive = 1; } else { @@ -546,7 +717,6 @@ int main(int argc, char **argv) if (interactive) { js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0); } - //POLYFILLS FOR QJS REPL BEGIN const char *pf = "globalThis.global = globalThis;\n" "global.console.error = console.log\n" @@ -566,7 +736,7 @@ int main(int argc, char **argv) " globalThis.loadFile = std.loadFile;\n" " globalThis.printf = console.log;\n" " globalThis.evalFile = std.loadScript;\n" - " globalThis.require = std.loadScript;\n" + // " globalThis.require = std.loadScript;\n" " globalThis.getURL = std.urlGet;\n" "} else {\n" " console.error('std is not defined.');\n" @@ -574,10 +744,23 @@ int main(int argc, char **argv) eval_buf(ctx, pf, strlen(pf), "", JS_EVAL_TYPE_MODULE); - - js_std_loop(ctx); + if (standalone || compile_file) { + if (JS_IsException(ret)) { + ret = JS_GetException(ctx); + } else { + JS_FreeValue(ctx, ret); + ret = js_std_loop(ctx); + } + } else { + ret = js_std_loop(ctx); + } + if (!JS_IsUndefined(ret)) { + js_std_dump_error1(ctx, ret); + JS_FreeValue(ctx, ret); + goto fail; + } } - + if (dump_memory) { JSMemoryUsage stats; JS_ComputeMemoryUsage(rt, &stats); @@ -589,7 +772,7 @@ int main(int argc, char **argv) if (empty_run && dump_memory) { clock_t t[5]; - double best[5]; + double best[5] = {0}; int i, j; for (i = 0; i < 100; i++) { t[0] = clock(); diff --git a/qjsc.c b/qjsc.c index f8e60b3..f5e42a7 100644 --- a/qjsc.c +++ b/qjsc.c @@ -1,7 +1,9 @@ /* * QuickJS command line compiler - * + * * Copyright (c) 2018-2021 Fabrice Bellard + * Copyright (c) 2023 Ben Noordhuis + * Copyright (c) 2023 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 @@ -27,15 +29,22 @@ #include #include #include +#if defined(_MSC_VER) +#include "getopt_compat.h" +#else #include -#include -#if !defined(_WIN32) -#include #endif +#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; @@ -48,36 +57,13 @@ typedef struct namelist_t { 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 OutputTypeEnum output_type; 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 }, - { "bigint", "BigInt" }, -}; +static int strip; void namelist_add(namelist_t *lp, const char *name, const char *short_name, int flags) @@ -129,7 +115,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file) size_t len, i; int c; char *q; - + p = strrchr(file, '/'); if (!p) p = file; @@ -140,7 +126,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file) len = strlen(p); else len = r - p; - pstrcpy(buf, buf_size, c_ident_prefix); + js__pstrcpy(buf, buf_size, c_ident_prefix); q = buf + strlen(buf); for(i = 0; i < len; i++) { c = p[i]; @@ -171,15 +157,19 @@ static void dump_hex(FILE *f, const uint8_t *buf, size_t len) } static void output_object_code(JSContext *ctx, - FILE *fo, JSValueConst obj, const char *c_name, + FILE *fo, JSValue obj, const char *c_name, BOOL load_only) { uint8_t *out_buf; size_t out_buf_len; - int flags; - flags = JS_WRITE_OBJ_BYTECODE; - if (byte_swap) - flags |= JS_WRITE_OBJ_BSWAP; + 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); @@ -187,13 +177,17 @@ static void output_object_code(JSContext *ctx, } namelist_add(&cname_list, c_name, NULL, load_only); - - 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"); + + 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); } @@ -202,6 +196,7 @@ 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) @@ -223,7 +218,7 @@ static void find_unique_cname(char *cname, size_t cname_size) break; suffix_num++; } - pstrcpy(cname, cname_size, cname1); + js__pstrcpy(cname, cname_size, cname1); } JSModuleDef *jsc_module_loader(JSContext *ctx, @@ -239,26 +234,23 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, 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 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[1024]; - + 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); @@ -270,7 +262,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, 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); @@ -280,6 +272,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, static void compile_file(JSContext *ctx, FILE *fo, const char *filename, + const char *script_name, const char *c_name1, int module) { @@ -288,7 +281,7 @@ static void compile_file(JSContext *ctx, FILE *fo, 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); @@ -296,21 +289,21 @@ static void compile_file(JSContext *ctx, FILE *fo, } eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; if (module < 0) { - module = (has_suffix(filename, ".mjs") || + 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, filename, eval_flags); + 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) { - pstrcpy(c_name, sizeof(c_name), c_name1); + js__pstrcpy(c_name, sizeof(c_name), c_name1); } else { get_c_name(c_name, sizeof(c_name), filename); } @@ -321,245 +314,106 @@ static void compile_file(JSContext *ctx, FILE *fo, static const char main_c_template1[] = "int main(int argc, char **argv)\n" "{\n" + " int r;\n" + " JSValue ret;\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[] = - " js_std_loop(ctx);\n" - " js_std_free_handlers(rt);\n" + " ret = js_std_loop(ctx);\n" + " if (JS_IsException(ret)) {\n" + " js_std_dump_error1(ctx, ret);\n" + " r = 1;\n" + " }\n" + " JS_FreeValue(ctx, ret);\n" " JS_FreeContext(ctx);\n" + " js_std_free_handlers(rt);\n" " JS_FreeRuntime(rt);\n" - " return 0;\n" + " return r;\n" "}\n"; #define PROG_NAME "qjsc" void help(void) { - printf("QuickJS Compiler version " CONFIG_VERSION "\n" + printf("QuickJS-ng Compiler DoneJS Edition version %s\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" + "-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" "-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 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); -#ifdef CONFIG_LTO - { - int i; - printf("-flto use link time optimization\n"); - printf("-fbignum enable bignum extensions\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 - - -typedef enum { - OUTPUT_C, - OUTPUT_C_MAIN, - OUTPUT_EXECUTABLE, -} OutputTypeEnum; - int main(int argc, char **argv) { int c, i, verbose; - const char *out_filename, *cname; + const char *out_filename, *cname, *script_name; char cfilename[1024]; FILE *fo; JSRuntime *rt; JSContext *ctx; - BOOL use_lto; int module; - OutputTypeEnum output_type; size_t stack_size; -#ifdef CONFIG_BIGNUM - BOOL bignum_ext = FALSE; -#endif namelist_t dynamic_module_list; - + out_filename = NULL; - output_type = OUTPUT_EXECUTABLE; + script_name = NULL; + output_type = OUTPUT_C; cname = NULL; - feature_bitmap = FE_ALL; module = -1; - byte_swap = FALSE; verbose = 0; - use_lto = FALSE; + strip = 0; stack_size = 0; memset(&dynamic_module_list, 0, sizeof(dynamic_module_list)); - + + /* 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); for(;;) { - c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:"); + c = getopt(argc, argv, "ho:N:mn:bxesvM:p:S:D:"); if (c == -1) break; switch(c) { case 'h': help(); + case 'b': + output_type = OUTPUT_RAW; + break; case 'o': out_filename = optarg; break; - case 'c': - output_type = OUTPUT_C; - break; case 'e': output_type = OUTPUT_C_MAIN; break; + case 'n': + script_name = optarg; + break; case 'N': cname = optarg; break; - case 'f': - { - const char *p; - p = optarg; - if (!strcmp(optarg, "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 -#ifdef CONFIG_BIGNUM - if (!strcmp(optarg, "bignum")) { - bignum_ext = TRUE; - } else -#endif - { - bad_feature: - fprintf(stderr, "unsupported feature: %s\n", optarg); - exit(1); - } - } - break; case 'm': module = 1; break; @@ -568,11 +422,11 @@ int main(int argc, char **argv) char *p; char path[1024]; char cname[1024]; - pstrcpy(path, sizeof(path), optarg); + js__pstrcpy(path, sizeof(path), optarg); p = strchr(path, ','); if (p) { *p = '\0'; - pstrcpy(cname, sizeof(cname), p + 1); + js__pstrcpy(cname, sizeof(cname), p + 1); } else { get_c_name(cname, sizeof(cname), path); } @@ -582,8 +436,8 @@ int main(int argc, char **argv) case 'D': namelist_add(&dynamic_module_list, optarg, NULL, 0); break; - case 'x': - byte_swap = TRUE; + case 's': + strip++; break; case 'v': verbose++; @@ -602,55 +456,39 @@ int main(int argc, char **argv) if (optind >= argc) help(); - if (!out_filename) { - if (output_type == OUTPUT_EXECUTABLE) { - out_filename = "a.out"; - } else { - out_filename = "out.c"; - } - } + 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 (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); -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - JS_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, TRUE); - } -#endif - + /* loader for ES6 modules */ JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); - fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" - "\n" - ); - - if (output_type != OUTPUT_C) { + 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 { + } else if (output_type == OUTPUT_C) { fprintf(fo, "#include \n" "\n" ); @@ -658,7 +496,7 @@ int main(int argc, char **argv) for(i = optind; i < argc; i++) { const char *filename = argv[i]; - compile_file(ctx, fo, filename, cname, module); + compile_file(ctx, fo, filename, script_name, cname, module); cname = NULL; } @@ -669,38 +507,20 @@ int main(int argc, char **argv) exit(1); } } - - if (output_type != OUTPUT_C) { + + if (output_type == OUTPUT_C_MAIN) { fprintf(fo, "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n" "{\n" - " JSContext *ctx = JS_NewContextRaw(rt);\n" + " JSContext *ctx = JS_NewContext(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); - } - } -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - fprintf(fo, - " JS_AddIntrinsicBigFloat(ctx);\n" - " JS_AddIntrinsicBigDecimal(ctx);\n" - " JS_AddIntrinsicOperators(ctx);\n" - " JS_EnableBignumExt(ctx, 1);\n"); - } -#endif /* 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" @@ -718,19 +538,17 @@ int main(int argc, char **argv) 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_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); - } - + + /* 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"); @@ -744,16 +562,12 @@ int main(int argc, char **argv) } 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); diff --git a/qjscalc.js b/qjscalc.js deleted file mode 100644 index b1ad1e8..0000000 --- a/qjscalc.js +++ /dev/null @@ -1,2657 +0,0 @@ -/* - * QuickJS Javascript Calculator - * - * Copyright (c) 2017-2020 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. - */ -"use strict"; -"use math"; - -var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunction, Series, Matrix; - -(function(global) { - global.Integer = global.BigInt; - global.Float = global.BigFloat; - global.algebraicMode = true; - - /* add non enumerable properties */ - function add_props(obj, props) { - var i, val, prop, tab, desc; - tab = Reflect.ownKeys(props); - for(i = 0; i < tab.length; i++) { - prop = tab[i]; - desc = Object.getOwnPropertyDescriptor(props, prop); - desc.enumerable = false; - if ("value" in desc) { - if (typeof desc.value !== "function") { - desc.writable = false; - desc.configurable = false; - } - } else { - /* getter/setter */ - desc.configurable = false; - } - Object.defineProperty(obj, prop, desc); - } - } - - /* same as proto[Symbol.operatorSet] = Operators.create(..op_list) - but allow shortcuts: left: [], right: [] or both - */ - function operators_set(proto, ...op_list) - { - var new_op_list, i, a, j, b, k, obj, tab; - var fields = [ "left", "right" ]; - new_op_list = []; - for(i = 0; i < op_list.length; i++) { - a = op_list[i]; - if (a.left || a.right) { - tab = [ a.left, a.right ]; - delete a.left; - delete a.right; - for(k = 0; k < 2; k++) { - obj = tab[k]; - if (obj) { - if (!Array.isArray(obj)) { - obj = [ obj ]; - } - for(j = 0; j < obj.length; j++) { - b = {}; - Object.assign(b, a); - b[fields[k]] = obj[j]; - new_op_list.push(b); - } - } - } - } else { - new_op_list.push(a); - } - } - proto[Symbol.operatorSet] = - Operators.create.call(null, ...new_op_list); - } - - /* Integer */ - - function generic_pow(a, b) { - var r, is_neg, i; - if (!Integer.isInteger(b)) { - return exp(log(a) * b); - } - if (Array.isArray(a) && !(a instanceof Polynomial || - a instanceof Series)) { - r = idn(Matrix.check_square(a)); - } else { - r = 1; - } - if (b == 0) - return r; - is_neg = false; - if (b < 0) { - is_neg = true; - b = -b; - } - r = a; - for(i = Integer.floorLog2(b) - 1; i >= 0; i--) { - r *= r; - if ((b >> i) & 1) - r *= a; - } - if (is_neg) { - if (typeof r.inverse != "function") - throw "negative powers are not supported for this type"; - r = r.inverse(); - } - return r; - } - - var small_primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499 ]; - - function miller_rabin_test(n, t) { - var d, r, s, i, j, a; - d = n - 1; - s = 0; - while ((d & 1) == 0) { - d >>= 1; - s++; - } - if (small_primes.length < t) - t = small_primes.length; - loop: for(j = 0; j < t; j++) { - a = small_primes[j]; - r = Integer.pmod(a, d, n); - if (r == 1 || r == (n - 1)) - continue; - for(i = 1; i < s; i++) { - r = (r * r) % n; - if (r == 1) - return false; - if (r == (n - 1)) - continue loop; - } - return false; /* n is composite */ - } - return true; /* n is probably prime with probability (1-0.5^t) */ - } - - function fact_rec(a, b) { /* assumes a <= b */ - var i, r; - if ((b - a) <= 5) { - r = a; - for(i = a + 1; i <= b; i++) - r *= i; - return r; - } else { - /* to avoid a quadratic running time it is better to - multiply numbers of similar size */ - i = (a + b) >> 1; - return fact_rec(a, i) * fact_rec(i + 1, b); - } - } - - /* math mode specific quirk to overload the integer division and power */ - Operators.updateBigIntOperators( - { - "/"(a, b) { - if (algebraicMode) { - return Fraction.toFraction(a, b); - } else { - return Float(a) / Float(b); - } - }, - "**"(a, b) { - if (algebraicMode) { - return generic_pow(a, b); - } else { - return Float(a) ** Float(b); - } - } - }); - - add_props(Integer, { - isInteger(a) { - /* integers are represented either as bigint or as number */ - return typeof a === "bigint" || - (typeof a === "number" && Number.isSafeInteger(a)); - }, - gcd(a, b) { - var r; - while (b != 0) { - r = a % b; - a = b; - b = r; - } - return a; - }, - fact(n) { - return n <= 0 ? 1 : fact_rec(1, n); - }, - /* binomial coefficient */ - comb(n, k) { - if (k < 0 || k > n) - return 0; - if (k > n - k) - k = n - k; - if (k == 0) - return 1; - return Integer.tdiv(fact_rec(n - k + 1, n), fact_rec(1, k)); - }, - /* inverse of x modulo y */ - invmod(x, y) { - var q, u, v, a, c, t; - u = x; - v = y; - c = 1; - a = 0; - while (u != 0) { - t = Integer.fdivrem(v, u); - q = t[0]; - v = u; - u = t[1]; - t = c; - c = a - q * c; - a = t; - } - /* v = gcd(x, y) */ - if (v != 1) - throw RangeError("not invertible"); - return a % y; - }, - /* return a ^ b modulo m */ - pmod(a, b, m) { - var r; - if (b == 0) - return 1; - if (b < 0) { - a = Integer.invmod(a, m); - b = -b; - } - r = 1; - for(;;) { - if (b & 1) { - r = (r * a) % m; - } - b >>= 1; - if (b == 0) - break; - a = (a * a) % m; - } - return r; - }, - - /* return true if n is prime (or probably prime with - probability 1-0.5^t) */ - isPrime(n, t) { - var i, d, n1; - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - if (n <= 1) - return false; - n1 = small_primes.length; - /* XXX: need Integer.sqrt() */ - for(i = 0; i < n1; i++) { - d = small_primes[i]; - if (d == n) - return true; - if (d > n) - return false; - if ((n % d) == 0) - return false; - } - if (n < d * d) - return true; - if (typeof t == "undefined") - t = 64; - return miller_rabin_test(n, t); - }, - nextPrime(n) { - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - if (n < 1) - n = 1; - for(;;) { - n++; - if (Integer.isPrime(n)) - return n; - } - }, - factor(n) { - var r, d; - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - r = []; - if (abs(n) <= 1) { - r.push(n); - return r; - } - if (n < 0) { - r.push(-1); - n = -n; - } - - while ((n % 2) == 0) { - n >>= 1; - r.push(2); - } - - d = 3; - while (n != 1) { - if (Integer.isPrime(n)) { - r.push(n); - break; - } - /* we are sure there is at least one divisor, so one test */ - for(;;) { - if ((n % d) == 0) - break; - d += 2; - } - for(;;) { - r.push(d); - n = Integer.tdiv(n, d); - if ((n % d) != 0) - break; - } - } - return r; - }, - }); - - add_props(Integer.prototype, { - inverse() { - return 1 / this; - }, - norm2() { - return this * this; - }, - abs() { - var v = this; - if (v < 0) - v = -v; - return v; - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - if (this == 0) - return 1; - else - return Float.exp(this); - }, - log() { - if (this == 1) - return 0; - else - return Float(this).log(); - }, - }); - - /* Fraction */ - - Fraction = function Fraction(a, b) - { - var d, r, obj; - - if (new.target) - throw TypeError("not a constructor"); - if (a instanceof Fraction) - return a; - if (!Integer.isInteger(a)) - throw TypeError("integer expected"); - if (typeof b === "undefined") { - b = 1; - } else { - if (!Integer.isInteger(b)) - throw TypeError("integer expected"); - if (b == 0) - throw RangeError("division by zero"); - d = Integer.gcd(a, b); - if (d != 1) { - a = Integer.tdiv(a, d); - b = Integer.tdiv(b, d); - } - - /* the fractions are normalized with den > 0 */ - if (b < 0) { - a = -a; - b = -b; - } - } - obj = Object.create(Fraction.prototype); - obj.num = a; - obj.den = b; - return obj; - } - - function fraction_add(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den + a.den * b.num, a.den * b.den); - } - function fraction_sub(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den - a.den * b.num, a.den * b.den); - } - function fraction_mul(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.num, a.den * b.den); - } - function fraction_div(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den, a.den * b.num); - } - function fraction_mod(a, b) { - var a1 = Fraction(a); - var b1 = Fraction(b); - return a - Integer.ediv(a1.num * b1.den, a1.den * b1.num) * b; - } - function fraction_eq(a, b) { - a = Fraction(a); - b = Fraction(b); - /* we assume the fractions are normalized */ - return (a.num == b.num && a.den == b.den); - } - function fraction_lt(a, b) { - a = Fraction(a); - b = Fraction(b); - return (a.num * b.den < b.num * a.den); - } - - /* operators are needed for fractions */ - function float_add(a, b) { - return Float(a) + Float(b); - } - function float_sub(a, b) { - return Float(a) - Float(b); - } - function float_mul(a, b) { - return Float(a) * Float(b); - } - function float_div(a, b) { - return Float(a) / Float(b); - } - function float_mod(a, b) { - return Float(a) % Float(b); - } - function float_pow(a, b) { - return Float(a) ** Float(b); - } - function float_eq(a, b) { - /* XXX: may be better to use infinite precision for the comparison */ - return Float(a) === Float(b); - } - function float_lt(a, b) { - a = Float(a); - b = Float(b); - /* XXX: may be better to use infinite precision for the comparison */ - if (Float.isNaN(a) || Float.isNaN(b)) - return undefined; - else - return a < b; - } - - operators_set(Fraction.prototype, - { - "+": fraction_add, - "-": fraction_sub, - "*": fraction_mul, - "/": fraction_div, - "%": fraction_mod, - "**": generic_pow, - "==": fraction_eq, - "<": fraction_lt, - "pos"(a) { - return a; - }, - "neg"(a) { - return Fraction(-a.num, a.den); - }, - }, - { - left: [Number, BigInt], - right: [Number, BigInt], - "+": fraction_add, - "-": fraction_sub, - "*": fraction_mul, - "/": fraction_div, - "%": fraction_mod, - "**": generic_pow, - "==": fraction_eq, - "<": fraction_lt, - }, - { - left: Float, - right: Float, - "+": float_add, - "-": float_sub, - "*": float_mul, - "/": float_div, - "%": float_mod, - "**": float_pow, - "==": float_eq, - "<": float_lt, - }); - - add_props(Fraction, { - /* (internal use) simplify 'a' to an integer when possible */ - toFraction(a, b) { - var r = Fraction(a, b); - if (algebraicMode && r.den == 1) - return r.num; - else - return r; - }, - }); - - add_props(Fraction.prototype, { - [Symbol.toPrimitive](hint) { - if (hint === "string") { - return this.toString(); - } else { - return Float(this.num) / this.den; - } - }, - inverse() { - return Fraction(this.den, this.num); - }, - toString() { - return this.num + "/" + this.den; - }, - norm2() { - return this * this; - }, - abs() { - if (this.num < 0) - return -this; - else - return this; - }, - conj() { - return this; - }, - arg() { - if (this.num >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(Float(this)); - }, - log() { - return Float(this).log(); - }, - }); - - /* Number (Float64) */ - - add_props(Number.prototype, { - inverse() { - return 1 / this; - }, - norm2() { - return this * this; - }, - abs() { - return Math.abs(this); - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(this); - }, - log() { - if (this < 0) { - return Complex(this).log(); - } else { - return Float.log(this); - } - }, - }); - - /* Float */ - - var const_tab = []; - - /* we cache the constants for small precisions */ - function get_const(n) { - var t, c, p; - t = const_tab[n]; - p = BigFloatEnv.prec; - if (t && t.prec == p) { - return t.val; - } else { - switch(n) { - case 0: c = Float.exp(1); break; - case 1: c = Float.log(10); break; -// case 2: c = Float.log(2); break; - case 3: c = 1/Float.log(2); break; - case 4: c = 1/Float.log(10); break; -// case 5: c = Float.atan(1) * 4; break; - case 6: c = Float.sqrt(0.5); break; - case 7: c = Float.sqrt(2); break; - } - if (p <= 1024) { - const_tab[n] = { prec: p, val: c }; - } - return c; - } - } - - add_props(Float, { - isFloat(a) { - return typeof a === "number" || typeof a === "bigfloat"; - }, - bestappr(u, b) { - var num1, num0, den1, den0, u, num, den, n; - - if (typeof b === "undefined") - throw TypeError("second argument expected"); - num1 = 1; - num0 = 0; - den1 = 0; - den0 = 1; - for(;;) { - n = Integer(Float.floor(u)); - num = n * num1 + num0; - den = n * den1 + den0; - if (den > b) - break; - u = 1.0 / (u - n); - num0 = num1; - num1 = num; - den0 = den1; - den1 = den; - } - return Fraction(num1, den1); - }, - /* similar constants as Math.x */ - get E() { return get_const(0); }, - get LN10() { return get_const(1); }, -// get LN2() { return get_const(2); }, - get LOG2E() { return get_const(3); }, - get LOG10E() { return get_const(4); }, -// get PI() { return get_const(5); }, - get SQRT1_2() { return get_const(6); }, - get SQRT2() { return get_const(7); }, - }); - - add_props(Float.prototype, { - inverse() { - return 1.0 / this; - }, - norm2() { - return this * this; - }, - abs() { - return Float.abs(this); - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(this); - }, - log() { - if (this < 0) { - return Complex(this).log(); - } else { - return Float.log(this); - } - }, - }); - - /* Complex */ - - Complex = function Complex(re, im) - { - var obj; - if (new.target) - throw TypeError("not a constructor"); - if (re instanceof Complex) - return re; - if (typeof im === "undefined") { - im = 0; - } - obj = Object.create(Complex.prototype); - obj.re = re; - obj.im = im; - return obj; - } - - - function complex_add(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re + b.re, a.im + b.im); - } - function complex_sub(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re - b.re, a.im - b.im); - } - function complex_mul(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re * b.re - a.im * b.im, - a.re * b.im + a.im * b.re); - } - function complex_div(a, b) { - a = Complex(a); - b = Complex(b); - return a * b.inverse(); - } - function complex_eq(a, b) { - a = Complex(a); - b = Complex(b); - return a.re == b.re && a.im == b.im; - } - - operators_set(Complex.prototype, - { - "+": complex_add, - "-": complex_sub, - "*": complex_mul, - "/": complex_div, - "**": generic_pow, - "==": complex_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return Complex(-a.re, -a.im); - } - }, - { - left: [Number, BigInt, Float, Fraction], - right: [Number, BigInt, Float, Fraction], - "+": complex_add, - "-": complex_sub, - "*": complex_mul, - "/": complex_div, - "**": generic_pow, - "==": complex_eq, - }); - - add_props(Complex, { - /* simplify to real number when possible */ - toComplex(re, im) { - if (algebraicMode && im == 0) - return re; - else - return Complex(re, im); - }, - }); - - add_props(Complex.prototype, { - inverse() { - var c = this.norm2(); - return Complex(this.re / c, -this.im / c); - }, - toString() { - var v, s = "", a = this; - if (a.re != 0) - s += a.re.toString(); - if (a.im == 1) { - if (s != "") - s += "+"; - s += "I"; - } else if (a.im == -1) { - s += "-I"; - } else { - v = a.im.toString(); - if (v[0] != "-" && s != "") - s += "+"; - s += v + "*I"; - } - return s; - }, - norm2() { - return this.re * this.re + this.im * this.im; - }, - abs() { - return Float.sqrt(norm2(this)); - }, - conj() { - return Complex(this.re, -this.im); - }, - arg() { - return Float.atan2(this.im, this.re); - }, - exp() { - var arg = this.im, r = this.re.exp(); - return Complex(r * cos(arg), r * sin(arg)); - }, - log() { - return Complex(abs(this).log(), atan2(this.im, this.re)); - }, - }); - - /* Mod */ - - Mod = function Mod(a, m) { - var obj, t; - if (new.target) - throw TypeError("not a constructor"); - obj = Object.create(Mod.prototype); - if (Integer.isInteger(m)) { - if (m <= 0) - throw RangeError("the modulo cannot be <= 0"); - if (Integer.isInteger(a)) { - a %= m; - } else if (a instanceof Fraction) { - return Mod(a.num, m) / a.den; - } else { - throw TypeError("invalid types"); - } - } else { - throw TypeError("invalid types"); - } - obj.res = a; - obj.mod = m; - return obj; - }; - - function mod_add(a, b) { - if (!(a instanceof Mod)) { - return Mod(a + b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res + b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res + b.res, a.mod); - } - } - function mod_sub(a, b) { - if (!(a instanceof Mod)) { - return Mod(a - b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res - b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res - b.res, a.mod); - } - } - function mod_mul(a, b) { - if (!(a instanceof Mod)) { - return Mod(a * b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res * b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res * b.res, a.mod); - } - } - function mod_div(a, b) { - if (!(b instanceof Mod)) - b = Mod(b, a.mod); - return mod_mul(a, b.inverse()); - } - function mod_eq(a, b) { - return (a.mod == b.mod && a.res == b.res); - } - - operators_set(Mod.prototype, - { - "+": mod_add, - "-": mod_sub, - "*": mod_mul, - "/": mod_div, - "**": generic_pow, - "==": mod_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return Mod(-a.res, a.mod); - } - }, - { - left: [Number, BigInt, Float, Fraction], - right: [Number, BigInt, Float, Fraction], - "+": mod_add, - "-": mod_sub, - "*": mod_mul, - "/": mod_div, - "**": generic_pow, - }); - - add_props(Mod.prototype, { - inverse() { - var a = this, m = a.mod; - if (Integer.isInteger(m)) { - return Mod(Integer.invmod(a.res, m), m); - } else { - throw TypeError("unsupported type"); - } - }, - toString() { - return "Mod(" + this.res + "," + this.mod + ")"; - }, - }); - - /* Polynomial */ - - function polynomial_is_scalar(a) - { - if (typeof a === "number" || - typeof a === "bigint" || - typeof a === "bigfloat") - return true; - if (a instanceof Fraction || - a instanceof Complex || - a instanceof Mod) - return true; - return false; - } - - Polynomial = function Polynomial(a) - { - if (new.target) - throw TypeError("not a constructor"); - if (a instanceof Polynomial) { - return a; - } else if (Array.isArray(a)) { - if (a.length == 0) - a = [ 0 ]; - Object.setPrototypeOf(a, Polynomial.prototype); - return a.trim(); - } else if (polynomial_is_scalar(a)) { - a = [a]; - Object.setPrototypeOf(a, Polynomial.prototype); - return a; - } else { - throw TypeError("invalid type"); - } - } - - function number_need_paren(c) - { - return !(Integer.isInteger(c) || - Float.isFloat(c) || - c instanceof Fraction || - (c instanceof Complex && c.re == 0)); - } - - /* string for c*X^i */ - function monomial_toString(c, i) - { - var str1; - if (i == 0) { - str1 = c.toString(); - } else { - if (c == 1) { - str1 = ""; - } else if (c == -1) { - str1 = "-"; - } else { - if (number_need_paren(c)) { - str1 = "(" + c + ")"; - } else { - str1 = String(c); - } - str1 += "*"; - } - str1 += "X"; - if (i != 1) { - str1 += "^" + i; - } - } - return str1; - } - - /* find one complex root of 'p' starting from z at precision eps using - at most max_it iterations. Return null if could not find root. */ - function poly_root_laguerre1(p, z, max_it) - { - var p1, p2, i, z0, z1, z2, d, t0, t1, d1, d2, e, el, zl; - - d = p.deg(); - if (d == 1) { - /* monomial case */ - return -p[0] / p[1]; - } - /* trivial zero */ - if (p[0] == 0) - return 0.0; - - p1 = p.deriv(); - p2 = p1.deriv(); - el = 0.0; - zl = 0.0; - for(i = 0; i < max_it; i++) { - z0 = p.apply(z); - if (z0 == 0) - return z; /* simple exit case */ - - /* Ward stopping criteria */ - e = abs(z - zl); -// print("e", i, e); - if (i >= 2 && e >= el) { - if (abs(zl) < 1e-4) { - if (e < 1e-7) - return zl; - } else { - if (e < abs(zl) * 1e-3) - return zl; - } - } - el = e; - zl = z; - - z1 = p1.apply(z); - z2 = p2.apply(z); - t0 = (d - 1) * z1; - t0 = t0 * t0; - t1 = d * (d - 1) * z0 * z2; - t0 = sqrt(t0 - t1); - d1 = z1 + t0; - d2 = z1 - t0; - if (norm2(d2) > norm2(d1)) - d1 = d2; - if (d1 == 0) - return null; - z = z - d * z0 / d1; - } - return null; - } - - function poly_roots(p) - { - var d, i, roots, j, z, eps; - var start_points = [ 0.1, -1.4, 1.7 ]; - - if (!(p instanceof Polynomial)) - throw TypeError("polynomial expected"); - d = p.deg(); - if (d <= 0) - return []; - eps = 2.0 ^ (-BigFloatEnv.prec); - roots = []; - for(i = 0; i < d; i++) { - /* XXX: should select another start point if error */ - for(j = 0; j < 3; j++) { - z = poly_root_laguerre1(p, start_points[j], 100); - if (z !== null) - break; - } - if (j == 3) - throw RangeError("error in root finding algorithm"); - roots[i] = z; - p = Polynomial.divrem(p, X - z)[0]; - } - return roots; - } - - add_props(Polynomial.prototype, { - trim() { - var a = this, i; - i = a.length; - while (i > 1 && a[i - 1] == 0) - i--; - a.length = i; - return a; - }, - conj() { - var r, i, n, a; - a = this; - n = a.length; - r = []; - for(i = 0; i < n; i++) - r[i] = a[i].conj(); - return Polynomial(r); - }, - inverse() { - return RationalFunction(Polynomial([1]), this); - }, - toString() { - var i, str, str1, c, a = this; - if (a.length == 1) { - return a[0].toString(); - } - str=""; - for(i = a.length - 1; i >= 0; i--) { - c = a[i]; - if (c == 0 || - (c instanceof Mod) && c.res == 0) - continue; - str1 = monomial_toString(c, i); - if (str1[0] != "-") { - if (str != "") - str += "+"; - } - str += str1; - } - return str; - }, - deg() { - if (this.length == 1 && this[0] == 0) - return -Infinity; - else - return this.length - 1; - }, - apply(b) { - var i, n, r, a = this; - n = a.length - 1; - r = a[n]; - while (n > 0) { - n--; - r = r * b + a[n]; - } - return r; - }, - deriv() { - var a = this, n, r, i; - n = a.length; - if (n == 1) { - return Polynomial(0); - } else { - r = []; - for(i = 1; i < n; i++) { - r[i - 1] = i * a[i]; - } - return Polynomial(r); - } - }, - integ() { - var a = this, n, r, i; - n = a.length; - r = [0]; - for(i = 0; i < n; i++) { - r[i + 1] = a[i] / (i + 1); - } - return Polynomial(r); - }, - norm2() { - var a = this, n, r, i; - n = a.length; - r = 0; - for(i = 0; i < n; i++) { - r += a[i].norm2(); - } - return r; - }, - }); - - - function polynomial_add(a, b) { - var tmp, r, i, n1, n2; - a = Polynomial(a); - b = Polynomial(b); - if (a.length < b.length) { - tmp = a; - a = b; - b = tmp; - } - n1 = b.length; - n2 = a.length; - r = []; - for(i = 0; i < n1; i++) - r[i] = a[i] + b[i]; - for(i = n1; i < n2; i++) - r[i] = a[i]; - return Polynomial(r); - } - function polynomial_sub(a, b) { - return polynomial_add(a, -b); - } - function polynomial_mul(a, b) { - var i, j, n1, n2, n, r; - a = Polynomial(a); - b = Polynomial(b); - n1 = a.length; - n2 = b.length; - n = n1 + n2 - 1; - r = []; - for(i = 0; i < n; i++) - r[i] = 0; - for(i = 0; i < n1; i++) { - for(j = 0; j < n2; j++) { - r[i + j] += a[i] * b[j]; - } - } - return Polynomial(r); - } - function polynomial_div_scalar(a, b) { - return a * (1 / b); - } - function polynomial_div(a, b) - { - return RationalFunction(Polynomial(a), - Polynomial(b)); - } - function polynomial_mod(a, b) { - return Polynomial.divrem(a, b)[1]; - } - function polynomial_eq(a, b) { - var n, i; - n = a.length; - if (n != b.length) - return false; - for(i = 0; i < n; i++) { - if (a[i] != b[i]) - return false; - } - return true; - } - - operators_set(Polynomial.prototype, - { - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div, - "**": generic_pow, - "==": polynomial_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - var r, i, n, a; - n = a.length; - r = []; - for(i = 0; i < n; i++) - r[i] = -a[i]; - return Polynomial(r); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod], - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div, - "**": generic_pow, /* XXX: only for integer */ - }, - { - right: [Number, BigInt, Float, Fraction, Complex, Mod], - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div_scalar, - "**": generic_pow, /* XXX: only for integer */ - }); - - add_props(Polynomial, { - divrem(a, b) { - var n1, n2, i, j, q, r, n, c; - if (b.deg() < 0) - throw RangeError("division by zero"); - n1 = a.length; - n2 = b.length; - if (n1 < n2) - return [Polynomial([0]), a]; - r = Array.prototype.dup.call(a); - q = []; - n2--; - n = n1 - n2; - for(i = 0; i < n; i++) - q[i] = 0; - for(i = n - 1; i >= 0; i--) { - c = r[i + n2]; - if (c != 0) { - c = c / b[n2]; - r[i + n2] = 0; - for(j = 0; j < n2; j++) { - r[i + j] -= b[j] * c; - } - q[i] = c; - } - } - return [Polynomial(q), Polynomial(r)]; - }, - gcd(a, b) { - var t; - while (b.deg() >= 0) { - t = Polynomial.divrem(a, b); - a = b; - b = t[1]; - } - /* convert to monic form */ - return a / a[a.length - 1]; - }, - invmod(x, y) { - var q, u, v, a, c, t; - u = x; - v = y; - c = Polynomial([1]); - a = Polynomial([0]); - while (u.deg() >= 0) { - t = Polynomial.divrem(v, u); - q = t[0]; - v = u; - u = t[1]; - t = c; - c = a - q * c; - a = t; - } - /* v = gcd(x, y) */ - if (v.deg() > 0) - throw RangeError("not invertible"); - return Polynomial.divrem(a, y)[1]; - }, - roots(p) { - return poly_roots(p); - } - }); - - /* Polynomial Modulo Q */ - - PolyMod = function PolyMod(a, m) { - var obj, t; - if (new.target) - throw TypeError("not a constructor"); - obj = Object.create(PolyMod.prototype); - if (m instanceof Polynomial) { - if (m.deg() <= 0) - throw RangeError("the modulo cannot have a degree <= 0"); - if (a instanceof RationalFunction) { - return PolyMod(a.num, m) / a.den; - } else { - a = Polynomial(a); - t = Polynomial.divrem(a, m); - a = t[1]; - } - } else { - throw TypeError("invalid types"); - } - obj.res = a; - obj.mod = m; - return obj; - }; - - function polymod_add(a, b) { - if (!(a instanceof PolyMod)) { - return PolyMod(a + b.res, b.mod); - } else if (!(b instanceof PolyMod)) { - return PolyMod(a.res + b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return PolyMod(a.res + b.res, a.mod); - } - } - function polymod_sub(a, b) { - return polymod_add(a, -b); - } - function polymod_mul(a, b) { - if (!(a instanceof PolyMod)) { - return PolyMod(a * b.res, b.mod); - } else if (!(b instanceof PolyMod)) { - return PolyMod(a.res * b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return PolyMod(a.res * b.res, a.mod); - } - } - function polymod_div(a, b) { - if (!(b instanceof PolyMod)) - b = PolyMod(b, a.mod); - return polymod_mul(a, b.inverse()); - } - function polymod_eq(a, b) { - return (a.mod == b.mod && a.res == b.res); - } - - operators_set(PolyMod.prototype, - { - "+": polymod_add, - "-": polymod_sub, - "*": polymod_mul, - "/": polymod_div, - "**": generic_pow, - "==": polymod_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return PolyMod(-a.res, a.mod); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": polymod_add, - "-": polymod_sub, - "*": polymod_mul, - "/": polymod_div, - "**": generic_pow, /* XXX: only for integer */ - }); - - add_props(PolyMod.prototype, { - inverse() { - var a = this, m = a.mod; - if (m instanceof Polynomial) { - return PolyMod(Polynomial.invmod(a.res, m), m); - } else { - throw TypeError("unsupported type"); - } - }, - toString() { - return "PolyMod(" + this.res + "," + this.mod + ")"; - }, - }); - - /* Rational function */ - - RationalFunction = function RationalFunction(a, b) - { - var t, r, d, obj; - if (new.target) - throw TypeError("not a constructor"); - if (!(a instanceof Polynomial) || - !(b instanceof Polynomial)) - throw TypeError("polynomial expected"); - t = Polynomial.divrem(a, b); - r = t[1]; - if (r.deg() < 0) - return t[0]; /* no need for a fraction */ - d = Polynomial.gcd(b, r); - if (d.deg() > 0) { - a = Polynomial.divrem(a, d)[0]; - b = Polynomial.divrem(b, d)[0]; - } - obj = Object.create(RationalFunction.prototype); - obj.num = a; - obj.den = b; - return obj; - } - - add_props(RationalFunction.prototype, { - inverse() { - return RationalFunction(this.den, this.num); - }, - conj() { - return RationalFunction(this.num.conj(), this.den.conj()); - }, - toString() { - var str; - if (this.num.deg() <= 0 && - !number_need_paren(this.num[0])) - str = this.num.toString(); - else - str = "(" + this.num.toString() + ")"; - str += "/(" + this.den.toString() + ")" - return str; - }, - apply(b) { - return this.num.apply(b) / this.den.apply(b); - }, - deriv() { - var n = this.num, d = this.den; - return RationalFunction(n.deriv() * d - n * d.deriv(), d * d); - }, - }); - - function ratfunc_add(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den + a.den * b.num, a.den * b.den); - } - function ratfunc_sub(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den - a.den * b.num, a.den * b.den); - } - function ratfunc_mul(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.num, a.den * b.den); - } - function ratfunc_div(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den, a.den * b.num); - } - function ratfunc_eq(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - /* we assume the fractions are normalized */ - return (a.num == b.num && a.den == b.den); - } - - operators_set(RationalFunction.prototype, - { - "+": ratfunc_add, - "-": ratfunc_sub, - "*": ratfunc_mul, - "/": ratfunc_div, - "**": generic_pow, - "==": ratfunc_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return RationalFunction(-this.num, this.den); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": ratfunc_add, - "-": ratfunc_sub, - "*": ratfunc_mul, - "/": ratfunc_div, - "**": generic_pow, /* should only be used with integers */ - }); - - add_props(RationalFunction, { - /* This function always return a RationalFunction object even - if it could simplified to a polynomial, so it is not - equivalent to RationalFunction(a) */ - toRationalFunction(a) { - var obj; - if (a instanceof RationalFunction) { - return a; - } else { - obj = Object.create(RationalFunction.prototype); - obj.num = Polynomial(a); - obj.den = Polynomial(1); - return obj; - } - }, - }); - - /* Power series */ - - /* 'a' is an array */ - function get_emin(a) { - var i, n; - n = a.length; - for(i = 0; i < n; i++) { - if (a[i] != 0) - return i; - } - return n; - }; - - function series_is_scalar_or_polynomial(a) - { - return polynomial_is_scalar(a) || - (a instanceof Polynomial); - } - - /* n is the maximum number of terms if 'a' is not a serie */ - Series = function Series(a, n) { - var emin, r, i; - - if (a instanceof Series) { - return a; - } else if (series_is_scalar_or_polynomial(a)) { - if (n <= 0) { - /* XXX: should still use the polynomial degree */ - return Series.zero(0, 0); - } else { - a = Polynomial(a); - emin = get_emin(a); - r = Series.zero(n, emin); - n = Math.min(a.length - emin, n); - for(i = 0; i < n; i++) - r[i] = a[i + emin]; - return r; - } - } else if (a instanceof RationalFunction) { - return Series(a.num, n) / a.den; - } else { - throw TypeError("invalid type"); - } - }; - - function series_add(v1, v2) { - var tmp, d, emin, n, r, i, j, v2_emin, c1, c2; - if (!(v1 instanceof Series)) { - tmp = v1; - v1 = v2; - v2 = tmp; - } - d = v1.emin + v1.length; - if (series_is_scalar_or_polynomial(v2)) { - v2 = Polynomial(v2); - if (d <= 0) - return v1; - v2_emin = 0; - } else if (v2 instanceof RationalFunction) { - /* compute the emin of the rational fonction */ - i = get_emin(v2.num) - get_emin(v2.den); - if (d <= i) - return v1; - /* compute the serie with the required terms */ - v2 = Series(v2, d - i); - v2_emin = v2.emin; - } else { - v2_emin = v2.emin; - d = Math.min(d, v2_emin + v2.length); - } - emin = Math.min(v1.emin, v2_emin); - n = d - emin; - r = Series.zero(n, emin); - /* XXX: slow */ - for(i = emin; i < d; i++) { - j = i - v1.emin; - if (j >= 0 && j < v1.length) - c1 = v1[j]; - else - c1 = 0; - j = i - v2_emin; - if (j >= 0 && j < v2.length) - c2 = v2[j]; - else - c2 = 0; - r[i - emin] = c1 + c2; - } - return r.trim(); - } - function series_sub(a, b) { - return series_add(a, -b); - } - function series_mul(v1, v2) { - var n, i, j, r, n, emin, n1, n2, k; - if (!(v1 instanceof Series)) - v1 = Series(v1, v2.length); - else if (!(v2 instanceof Series)) - v2 = Series(v2, v1.length); - emin = v1.emin + v2.emin; - n = Math.min(v1.length, v2.length); - n1 = v1.length; - n2 = v2.length; - r = Series.zero(n, emin); - for(i = 0; i < n1; i++) { - k = Math.min(n2, n - i); - for(j = 0; j < k; j++) { - r[i + j] += v1[i] * v2[j]; - } - } - return r.trim(); - } - function series_div(v1, v2) { - if (!(v2 instanceof Series)) - v2 = Series(v2, v1.length); - return series_mul(v1, v2.inverse()); - } - function series_pow(a, b) { - if (Integer.isInteger(b)) { - return generic_pow(a, b); - } else { - if (!(a instanceof Series)) - a = Series(a, b.length); - return exp(log(a) * b); - } - } - function series_eq(a, b) { - var n, i; - if (a.emin != b.emin) - return false; - n = a.length; - if (n != b.length) - return false; - for(i = 0; i < n; i++) { - if (a[i] != b[i]) - return false; - } - return true; - } - - operators_set(Series.prototype, - { - "+": series_add, - "-": series_sub, - "*": series_mul, - "/": series_div, - "**": series_pow, - "==": series_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - var obj, n, i; - n = a.length; - obj = Series.zero(a.length, a.emin); - for(i = 0; i < n; i++) { - obj[i] = -a[i]; - } - return obj; - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": series_add, - "-": series_sub, - "*": series_mul, - "/": series_div, - "**": series_pow, - }); - - add_props(Series.prototype, { - conj() { - var obj, n, i; - n = this.length; - obj = Series.zero(this.length, this.emin); - for(i = 0; i < n; i++) { - obj[i] = this[i].conj(); - } - return obj; - }, - inverse() { - var r, n, i, j, sum, v1 = this; - n = v1.length; - if (n == 0) - throw RangeError("division by zero"); - r = Series.zero(n, -v1.emin); - r[0] = 1 / v1[0]; - for(i = 1; i < n; i++) { - sum = 0; - for(j = 1; j <= i; j++) { - sum += v1[j] * r[i - j]; - } - r[i] = -sum * r[0]; - } - return r; - }, - /* remove leading zero terms */ - trim() { - var i, j, n, r, v1 = this; - n = v1.length; - i = 0; - while (i < n && v1[i] == 0) - i++; - if (i == 0) - return v1; - for(j = i; j < n; j++) - v1[j - i] = v1[j]; - v1.length = n - i; - v1.__proto__.emin += i; - return v1; - }, - toString() { - var i, j, str, str1, c, a = this, emin, n; - str=""; - emin = this.emin; - n = this.length; - for(j = 0; j < n; j++) { - i = j + emin; - c = a[j]; - if (c != 0) { - str1 = monomial_toString(c, i); - if (str1[0] != "-") { - if (str != "") - str += "+"; - } - str += str1; - } - } - if (str != "") - str += "+"; - str += "O(" + monomial_toString(1, n + emin) + ")"; - return str; - }, - apply(b) { - var i, n, r, a = this; - n = a.length; - if (n == 0) - return 0; - r = a[--n]; - while (n > 0) { - n--; - r = r * b + a[n]; - } - if (a.emin != 0) - r *= b ^ a.emin; - return r; - }, - deriv() { - var a = this, n = a.length, emin = a.emin, r, i, j; - if (n == 0 && emin == 0) { - return Series.zero(0, 0); - } else { - r = Series.zero(n, emin - 1); - for(i = 0; i < n; i++) { - j = emin + i; - if (j == 0) - r[i] = 0; - else - r[i] = j * a[i]; - } - return r.trim(); - } - }, - integ() { - var a = this, n = a.length, emin = a.emin, i, j, r; - r = Series.zero(n, emin + 1); - for(i = 0; i < n; i++) { - j = emin + i; - if (j == -1) { - if (a[i] != 0) - throw RangeError("cannot represent integ(1/X)"); - } else { - r[i] = a[i] / (j + 1); - } - } - return r.trim(); - }, - exp() { - var c, i, r, n, a = this; - if (a.emin < 0) - throw RangeError("negative exponent in exp"); - n = a.emin + a.length; - if (a.emin > 0 || a[0] == 0) { - c = 1; - } else { - c = global.exp(a[0]); - a -= a[0]; - } - r = Series.zero(n, 0); - for(i = 0; i < n; i++) { - r[i] = c / fact(i); - } - return r.apply(a); - }, - log() { - var a = this, r; - if (a.emin != 0) - throw RangeError("log argument must have a non zero constant term"); - r = integ(deriv(a) / a); - /* add the constant term */ - r += global.log(a[0]); - return r; - }, - }); - - add_props(Series, { - /* new series of length n and first exponent emin */ - zero(n, emin) { - var r, i, obj; - - r = []; - for(i = 0; i < n; i++) - r[i] = 0; - /* we return an array and store emin in its prototype */ - obj = Object.create(Series.prototype); - obj.emin = emin; - Object.setPrototypeOf(r, obj); - return r; - }, - O(a) { - function ErrorO() { - return TypeError("invalid O() argument"); - } - var n; - if (series_is_scalar_or_polynomial(a)) { - a = Polynomial(a); - n = a.deg(); - if (n < 0) - throw ErrorO(); - } else if (a instanceof RationalFunction) { - if (a.num.deg() != 0) - throw ErrorO(); - n = a.den.deg(); - if (n < 0) - throw ErrorO(); - n = -n; - } else - throw ErrorO(); - return Series.zero(0, n); - }, - }); - - /* Array (Matrix) */ - - Matrix = function Matrix(h, w) { - var i, j, r, rl; - if (typeof w === "undefined") - w = h; - r = []; - for(i = 0; i < h; i++) { - rl = []; - for(j = 0; j < w; j++) - rl[j] = 0; - r[i] = rl; - } - return r; - }; - - add_props(Matrix, { - idn(n) { - var r, i; - r = Matrix(n, n); - for(i = 0; i < n; i++) - r[i][i] = 1; - return r; - }, - diag(a) { - var r, i, n; - n = a.length; - r = Matrix(n, n); - for(i = 0; i < n; i++) - r[i][i] = a[i]; - return r; - }, - hilbert(n) { - var i, j, r; - r = Matrix(n); - for(i = 0; i < n; i++) { - for(j = 0; j < n; j++) { - r[i][j] = 1 / (1 + i + j); - } - } - return r; - }, - trans(a) { - var h, w, r, i, j; - if (!Array.isArray(a)) - throw TypeError("matrix expected"); - h = a.length; - if (!Array.isArray(a[0])) { - w = 1; - r = Matrix(w, h); - for(i = 0; i < h; i++) { - r[0][i] = a[i]; - } - } else { - w = a[0].length; - r = Matrix(w, h); - for(i = 0; i < h; i++) { - for(j = 0; j < w; j++) { - r[j][i] = a[i][j]; - } - } - } - return r; - }, - check_square(a) { - var a, n; - if (!Array.isArray(a)) - throw TypeError("array expected"); - n = a.length; - if (!Array.isArray(a[0]) || n != a[0].length) - throw TypeError("square matrix expected"); - return n; - }, - trace(a) { - var n, r, i; - n = Matrix.check_square(a); - r = a[0][0]; - for(i = 1; i < n; i++) { - r += a[i][i]; - } - return r; - }, - charpoly(a) { - var n, p, c, i, j, coef; - n = Matrix.check_square(a); - p = []; - for(i = 0; i < n + 1; i++) - p[i] = 0; - p[n] = 1; - c = Matrix.idn(n); - for(i = 0; i < n; i++) { - c = c * a; - coef = -trace(c) / (i + 1); - p[n - i - 1] = coef; - for(j = 0; j < n; j++) - c[j][j] += coef; - } - return Polynomial(p); - }, - eigenvals(a) { - return Polynomial.roots(Matrix.charpoly(a)); - }, - det(a) { - var n, i, j, k, s, src, v, c; - - n = Matrix.check_square(a); - s = 1; - src = a.dup(); - for(i=0;i") /* symbols */ @@ -266,8 +258,5 @@ DEF(Symbol_hasInstance, "Symbol.hasInstance") DEF(Symbol_species, "Symbol.species") DEF(Symbol_unscopables, "Symbol.unscopables") DEF(Symbol_asyncIterator, "Symbol.asyncIterator") -#ifdef CONFIG_BIGNUM -DEF(Symbol_operatorSet, "Symbol.operatorSet") -#endif - + #endif /* DEF */ diff --git a/quickjs-c-atomics.h b/quickjs-c-atomics.h new file mode 100644 index 0000000..8fc6b72 --- /dev/null +++ b/quickjs-c-atomics.h @@ -0,0 +1,54 @@ +/* + * 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-libc.c b/quickjs-libc.c index d4f4d67..a7b334f 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -1,6 +1,6 @@ /* * QuickJS C library - * + * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon * @@ -28,49 +28,82 @@ #include #include #include +#if !defined(_MSC_VER) #include +#endif #include #include +#if !defined(_MSC_VER) #include +#endif #include #include #include #include +#if defined(_MSC_VER) +#include "dirent_compat.h" +#else #include +#endif #if defined(_WIN32) #include +#include +#include #include -#include +#include +#include +#include +#define popen _popen +#define pclose _pclose +#define rmdir _rmdir +#define getcwd _getcwd +#define chdir _chdir #else +#include +#if !defined(__wasi__) #include #include -#include +#include #include +#endif #if defined(__APPLE__) typedef sig_t sighandler_t; -#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 -#if !defined(_WIN32) +#endif /* _WIN32 */ + +#if !defined(_WIN32) && !defined(__wasi__) /* enable the os.Worker API. IT relies on POSIX threads */ #define USE_WORKER #endif #ifdef USE_WORKER #include -#include +#include "quickjs-c-atomics.h" #endif #include "cutils.h" #include "list.h" #include "quickjs-libc.h" +#define MAX_SAFE_INTEGER (((int64_t) 1 << 53) - 1) + +#ifndef QJS_NATIVE_MODULE_SUFFIX +#ifdef _WIN32 +#define QJS_NATIVE_MODULE_SUFFIX ".dll" +#else +#define QJS_NATIVE_MODULE_SUFFIX ".so" +#endif +#endif + /* TODO: - add socket calls */ @@ -89,8 +122,10 @@ typedef struct { typedef struct { struct list_head link; - BOOL has_object; + int64_t timer_id; + uint8_t repeats:1; int64_t timeout; + int64_t delay; JSValue func; } JSOSTimer; @@ -125,12 +160,16 @@ typedef struct JSThreadState { struct list_head os_timers; /* list of JSOSTimer.link */ struct list_head port_list; /* list of JSWorkerMessageHandler.link */ int eval_script_recurse; /* only used in the main thread */ + int64_t next_timer_id; /* for setTimeout / setInterval */ + JSValue exc; /* current exception from one of our handlers */ + BOOL can_js_os_poll; /* not used in the main thread */ JSWorkerMessagePipe *recv_pipe, *send_pipe; + JSClassID std_file_class_id; + JSClassID worker_class_id; } JSThreadState; static uint64_t os_pending_signals; -static int (*os_poll_func)(JSContext *ctx); static void js_std_dbuf_init(JSContext *ctx, DynBuf *s) { @@ -142,14 +181,24 @@ 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); +} + static JSValue js_printf_internal(JSContext *ctx, - int argc, JSValueConst *argv, FILE *fp) + int argc, JSValue *argv, FILE *fp) { char fmtbuf[32]; uint8_t cbuf[UTF8_CHAR_LEN_MAX+1]; JSValue res; DynBuf dbuf; - const char *fmt_str; + const char *fmt_str = NULL; const uint8_t *fmt, *fmt_end; const uint8_t *p; char *q; @@ -159,8 +208,7 @@ 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; + int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = dbuf_printf; js_std_dbuf_init(ctx, &dbuf); @@ -180,7 +228,7 @@ static JSValue js_printf_internal(JSContext *ctx, break; q = fmtbuf; *q++ = *fmt++; /* copy '%' */ - + /* flags */ for(;;) { c = *fmt; @@ -234,36 +282,37 @@ static JSValue js_printf_internal(JSContext *ctx, if (*fmt == 'l') { mod = *fmt++; } - + /* type */ c = *fmt++; if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = c; *q = '\0'; - + switch (c) { case 'c': 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 = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); + int32_arg = utf8_decode((const uint8_t *)string_arg, &p); JS_FreeCString(ctx, string_arg); } else { if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; } - /* handle utf-8 encoding explicitly */ + // XXX: throw an exception? if ((unsigned)int32_arg > 0x10FFFF) int32_arg = 0xFFFD; /* ignore conversion flags, width and precision */ - len = unicode_to_utf8(cbuf, int32_arg); + len = utf8_encode(cbuf, int32_arg); dbuf_put(&dbuf, cbuf, len); break; - + case 'd': case 'i': case 'o': @@ -308,7 +357,7 @@ static JSValue js_printf_internal(JSContext *ctx, dbuf_printf_fun(&dbuf, fmtbuf, string_arg); JS_FreeCString(ctx, string_arg); break; - + case 'e': case 'f': case 'g': @@ -323,11 +372,11 @@ static JSValue js_printf_internal(JSContext *ctx, goto fail; dbuf_printf_fun(&dbuf, fmtbuf, double_arg); break; - + case '%': dbuf_putc(&dbuf, '%'); break; - + default: /* XXX: should support an extension mechanism */ invalid: @@ -354,6 +403,7 @@ static JSValue js_printf_internal(JSContext *ctx, return res; fail: + JS_FreeCString(ctx, fmt_str); dbuf_free(&dbuf); return JS_EXCEPTION; } @@ -364,7 +414,7 @@ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) uint8_t *buf; size_t buf_len; long lret; - + f = fopen(filename, "rb"); if (!f) return NULL; @@ -404,14 +454,14 @@ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) } /* load and evaluate a file */ -static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_loadScript(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { uint8_t *buf; const char *filename; JSValue ret; size_t buf_len; - + filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; @@ -428,15 +478,42 @@ static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, return ret; } -/* load a file as a UTF-8 encoded string */ -static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static int get_bool_option(JSContext *ctx, BOOL *pbool, + JSValue 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 */ +static JSValue js_std_loadFile(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { uint8_t *buf; const char *filename; - JSValue ret; + JSValue ret, options_obj; 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) return JS_EXCEPTION; @@ -444,8 +521,13 @@ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, filename); if (!buf) return JS_NULL; - ret = JS_NewStringLen(ctx, (char *)buf, buf_len); - js_free(ctx, buf); + 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; } @@ -454,6 +536,52 @@ 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); + JS_BOOL is_absolute = len > 2 && ((module_name[0] >= 'A' && module_name[0] <= 'Z') || + (module_name[0] >= 'a' && module_name[0] <= 'z')) && module_name[1] == ':'; + JS_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) { @@ -468,7 +596,7 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, void *hd; JSInitModuleFunc *init; char *filename; - + if (!strchr(module_name, '/')) { /* must add a '/' so that the DLL is not searched in the system library paths */ @@ -480,18 +608,18 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, } else { filename = (char *)module_name; } - + /* C module */ hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL); if (filename != module_name) js_free(ctx, filename); if (!hd) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library", - module_name); + JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library: %s", + module_name, dlerror()); goto fail; } - init = dlsym(hd, "js_init_module"); + *(void **) (&init) = dlsym(hd, "js_init_module"); if (!init) { JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found", module_name); @@ -511,7 +639,7 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, } #endif /* !_WIN32 */ -int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, +int js_module_set_import_meta(JSContext *ctx, JSValue func_val, JS_BOOL use_realpath, JS_BOOL is_main) { JSModuleDef *m; @@ -519,7 +647,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, JSValue meta_obj; JSAtom module_name_atom; const char *module_name; - + assert(JS_VALUE_GET_TAG(func_val) == JS_TAG_MODULE); m = JS_VALUE_GET_PTR(func_val); @@ -530,7 +658,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, return -1; if (!strchr(module_name, ':')) { strcpy(buf, "file://"); -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__wasi__) /* realpath() cannot be used with modules compiled with qjsc because the corresponding module source code is not necessarily present */ @@ -544,13 +672,13 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, } else #endif { - pstrcat(buf, sizeof(buf), module_name); + js__pstrcat(buf, sizeof(buf), module_name); } } else { - pstrcpy(buf, sizeof(buf), module_name); + js__pstrcpy(buf, sizeof(buf), module_name); } JS_FreeCString(ctx, module_name); - + meta_obj = JS_GetImportMeta(ctx, m); if (JS_IsException(meta_obj)) return -1; @@ -569,20 +697,20 @@ JSModuleDef *js_module_loader(JSContext *ctx, { JSModuleDef *m; - if (has_suffix(module_name, ".so")) { + if (js__has_suffix(module_name, QJS_NATIVE_MODULE_SUFFIX)) { 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) { 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); @@ -598,8 +726,8 @@ JSModuleDef *js_module_loader(JSContext *ctx, return m; } -static JSValue js_std_exit(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_exit(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int status; if (JS_ToInt32(ctx, &status, argv[0])) @@ -608,8 +736,8 @@ static JSValue js_std_exit(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_std_getenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_getenv(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *name, *str; name = JS_ToCString(ctx, argv[0]); @@ -645,8 +773,8 @@ static void unsetenv(const char *name) } #endif /* _WIN32 */ -static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_setenv(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *name, *value; name = JS_ToCString(ctx, argv[0]); @@ -663,8 +791,8 @@ static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_unsetenv(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *name; name = JS_ToCString(ctx, argv[0]); @@ -677,8 +805,8 @@ static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val, /* return an object containing the list of the available environment variables. */ -static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_getenviron(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { char **envp; const char *name, *p, *value; @@ -714,8 +842,8 @@ static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_gc(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JS_RunGC(JS_GetRuntime(ctx)); return JS_UNDEFINED; @@ -726,57 +854,80 @@ 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) +static JSValue js_evalScript(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - const char *str; + JSThreadState *ts = js_get_thread_state(rt); + const char *str = NULL; size_t len; - JSValue ret; - JSValueConst options_obj; + JSValue ret, obj; + JSValue options_obj; BOOL backtrace_barrier = FALSE; + BOOL eval_function = FALSE; + BOOL eval_module = FALSE; + BOOL compile_only = FALSE; + BOOL compile_module = FALSE; BOOL is_async = FALSE; int flags; - + if (argc >= 2) { options_obj = argv[1]; 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; } - str = JS_ToCStringLen(ctx, &len, argv[0]); - if (!str) - return JS_EXCEPTION; + if (eval_module) { + obj = argv[0]; + if (JS_VALUE_GET_TAG(obj) != JS_TAG_MODULE) + return JS_ThrowTypeError(ctx, "not a module"); + + if (JS_ResolveModule(ctx, obj) < 0) + return JS_EXCEPTION; + + js_module_set_import_meta(ctx, obj, FALSE, FALSE); + + return JS_EvalFunction(ctx, obj); + } + + if (!eval_function) { + 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 = JS_EVAL_TYPE_GLOBAL; + flags = compile_module ? JS_EVAL_TYPE_MODULE : 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; - ret = JS_Eval(ctx, str, len, "", flags); + 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); + } JS_FreeCString(ctx, str); if (!ts->recv_pipe && --ts->eval_script_recurse == 0) { /* remove the interrupt handler */ @@ -790,22 +941,27 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, return ret; } -static JSClassID js_std_file_class_id; - typedef struct { FILE *f; - BOOL close_in_finalizer; BOOL is_popen; } JSSTDFile; +static BOOL is_stdio(FILE *f) +{ + return f == stdin || f == stdout || f == stderr; +} + static void js_std_file_finalizer(JSRuntime *rt, JSValue val) { - JSSTDFile *s = JS_GetOpaque(val, js_std_file_class_id); + JSThreadState *ts = js_get_thread_state(rt); + JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id); if (s) { - if (s->f && s->close_in_finalizer) { + if (s->f && !is_stdio(s->f)) { +#if !defined(__wasi__) if (s->is_popen) pclose(s->f); else +#endif fclose(s->f); } js_free_rt(rt, s); @@ -819,8 +975,8 @@ static ssize_t js_get_errno(ssize_t ret) return ret; } -static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_strerror(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int err; if (JS_ToInt32(ctx, &err, argv[0])) @@ -828,28 +984,13 @@ static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, return JS_NewString(ctx, strerror(err)); } -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) +static JSValue js_new_std_file(JSContext *ctx, FILE *f, BOOL is_popen) { + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s; JSValue obj; - obj = JS_NewObjectClass(ctx, js_std_file_class_id); + obj = JS_NewObjectClass(ctx, ts->std_file_class_id); if (JS_IsException(obj)) return obj; s = js_mallocz(ctx, sizeof(*s)); @@ -857,7 +998,6 @@ static JSValue js_new_std_file(JSContext *ctx, FILE *f, 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); @@ -871,20 +1011,20 @@ static void js_set_error_object(JSContext *ctx, JSValue obj, int err) } } -static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_open(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *filename, *mode = NULL; FILE *f; int err; - + filename = JS_ToCString(ctx, argv[0]); if (!filename) goto fail; mode = JS_ToCString(ctx, argv[1]); if (!mode) goto fail; - if (mode[strspn(mode, "rwa+b")] != '\0') { + if (mode[strspn(mode, "rwa+bx")] != '\0') { JS_ThrowTypeError(ctx, "invalid file mode"); goto fail; } @@ -900,20 +1040,21 @@ 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, TRUE, FALSE); + return js_new_std_file(ctx, f, FALSE); fail: JS_FreeCString(ctx, filename); JS_FreeCString(ctx, mode); return JS_EXCEPTION; } -static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#if !defined(__wasi__) +static JSValue js_std_popen(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *filename, *mode = NULL; FILE *f; int err; - + filename = JS_ToCString(ctx, argv[0]); if (!filename) goto fail; @@ -936,15 +1077,16 @@ 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, TRUE); + return js_new_std_file(ctx, f, 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) +static JSValue js_std_fdopen(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *mode; FILE *f; @@ -970,14 +1112,15 @@ 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, TRUE, FALSE); + return js_new_std_file(ctx, f, FALSE); fail: JS_FreeCString(ctx, mode); return JS_EXCEPTION; } -static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#if !defined(__wasi__) +static JSValue js_std_tmpfile(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f; f = tmpfile(); @@ -985,24 +1128,27 @@ 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, TRUE, FALSE); + return js_new_std_file(ctx, f, FALSE); } +#endif -static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_sprintf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_printf_internal(ctx, argc, argv, NULL); } -static JSValue js_std_printf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_printf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_printf_internal(ctx, argc, argv, stdout); } -static FILE *js_std_file_get(JSContext *ctx, JSValueConst obj) +static FILE *js_std_file_get(JSContext *ctx, JSValue obj) { - JSSTDFile *s = JS_GetOpaque2(ctx, obj, js_std_file_class_id); + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSSTDFile *s = JS_GetOpaque2(ctx, obj, ts->std_file_class_id); if (!s) return NULL; if (!s->f) { @@ -1012,8 +1158,8 @@ static FILE *js_std_file_get(JSContext *ctx, JSValueConst obj) return s->f; } -static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_std_file_puts(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { FILE *f; int i; @@ -1027,7 +1173,7 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val, if (!f) return JS_EXCEPTION; } - + for(i = 0; i < argc; i++) { str = JS_ToCStringLen(ctx, &len, argv[i]); if (!str) @@ -1038,25 +1184,31 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_close(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSSTDFile *s = JS_GetOpaque2(ctx, this_val, js_std_file_class_id); + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSSTDFile *s = JS_GetOpaque2(ctx, this_val, ts->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); } -static JSValue js_std_file_printf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_printf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1064,8 +1216,8 @@ static JSValue js_std_file_printf(JSContext *ctx, JSValueConst this_val, return js_printf_internal(ctx, argc, argv, f); } -static JSValue js_std_file_flush(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_flush(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1074,8 +1226,8 @@ static JSValue js_std_file_flush(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_std_file_tell(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_bigint) +static JSValue js_std_file_tell(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int is_bigint) { FILE *f = js_std_file_get(ctx, this_val); int64_t pos; @@ -1092,8 +1244,8 @@ static JSValue js_std_file_tell(JSContext *ctx, JSValueConst this_val, return JS_NewInt64(ctx, pos); } -static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_seek(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); int64_t pos; @@ -1114,8 +1266,8 @@ static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, ret); } -static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_eof(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1123,8 +1275,8 @@ static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val, return JS_NewBool(ctx, feof(f)); } -static JSValue js_std_file_error(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_error(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1132,8 +1284,8 @@ static JSValue js_std_file_error(JSContext *ctx, JSValueConst this_val, return JS_NewBool(ctx, ferror(f)); } -static JSValue js_std_file_clearerr(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_clearerr(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1142,8 +1294,8 @@ static JSValue js_std_file_clearerr(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_std_file_fileno(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_fileno(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1151,14 +1303,14 @@ static JSValue js_std_file_fileno(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, fileno(f)); } -static JSValue js_std_file_read_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_std_file_read_write(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { FILE *f = js_std_file_get(ctx, this_val); uint64_t pos, len; size_t size, ret; uint8_t *buf; - + if (!f) return JS_EXCEPTION; if (JS_ToIndex(ctx, &pos, argv[1])) @@ -1178,14 +1330,14 @@ static JSValue js_std_file_read_write(JSContext *ctx, JSValueConst this_val, } /* XXX: could use less memory and go faster */ -static JSValue js_std_file_getline(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_getline(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); int c; DynBuf dbuf; JSValue obj; - + if (!f) return JS_EXCEPTION; @@ -1214,8 +1366,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_readAsString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_readAsString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); int c; @@ -1223,8 +1375,8 @@ static JSValue js_std_file_readAsString(JSContext *ctx, JSValueConst this_val, JSValue obj; uint64_t max_size64; size_t max_size; - JSValueConst max_size_val; - + JSValue max_size_val; + if (!f) return JS_EXCEPTION; @@ -1256,8 +1408,8 @@ static JSValue js_std_file_readAsString(JSContext *ctx, JSValueConst this_val, return obj; } -static JSValue js_std_file_getByte(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_getByte(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); if (!f) @@ -1265,8 +1417,8 @@ static JSValue js_std_file_getByte(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, fgetc(f)); } -static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_file_putByte(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { FILE *f = js_std_file_get(ctx, this_val); int c; @@ -1279,8 +1431,9 @@ 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_PROGRAM "curl -s -i --" #define URL_GET_BUF_SIZE 4096 static int http_get_header_line(FILE *f, char *buf, size_t buf_size, @@ -1288,7 +1441,7 @@ static int http_get_header_line(FILE *f, char *buf, size_t buf_size, { int c; char *p; - + p = buf; for(;;) { c = fgetc(f); @@ -1317,28 +1470,28 @@ static int http_get_status(const char *buf) return atoi(p); } -static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_std_urlGet(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *url; DynBuf cmd_buf; DynBuf data_buf_s, *data_buf = &data_buf_s; DynBuf header_buf_s, *header_buf = &header_buf_s; - char *buf; + char *buf; size_t i, len; - int c, status; + int status; JSValue response = JS_UNDEFINED, ret_obj; - JSValueConst options_obj; + JSValue options_obj; FILE *f; BOOL binary_flag, full_flag; - + url = JS_ToCString(ctx, argv[0]); if (!url) return JS_EXCEPTION; - + binary_flag = FALSE; full_flag = FALSE; - + if (argc >= 2) { options_obj = argv[1]; @@ -1351,18 +1504,27 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } } - + js_std_dbuf_init(ctx, &cmd_buf); - dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM); - len = strlen(url); - for(i = 0; i < len; i++) { - c = url[i]; - if (c == '\'' || c == '\\') + dbuf_printf(&cmd_buf, "%s '", URL_GET_PROGRAM); + for(i = 0; url[i] != '\0'; i++) { + unsigned char c = url[i]; + switch (c) { + case '\'': + /* shell single quoted string does not support \' */ + dbuf_putstr(&cmd_buf, "'\\''"); + break; + case '[': case ']': case '{': case '}': case '\\': + /* prevent interpretation by curl as range or set specification */ dbuf_putc(&cmd_buf, '\\'); - dbuf_putc(&cmd_buf, c); + /* FALLTHROUGH */ + default: + dbuf_putc(&cmd_buf, c); + break; + } } JS_FreeCString(ctx, url); - dbuf_putstr(&cmd_buf, "''"); + dbuf_putstr(&cmd_buf, "'"); dbuf_putc(&cmd_buf, '\0'); if (dbuf_error(&cmd_buf)) { dbuf_free(&cmd_buf); @@ -1377,7 +1539,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, js_std_dbuf_init(ctx, data_buf); js_std_dbuf_init(ctx, header_buf); - + buf = js_malloc(ctx, URL_GET_BUF_SIZE); if (!buf) goto fail; @@ -1391,7 +1553,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, if (!full_flag && !(status >= 200 && status <= 299)) { goto bad_header; } - + /* wait until there is an empty line */ for(;;) { if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, header_buf) < 0) { @@ -1463,11 +1625,12 @@ 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", .finalizer = js_std_file_finalizer, -}; +}; static const JSCFunctionListEntry js_std_error_props[] = { /* various errno values */ @@ -1495,16 +1658,19 @@ 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("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("fdopen", 2, js_std_fdopen ), JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), +#endif + JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ), 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 ), @@ -1513,7 +1679,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { 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), }; - + static const JSCFunctionListEntry js_std_file_proto_funcs[] = { JS_CFUNC_DEF("close", 0, js_std_file_close ), JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 1 ), @@ -1538,22 +1704,24 @@ 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(&js_std_file_class_id); + JS_NewClassID(rt, &ts->std_file_class_id); /* the class is created once per runtime */ - JS_NewClass(JS_GetRuntime(ctx), js_std_file_class_id, &js_std_file_class); + JS_NewClass(rt, ts->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, js_std_file_class_id, proto); + JS_SetClassProto(ctx, ts->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, 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)); + 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)); return 0; } @@ -1573,8 +1741,8 @@ JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name) /**********************************************************/ /* 'os' object */ -static JSValue js_os_open(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_open(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *filename; int flags, mode, ret; @@ -1603,8 +1771,8 @@ static JSValue js_os_open(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, ret); } -static JSValue js_os_close(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_close(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd, ret; if (JS_ToInt32(ctx, &fd, argv[0])) @@ -1613,13 +1781,13 @@ static JSValue js_os_close(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, ret); } -static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_seek(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd, whence; int64_t pos, ret; BOOL is_bigint; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; is_bigint = JS_IsBigInt(ctx, argv[1]); @@ -1636,15 +1804,15 @@ static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val, return JS_NewInt64(ctx, ret); } -static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_os_read_write(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { int fd; uint64_t pos, len; size_t size; ssize_t ret; uint8_t *buf; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; if (JS_ToIndex(ctx, &pos, argv[2])) @@ -1663,8 +1831,8 @@ static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val, return JS_NewInt64(ctx, ret); } -static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_isatty(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd; if (JS_ToInt32(ctx, &fd, argv[0])) @@ -1673,8 +1841,8 @@ static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, } #if defined(_WIN32) -static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd; HANDLE handle; @@ -1684,7 +1852,7 @@ static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; handle = (HANDLE)_get_osfhandle(fd); - + if (!GetConsoleScreenBufferInfo(handle, &info)) return JS_NULL; obj = JS_NewArray(ctx); @@ -1699,8 +1867,8 @@ static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, #define __ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #define __ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 -static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_ttySetRaw(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd; HANDLE handle; @@ -1716,14 +1884,14 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, } return JS_UNDEFINED; } -#else -static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#elif !defined(__wasi__) +static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd; struct winsize ws; JSValue obj; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; if (ioctl(fd, TIOCGWINSZ, &ws) == 0 && @@ -1747,15 +1915,15 @@ static void term_exit(void) } /* XXX: should add a way to go back to normal mode */ -static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_ttySetRaw(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { struct termios tty; int fd; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; - + memset(&tty, 0, sizeof(tty)); tcgetattr(fd, &tty); oldtty = tty; @@ -1775,14 +1943,14 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -#endif /* !_WIN32 */ +#endif /* !_WIN32 && !__wasi__ */ -static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_remove(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *filename; int ret; - + filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; @@ -1803,12 +1971,12 @@ static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, ret); } -static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_rename(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *oldpath, *newpath; int ret; - + oldpath = JS_ToCString(ctx, argv[0]); if (!oldpath) return JS_EXCEPTION; @@ -1825,7 +1993,7 @@ static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val, static BOOL is_main_thread(JSRuntime *rt) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); return !ts->recv_pipe; } @@ -1852,15 +2020,15 @@ static void free_rw_handler(JSRuntime *rt, JSOSRWHandler *rh) js_free_rt(rt, rh); } -static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_os_setReadHandler(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSOSRWHandler *rh; int fd; - JSValueConst func; - + JSValue func; + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; func = argv[1]; @@ -1922,19 +2090,19 @@ static void os_signal_handler(int sig_num) typedef void (*sighandler_t)(int sig_num); #endif -static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_signal(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSOSSignalHandler *sh; uint32_t sig_num; - JSValueConst func; + JSValue func; sighandler_t handler; if (!is_main_thread(rt)) return JS_ThrowTypeError(ctx, "signal handler can only be set in the main thread"); - + if (JS_ToUint32(ctx, &sig_num, argv[0])) return JS_EXCEPTION; if (sig_num >= 64) @@ -1969,131 +2137,107 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -#if defined(__linux__) || defined(__APPLE__) -static int64_t get_time_ms(void) +#if !defined(_WIN32) && !defined(__wasi__) +static JSValue js_os_cputime(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000); -} + struct rusage ru; + int64_t cputime; -static int64_t get_time_ns(void) -{ - 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); -} + cputime = 0; + if (!getrusage(RUSAGE_SELF, &ru)) + cputime = (int64_t)ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; -static int64_t get_time_ns(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000000000 + (tv.tv_usec * 1000); + return JS_NewInt64(ctx, cputime); } #endif static JSValue js_os_now(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { - return JS_NewFloat64(ctx, (double)get_time_ns() / 1e6); + return JS_NewInt64(ctx, js__hrtime_ns() / 1000); } -static void unlink_timer(JSRuntime *rt, JSOSTimer *th) +static uint64_t js__hrtime_ms(void) { - if (th->link.prev) { - list_del(&th->link); - th->link.prev = th->link.next = NULL; - } + return js__hrtime_ns() / (1000 * 1000); } static void free_timer(JSRuntime *rt, JSOSTimer *th) { + list_del(&th->link); JS_FreeValueRT(rt, th->func); js_free_rt(rt, th); } -static JSClassID js_os_timer_class_id; - -static void js_os_timer_finalizer(JSRuntime *rt, JSValue val) -{ - JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id); - if (th) { - th->has_object = FALSE; - if (!th->link.prev) - free_timer(rt, th); - } -} - -static void js_os_timer_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id); - if (th) { - JS_MarkValue(rt, th->func, mark_func); - } -} - -static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +// 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, JSValue this_val, + int argc, JSValue *argv, int magic) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int64_t delay; - JSValueConst func; + JSValue func; JSOSTimer *th; - JSValue obj; func = argv[0]; if (!JS_IsFunction(ctx, func)) return JS_ThrowTypeError(ctx, "not a function"); if (JS_ToInt64(ctx, &delay, argv[1])) return JS_EXCEPTION; - obj = JS_NewObjectClass(ctx, js_os_timer_class_id); - if (JS_IsException(obj)) - return obj; + if (delay < 1) + delay = 1; th = js_mallocz(ctx, sizeof(*th)); - if (!th) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - th->has_object = TRUE; - th->timeout = get_time_ms() + delay; - th->func = JS_DupValue(ctx, func); - list_add_tail(&th->link, &ts->os_timers); - JS_SetOpaque(obj, th); - return obj; -} - -static JSValue js_os_clearTimeout(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSOSTimer *th = JS_GetOpaque2(ctx, argv[0], js_os_timer_class_id); if (!th) return JS_EXCEPTION; - unlink_timer(JS_GetRuntime(ctx), th); - return JS_UNDEFINED; + th->timer_id = ts->next_timer_id++; + if (ts->next_timer_id > MAX_SAFE_INTEGER) + ts->next_timer_id = 1; + th->repeats = (magic > 0); + th->timeout = js__hrtime_ms() + delay; + th->delay = delay; + th->func = JS_DupValue(ctx, func); + list_add_tail(&th->link, &ts->os_timers); + return JS_NewInt64(ctx, th->timer_id); } -static JSClassDef js_os_timer_class = { - "OSTimer", - .finalizer = js_os_timer_finalizer, - .gc_mark = js_os_timer_mark, -}; +static JSOSTimer *find_timer_by_id(JSThreadState *ts, int timer_id) +{ + struct list_head *el; + if (timer_id <= 0) + return NULL; + list_for_each(el, &ts->os_timers) { + JSOSTimer *th = list_entry(el, JSOSTimer, link); + if (th->timer_id == timer_id) + return th; + } + return NULL; +} + +static JSValue js_os_clearTimeout(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSOSTimer *th; + int64_t timer_id; + + if (JS_ToInt64(ctx, &timer_id, argv[0])) + return JS_EXCEPTION; + th = find_timer_by_id(ts, timer_id); + if (!th) + return JS_UNDEFINED; + free_timer(rt, th); + return JS_UNDEFINED; +} /* return a promise */ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int64_t delay; JSOSTimer *th; JSValue promise, resolving_funcs[2]; @@ -2111,8 +2255,8 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, resolving_funcs[1]); return JS_EXCEPTION; } - th->has_object = FALSE; - th->timeout = get_time_ms() + delay; + th->timer_id = -1; + th->timeout = js__hrtime_ms() + delay; th->func = JS_DupValue(ctx, resolving_funcs[0]); list_add_tail(&th->link, &ts->os_timers); JS_FreeValue(ctx, resolving_funcs[0]); @@ -2120,17 +2264,61 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, return promise; } -static void call_handler(JSContext *ctx, JSValueConst func) +static int call_handler(JSContext *ctx, JSValue 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); - if (JS_IsException(ret)) - js_std_dump_error(ctx); + r = 0; + if (JS_IsException(ret)) { + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + ts->exc = JS_GetException(ctx); + 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; } #if defined(_WIN32) @@ -2138,42 +2326,20 @@ static void call_handler(JSContext *ctx, JSValueConst func) static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int min_delay, console_fd; - int64_t cur_time, delay; JSOSRWHandler *rh; struct list_head *el; - + /* XXX: handle signals if useful */ - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers)) - return -1; /* no more events */ - - /* XXX: only timers and basic console input are supported */ - 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; - unlink_timer(rt, th); - if (!th->has_object) - 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; - } + 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)) + return -1; /* no more events */ console_fd = -1; list_for_each(el, &ts->os_rw_handlers) { @@ -2197,9 +2363,8 @@ static int js_os_poll(JSContext *ctx) list_for_each(el, &ts->os_rw_handlers) { rh = list_entry(el, JSOSRWHandler, link); if (rh->fd == console_fd && !JS_IsNull(rh->rw_func[0])) { - call_handler(ctx, rh->rw_func[0]); + return call_handler(ctx, rh->rw_func[0]); /* must stop because the list may have been modified */ - break; } } } @@ -2223,7 +2388,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, struct list_head *el; JSWorkerMessage *msg; JSValue obj, data_obj, func, retval; - + pthread_mutex_lock(&ps->mutex); if (!list_empty(&ps->msg_queue)) { el = ps->msg_queue.next; @@ -2250,7 +2415,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, JS_READ_OBJ_SAB | JS_READ_OBJ_REFERENCE); js_free_message(msg); - + if (JS_IsException(data_obj)) goto fail; obj = JS_NewObject(ctx); @@ -2263,7 +2428,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, /* 'func' might be destroyed when calling itself (if it frees the handler), so must take extra care */ func = JS_DupValue(ctx, port->on_message_func); - retval = JS_Call(ctx, func, JS_UNDEFINED, 1, (JSValueConst *)&obj); + retval = JS_Call(ctx, func, JS_UNDEFINED, 1, &obj); JS_FreeValue(ctx, obj); JS_FreeValue(ctx, func); if (JS_IsException(retval)) { @@ -2290,9 +2455,8 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int ret, fd_max, min_delay; - int64_t cur_time, delay; fd_set rfds, wfds; JSOSRWHandler *rh; struct list_head *el; @@ -2303,50 +2467,32 @@ static int js_os_poll(JSContext *ctx) unlikely(os_pending_signals != 0)) { JSOSSignalHandler *sh; uint64_t mask; - + list_for_each(el, &ts->os_signal_handlers) { sh = list_entry(el, JSOSSignalHandler, link); mask = (uint64_t)1 << sh->sig_num; if (os_pending_signals & mask) { os_pending_signals &= ~mask; - call_handler(ctx, sh->func); - return 0; + return call_handler(ctx, sh->func); } } } - 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; - unlink_timer(rt, th); - if (!th->has_object) - free_timer(rt, th); - call_handler(ctx, func); - JS_FreeValue(ctx, func); - return 0; - } else if (delay < min_delay) { - min_delay = delay; - } - } + 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 */ + + tvp = NULL; + if (min_delay >= 0) { 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; @@ -2374,15 +2520,13 @@ static int js_os_poll(JSContext *ctx) 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]); + return call_handler(ctx, rh->rw_func[0]); /* must stop because the list may have been modified */ - goto done; } if (!JS_IsNull(rh->rw_func[1]) && FD_ISSET(rh->fd, &wfds)) { - call_handler(ctx, rh->rw_func[1]); + return call_handler(ctx, rh->rw_func[1]); /* must stop because the list may have been modified */ - goto done; } } @@ -2427,12 +2571,12 @@ static JSValue make_string_error(JSContext *ctx, } /* return [cwd, errorcode] */ -static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_getcwd(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { char buf[PATH_MAX]; int err; - + if (!getcwd(buf, sizeof(buf))) { buf[0] = '\0'; err = errno; @@ -2442,8 +2586,8 @@ static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, return make_string_error(ctx, buf, err); } -static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_chdir(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *target; int err; @@ -2456,12 +2600,12 @@ static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, err); } -static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_mkdir(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int mode, ret; const char *path; - + if (argc >= 2) { if (JS_ToInt32(ctx, &mode, argv[1])) return JS_EXCEPTION; @@ -2482,8 +2626,8 @@ static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, } /* return [array, errorcode] */ -static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_readdir(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *path; DIR *f; @@ -2491,7 +2635,7 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, JSValue obj; int err; uint32_t len; - + path = JS_ToCString(ctx, argv[0]); if (!path) return JS_EXCEPTION; @@ -2533,8 +2677,8 @@ static int64_t timespec_to_ms(const struct timespec *tv) #endif /* return [obj, errcode] */ -static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_lstat) +static JSValue js_os_stat(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int is_lstat) { const char *path; int err, res; @@ -2552,12 +2696,11 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, else res = stat(path, &st); #endif + err = (res < 0) ? errno : 0; JS_FreeCString(ctx, path); if (res < 0) { - err = errno; obj = JS_NULL; } else { - err = 0; obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; @@ -2633,13 +2776,13 @@ static void ms_to_timeval(struct timeval *tv, uint64_t v) } #endif -static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_utimes(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *path; int64_t atime, mtime; int ret; - + if (JS_ToInt64(ctx, &atime, argv[1])) return JS_EXCEPTION; if (JS_ToInt64(ctx, &mtime, argv[2])) @@ -2667,12 +2810,12 @@ 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) +static JSValue js_os_sleep(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int64_t delay; int ret; - + if (JS_ToInt64(ctx, &delay, argv[0])) return JS_EXCEPTION; if (delay < 0) @@ -2708,9 +2851,10 @@ 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) +static JSValue js_os_realpath(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *path; char buf[PATH_MAX], *res; @@ -2729,14 +2873,15 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, } return make_string_error(ctx, buf, err); } +#endif -#if !defined(_WIN32) -static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +#if !defined(_WIN32) && !defined(__wasi__) +static JSValue js_os_symlink(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *target, *linkpath; int err; - + target = JS_ToCString(ctx, argv[0]); if (!target) return JS_EXCEPTION; @@ -2752,14 +2897,14 @@ static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, } /* return [path, errorcode] */ -static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_readlink(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *path; char buf[PATH_MAX]; int err; ssize_t res; - + path = JS_ToCString(ctx, argv[0]); if (!path) return JS_EXCEPTION; @@ -2775,7 +2920,7 @@ static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, return make_string_error(ctx, buf, err); } -static char **build_envp(JSContext *ctx, JSValueConst obj) +static char **build_envp(JSContext *ctx, JSValue obj) { uint32_t len, i; JSPropertyEnum *tab; @@ -2783,7 +2928,7 @@ static char **build_envp(JSContext *ctx, JSValueConst obj) const char *key, *str; JSValue val; size_t key_len, str_len; - + if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj, JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) return NULL; @@ -2841,7 +2986,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) char buf[PATH_MAX]; size_t filename_len, path_len; BOOL eacces_error; - + filename_len = strlen(filename); if (filename_len == 0) { errno = ENOENT; @@ -2849,7 +2994,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) } if (strchr(filename, '/')) return execve(filename, argv, envp); - + path = getenv("PATH"); if (!path) path = (char *)"/bin:/usr/bin"; @@ -2871,7 +3016,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) buf[path_len] = '/'; memcpy(buf + path_len + 1, filename, filename_len); buf[path_len + 1 + filename_len] = '\0'; - + execve(buf, argv, envp); switch(errno) { @@ -2890,11 +3035,24 @@ static int my_execvpe(const char *filename, char **argv, char **envp) return -1; } -/* exec(args[, options]) -> exitcode */ -static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +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) { - JSValueConst options, args = argv[0]; + js_os_exec_closefrom = dlsym(RTLD_DEFAULT, "closefrom"); +} + +#endif + +/* exec(args[, options]) -> exitcode */ +static JSValue js_os_exec(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue options, args = argv[0]; JSValue val, ret_val; const char **exec_argv, *file = NULL, *str, *cwd = NULL; char **envp = environ; @@ -2904,7 +3062,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, static const char *std_name[3] = { "stdin", "stdout", "stderr" }; int std_fds[3]; uint32_t uid = -1, gid = -1; - + val = JS_GetPropertyStr(ctx, args, "length"); if (JS_IsException(val)) return JS_EXCEPTION; @@ -2933,7 +3091,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, for(i = 0; i < 3; i++) std_fds[i] = i; - + /* get the options, if any */ if (argc >= 2) { options = argv[1]; @@ -2942,7 +3100,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, goto exception; if (get_bool_option(ctx, &use_path, options, "usePath")) goto exception; - + val = JS_GetPropertyStr(ctx, options, "file"); if (JS_IsException(val)) goto exception; @@ -2987,7 +3145,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, if (!envp) goto exception; } - + val = JS_GetPropertyStr(ctx, options, "uid"); if (JS_IsException(val)) goto exception; @@ -3009,6 +3167,12 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, } } +#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"); @@ -3016,8 +3180,6 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, } if (pid == 0) { /* child */ - int fd_max = sysconf(_SC_OPEN_MAX); - /* remap the stdin/stdout/stderr handles if necessary */ for(i = 0; i < 3; i++) { if (std_fds[i] != i) { @@ -3026,8 +3188,14 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, } } - for(i = 3; i < fd_max; i++) - close(i); + if (js_os_exec_closefrom) { + js_os_exec_closefrom(3); + } else { + int fd_max = sysconf(_SC_OPEN_MAX); + for(i = 3; i < fd_max; i++) + close(i); + } + if (cwd) { if (chdir(cwd) < 0) _exit(127); @@ -3089,19 +3257,19 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, } /* getpid() -> pid */ -static JSValue js_os_getpid(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_getpid(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_NewInt32(ctx, getpid()); } /* waitpid(pid, block) -> [pid, status] */ -static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_waitpid(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int pid, status, options, ret; JSValue obj; - + if (JS_ToInt32(ctx, &pid, argv[0])) return JS_EXCEPTION; if (JS_ToInt32(ctx, &options, argv[1])) @@ -3121,15 +3289,15 @@ static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val, JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, status), JS_PROP_C_W_E); return obj; -} +} /* pipe() -> [read_fd, write_fd] or null if error */ -static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_pipe(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int pipe_fds[2], ret; JSValue obj; - + ret = pipe(pipe_fds); if (ret < 0) return JS_NULL; @@ -3144,11 +3312,11 @@ static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val, } /* kill(pid, sig) */ -static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_kill(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int pid, sig, ret; - + if (JS_ToInt32(ctx, &pid, argv[0])) return JS_EXCEPTION; if (JS_ToInt32(ctx, &sig, argv[1])) @@ -3158,11 +3326,11 @@ static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val, } /* dup(fd) */ -static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_dup(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd, ret; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; ret = js_get_errno(dup(fd)); @@ -3170,11 +3338,11 @@ static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val, } /* dup2(fd) */ -static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_os_dup2(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int fd, fd2, ret; - + if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; if (JS_ToInt32(ctx, &fd2, argv[1])) @@ -3203,15 +3371,14 @@ typedef struct { typedef struct { int ref_count; - uint64_t buf[0]; + uint64_t buf[]; } 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 */ @@ -3248,7 +3415,7 @@ static JSWorkerMessagePipe *js_new_message_pipe(void) { JSWorkerMessagePipe *ps; int pipe_fds[2]; - + if (pipe(pipe_fds) < 0) return NULL; @@ -3289,10 +3456,10 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps) struct list_head *el, *el1; JSWorkerMessage *msg; int ref_count; - + if (!ps) return; - + ref_count = atomic_add_int(&ps->ref_count, -1); assert(ref_count >= 0); if (ref_count == 0) { @@ -3319,7 +3486,8 @@ static void js_free_port(JSRuntime *rt, JSWorkerMessageHandler *port) static void js_worker_finalizer(JSRuntime *rt, JSValue val) { - JSWorkerData *worker = JS_GetOpaque(val, js_worker_class_id); + JSThreadState *ts = js_get_thread_state(rt); + JSWorkerData *worker = JS_GetOpaque(val, ts->worker_class_id); if (worker) { js_free_message_pipe(worker->recv_pipe); js_free_message_pipe(worker->send_pipe); @@ -3331,7 +3499,7 @@ static void js_worker_finalizer(JSRuntime *rt, JSValue val) static JSClassDef js_worker_class = { "Worker", .finalizer = js_worker_finalizer, -}; +}; static void *worker_func(void *opaque) { @@ -3339,22 +3507,22 @@ static void *worker_func(void *opaque) JSRuntime *rt; JSThreadState *ts; JSContext *ctx; - JSValue promise; - + JSValue val; + rt = JS_NewRuntime(); if (rt == NULL) { fprintf(stderr, "JS_NewRuntime failure"); exit(1); - } + } js_std_init_handlers(rt); JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); /* set the pipe to communicate with the parent */ - ts = JS_GetRuntimeOpaque(rt); + ts = js_get_thread_state(rt); ts->recv_pipe = args->recv_pipe; ts->send_pipe = args->send_pipe; - + /* function pointer to avoid linking the whole JS_NewContext() if not needed */ ctx = js_worker_new_context_func(rt); @@ -3366,16 +3534,16 @@ static void *worker_func(void *opaque) js_std_add_helpers(ctx, -1, NULL); - promise = JS_LoadModule(ctx, args->basename, args->filename); - if (JS_IsException(promise)) - js_std_dump_error(ctx); - /* XXX: check */ - JS_FreeValue(ctx, promise); + val = JS_LoadModule(ctx, args->basename, args->filename); free(args->filename); free(args->basename); free(args); + val = js_std_await(ctx, val); + if (JS_IsException(val)) + js_std_dump_error(ctx); + JS_FreeValue(ctx, val); - js_std_loop(ctx); + JS_FreeValue(ctx, js_std_loop(ctx)); JS_FreeContext(ctx); js_std_free_handlers(rt); @@ -3383,22 +3551,24 @@ static void *worker_func(void *opaque) return NULL; } -static JSValue js_worker_ctor_internal(JSContext *ctx, JSValueConst new_target, +static JSValue js_worker_ctor_internal(JSContext *ctx, JSValue 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, js_worker_class_id); + proto = JS_GetClassProto(ctx, ts->worker_class_id); } else { proto = JS_GetPropertyStr(ctx, new_target, "prototype"); if (JS_IsException(proto)) goto fail; } - obj = JS_NewObjectProtoClass(ctx, proto, js_worker_class_id); + obj = JS_NewObjectProtoClass(ctx, proto, ts->worker_class_id); JS_FreeValue(ctx, proto); if (JS_IsException(obj)) goto fail; @@ -3415,8 +3585,8 @@ static JSValue js_worker_ctor_internal(JSContext *ctx, JSValueConst new_target, return JS_EXCEPTION; } -static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_worker_ctor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); WorkerFuncArgs *args = NULL; @@ -3426,7 +3596,7 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, int ret; const char *filename = NULL, *basename; JSAtom basename_atom; - + /* XXX: in order to avoid problems with resource liberation, we don't support creating workers inside workers */ if (!is_main_thread(rt)) @@ -3442,7 +3612,7 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, JS_FreeAtom(ctx, basename_atom); if (!basename) goto fail; - + /* module name */ filename = JS_ToCString(ctx, argv[0]); if (!filename) @@ -3467,10 +3637,13 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, args->send_pipe, args->recv_pipe); if (JS_IsException(obj)) goto fail; - + pthread_attr_init(&attr); /* no join at the end */ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + // musl libc gives threads 80 kb stacks, much smaller than + // JS_DEFAULT_STACK_SIZE (1 MB) + pthread_attr_setstacksize(&attr, 2 << 20); // 2 MB, glibc default ret = pthread_create(&tid, &attr, worker_func, args); pthread_attr_destroy(&attr); if (ret != 0) { @@ -3496,22 +3669,24 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, return JS_EXCEPTION; } -static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_worker_postMessage(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessagePipe *ps; - size_t data_len, sab_tab_len, i; + size_t data_len, i; uint8_t *data; JSWorkerMessage *msg; - uint8_t **sab_tab; - + JSSABTab 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_len); + &sab_tab); if (!data) return JS_EXCEPTION; @@ -3528,15 +3703,17 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, memcpy(msg->data, data, data_len); msg->data_len = data_len; - msg->sab_tab = malloc(sizeof(msg->sab_tab[0]) * sab_tab_len); - if (!msg->sab_tab) - goto fail; - memcpy(msg->sab_tab, sab_tab, sizeof(msg->sab_tab[0]) * sab_tab_len); - msg->sab_tab_len = 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); + } + msg->sab_tab_len = sab_tab.len; js_free(ctx, data); - js_free(ctx, sab_tab); - + js_free(ctx, sab_tab.tab); + /* increment the SAB reference counts */ for(i = 0; i < msg->sab_tab_len; i++) { js_sab_dup(NULL, msg->sab_tab[i]); @@ -3566,19 +3743,19 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, free(msg); } js_free(ctx, data); - js_free(ctx, sab_tab); + js_free(ctx, sab_tab.tab); return JS_EXCEPTION; - + } -static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val, - JSValueConst func) +static JSValue js_worker_set_onmessage(JSContext *ctx, JSValue this_val, + JSValue func) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); + JSThreadState *ts = js_get_thread_state(rt); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessageHandler *port; - + if (!worker) return JS_EXCEPTION; @@ -3606,9 +3783,11 @@ static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_worker_get_onmessage(JSContext *ctx, JSValueConst this_val) +static JSValue js_worker_get_onmessage(JSContext *ctx, JSValue this_val) { - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessageHandler *port; if (!worker) return JS_EXCEPTION; @@ -3640,8 +3819,20 @@ void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)) #define OS_PLATFORM "darwin" #elif defined(EMSCRIPTEN) #define OS_PLATFORM "js" -#else +#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" +#else +#define OS_PLATFORM "unknown" #endif #define OS_FLAG(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE ) @@ -3664,8 +3855,10 @@ 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 ), @@ -3677,7 +3870,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { OS_FLAG(SIGILL), OS_FLAG(SIGSEGV), OS_FLAG(SIGTERM), -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__wasi__) OS_FLAG(SIGQUIT), OS_FLAG(SIGPIPE), OS_FLAG(SIGALRM), @@ -3689,10 +3882,14 @@ 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("now", 0, js_os_now ), - JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ), + 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("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 ), @@ -3715,8 +3912,10 @@ 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 ), -#if !defined(_WIN32) +#endif +#if !defined(_WIN32) && !defined(__wasi__) 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 ), @@ -3733,42 +3932,38 @@ static const JSCFunctionListEntry js_os_funcs[] = { static int js_os_init(JSContext *ctx, JSModuleDef *m) { - os_poll_func = js_os_poll; - - /* OSTimer class */ - JS_NewClassID(&js_os_timer_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_os_timer_class_id, &js_os_timer_class); + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + + ts->can_js_os_poll = TRUE; #ifdef USE_WORKER { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); JSValue proto, obj; /* Worker class */ - JS_NewClassID(&js_worker_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_worker_class_id, &js_worker_class); + JS_NewClassID(rt, &ts->worker_class_id); + JS_NewClass(rt, ts->worker_class_id, &js_worker_class); proto = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, proto, js_worker_proto_funcs, countof(js_worker_proto_funcs)); - + obj = JS_NewCFunction2(ctx, js_worker_ctor, "Worker", 1, JS_CFUNC_constructor, 0); JS_SetConstructor(ctx, obj, proto); - - JS_SetClassProto(ctx, js_worker_class_id, proto); - + + JS_SetClassProto(ctx, ts->worker_class_id, proto); + /* set 'Worker.parent' if necessary */ if (ts->recv_pipe && ts->send_pipe) { JS_DefinePropertyValueStr(ctx, obj, "parent", js_worker_ctor_internal(ctx, JS_UNDEFINED, ts->recv_pipe, ts->send_pipe), JS_PROP_C_W_E); } - + JS_SetModuleExport(ctx, m, "Worker", obj); } #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) @@ -3786,23 +3981,54 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) /**********************************************************/ -static JSValue js_print(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_print(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { +#ifdef _WIN32 + HANDLE handle; + DWORD mode; +#endif + const char *s; + DynBuf b; int i; - const char *str; - size_t len; + dbuf_init(&b); for(i = 0; i < argc; i++) { - if (i != 0) - putchar(' '); - str = JS_ToCStringLen(ctx, &len, argv[i]); - if (!str) - return JS_EXCEPTION; - fwrite(str, 1, len, stdout); - JS_FreeCString(ctx, str); + s = JS_ToCString(ctx, argv[i]); + if (s) { + dbuf_printf(&b, "%s%s", &" "[!i], s); + JS_FreeCString(ctx, s); + } else { + dbuf_printf(&b, "%s", &" "[!i]); + JS_FreeValue(ctx, JS_GetException(ctx)); + } } - putchar('\n'); + 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); return JS_UNDEFINED; } @@ -3827,31 +4053,39 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) } JS_SetPropertyStr(ctx, global_obj, "scriptArgs", args); } - + 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 = malloc(sizeof(*ts)); + ts = js_mallocz_rt(rt, 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); - JS_SetRuntimeOpaque(rt, ts); + ts->next_timer_id = 1; + ts->exc = JS_UNDEFINED; + + js_set_thread_state(rt, ts); + JS_AddRuntimeFinalizer(rt, js_std_finalize, ts); #ifdef USE_WORKER /* set the SharedArrayBuffer memory handlers */ @@ -3868,7 +4102,7 @@ void js_std_init_handlers(JSRuntime *rt) void js_std_free_handlers(JSRuntime *rt) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); struct list_head *el, *el1; list_for_each_safe(el, el1, &ts->os_rw_handlers) { @@ -3880,12 +4114,10 @@ void js_std_free_handlers(JSRuntime *rt) JSOSSignalHandler *sh = list_entry(el, JSOSSignalHandler, link); free_sh(rt, sh); } - + list_for_each_safe(el, el1, &ts->os_timers) { JSOSTimer *th = list_entry(el, JSOSTimer, link); - unlink_timer(rt, th); - if (!th->has_object) - free_timer(rt, th); + free_timer(rt, th); } #ifdef USE_WORKER @@ -3893,15 +4125,12 @@ void js_std_free_handlers(JSRuntime *rt) js_free_message_pipe(ts->recv_pipe); js_free_message_pipe(ts->send_pipe); #endif - - free(ts); - JS_SetRuntimeOpaque(rt, NULL); /* fail safe */ } -static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val) +static void js_dump_obj(JSContext *ctx, FILE *f, JSValue val) { const char *str; - + str = JS_ToCString(ctx, val); if (str) { fprintf(f, "%s\n", str); @@ -3911,11 +4140,11 @@ static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val) } } -static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val) +void js_std_dump_error1(JSContext *ctx, JSValue exception_val) { JSValue val; BOOL is_error; - + is_error = JS_IsError(ctx, exception_val); js_dump_obj(ctx, stderr, exception_val); if (is_error) { @@ -3930,14 +4159,14 @@ static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val) void js_std_dump_error(JSContext *ctx) { JSValue exception_val; - + exception_val = JS_GetException(ctx); js_std_dump_error1(ctx, exception_val); JS_FreeValue(ctx, exception_val); } -void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, +void js_std_promise_rejection_tracker(JSContext *ctx, JSValue promise, + JSValue reason, BOOL is_handled, void *opaque) { if (!is_handled) { @@ -3947,9 +4176,12 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, } /* main loop which calls the user JS callbacks */ -void js_std_loop(JSContext *ctx) +JSValue js_std_loop(JSContext *ctx) { + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); JSContext *ctx1; + JSValue ret; int err; for(;;) { @@ -3958,15 +4190,58 @@ void js_std_loop(JSContext *ctx) err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); if (err <= 0) { if (err < 0) { - js_std_dump_error(ctx1); + ts->exc = JS_GetException(ctx1); + goto done; } break; } } - if (!os_poll_func || os_poll_func(ctx)) + if (!ts->can_js_os_poll || js_os_poll(ctx)) break; } +done: + ret = ts->exc; + ts->exc = JS_UNDEFINED; + return ret; +} + +/* Wait for a promise and execute pending jobs while waiting for + it. Return the promise result or JS_EXCEPTION in case of promise + 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; + + for(;;) { + state = JS_PromiseState(ctx, obj); + if (state == JS_PROMISE_FULFILLED) { + ret = JS_PromiseResult(ctx, obj); + JS_FreeValue(ctx, obj); + break; + } else if (state == JS_PROMISE_REJECTED) { + ret = JS_Throw(ctx, JS_PromiseResult(ctx, obj)); + JS_FreeValue(ctx, obj); + break; + } else if (state == JS_PROMISE_PENDING) { + JSContext *ctx1; + int err; + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + if (err < 0) { + js_std_dump_error(ctx1); + } + if (ts->can_js_os_poll) + js_os_poll(ctx); + } else { + /* not a promise */ + ret = obj; + break; + } + } + return ret; } void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, @@ -3987,8 +4262,11 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, goto exception; } js_module_set_import_meta(ctx, obj, FALSE, TRUE); + val = JS_EvalFunction(ctx, obj); + val = js_std_await(ctx, val); + } else { + val = JS_EvalFunction(ctx, obj); } - val = JS_EvalFunction(ctx, obj); if (JS_IsException(val)) { exception: js_std_dump_error(ctx); @@ -3997,3 +4275,77 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, JS_FreeValue(ctx, val); } } + +static JSValue js_bjson_read(JSContext *ctx, JSValue this_val, + int argc, JSValue *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; + 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, JSValue this_val, + int argc, JSValue *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; +} diff --git a/quickjs-libc.h b/quickjs-libc.h index fbbe5b0..f80cf71 100644 --- a/quickjs-libc.h +++ b/quickjs-libc.h @@ -1,6 +1,6 @@ /* * QuickJS C library - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -35,23 +35,26 @@ extern "C" { JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); +JSModuleDef *js_init_module_bjson(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_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); +void js_std_dump_error1(JSContext *ctx, JSValue exception_val); 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, +int js_module_set_import_meta(JSContext *ctx, JSValue func_val, JS_BOOL use_realpath, JS_BOOL is_main); JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque); void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); -void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, +void js_std_promise_rejection_tracker(JSContext *ctx, JSValue promise, + JSValue reason, JS_BOOL is_handled, void *opaque); void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); - + #ifdef __cplusplus } /* extern "C" { */ #endif diff --git a/quickjs-opcode.h b/quickjs-opcode.h index 6d2d6e9..fb5394c 100644 --- a/quickjs-opcode.h +++ b/quickjs-opcode.h @@ -1,6 +1,6 @@ /* * QuickJS opcode definitions - * + * * Copyright (c) 2017-2018 Fabrice Bellard * Copyright (c) 2017-2018 Charlie Gordon * @@ -44,6 +44,7 @@ FMT(loc) FMT(arg) FMT(var_ref) FMT(u32) +FMT(u32x2) FMT(i32) FMT(const) FMT(label) @@ -110,6 +111,7 @@ DEF( return, 1, 1, 0, none) DEF( return_undef, 1, 0, 0, none) DEF(check_ctor_return, 1, 1, 2, none) DEF( check_ctor, 1, 0, 0, none) +DEF( init_ctor, 1, 0, 1, none) DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ DEF( return_async, 1, 1, 0, none) @@ -135,9 +137,12 @@ 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 */ @@ -165,15 +170,14 @@ DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */ DEF( get_arg, 3, 0, 1, arg) DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */ DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */ -DEF( get_var_ref, 3, 0, 1, var_ref) +DEF( get_var_ref, 3, 0, 1, var_ref) DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ 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(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) DEF( close_loc, 3, 0, 0, loc) @@ -234,15 +238,20 @@ 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) @@ -253,17 +262,10 @@ 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) -#ifdef CONFIG_BIGNUM -DEF( mul_pow10, 1, 2, 1, none) -DEF( math_mod, 1, 2, 1, none) -#endif /* must be the last non short and non temporary opcode */ -DEF( nop, 1, 0, 0, none) +DEF( nop, 1, 0, 0, none) /* temporary opcodes: never emitted in the final bytecode */ @@ -272,8 +274,6 @@ 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 */ @@ -281,7 +281,6 @@ 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 */ @@ -289,10 +288,9 @@ def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */ 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( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ -#if SHORT_OPCODES +def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */ + DEF( push_minus1, 1, 0, 1, none_int) DEF( push_0, 1, 0, 1, none_int) DEF( push_1, 1, 0, 1, none_int) @@ -312,6 +310,7 @@ 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,7 +364,11 @@ 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 + +// order matters, see non-IC counterparts +DEF( get_field_ic, 5, 1, 1, none) +DEF( get_field2_ic, 5, 1, 2, none) +DEF( put_field_ic, 5, 2, 0, none) #undef DEF #undef def diff --git a/quickjs.c b/quickjs.c index 4e58a98..9e53701 100644 --- a/quickjs.c +++ b/quickjs.c @@ -1,8 +1,10 @@ /* * QuickJS Javascript Engine - * + * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon + * Copyright (c) 2023 Ben Noordhuis + * Copyright (c) 2023 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 @@ -28,17 +30,15 @@ #include #include #include +#if !defined(_MSC_VER) #include +#if defined(_WIN32) +#include +#endif +#endif #include #include #include -#if defined(__APPLE__) -#include -#elif defined(__linux__) -#include -#elif defined(__FreeBSD__) -#include -#endif #include "cutils.h" #include "list.h" @@ -46,9 +46,7 @@ #include "libregexp.h" #include "libbf.h" -#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 @@ -60,60 +58,64 @@ #define MALLOC_OVERHEAD 8 #endif -#if !defined(_WIN32) -/* define it if printf uses the RNDN rounding mode instead of RNDNA */ -#define CONFIG_PRINTF_RNDN +#if defined(__NEWLIB__) +#define NO_TM_GMTOFF #endif -/* define to include Atomics.* operations which depend on the OS - threads */ -#if !defined(EMSCRIPTEN) +// 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__ +#include "quickjs-c-atomics.h" #define CONFIG_ATOMICS #endif -#if !defined(EMSCRIPTEN) -/* enable stack limitation */ -#define CONFIG_STACK_CHECK +#ifndef __GNUC__ +#define __extension__ #endif +// Debug trace system: the debug output will be produced to the dump stream (currently +// stdout) if qjs is invoked with -D with the corresponding bit set. -/* 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_PROMISE -//#define DUMP_READ_OBJECT - -/* test the GC by forcing it before each object allocation */ -//#define FORCE_GC_AT_MALLOC - -#ifdef CONFIG_ATOMICS -#include -#include -#include +#ifndef NDEBUG +#define DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */ +#define DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */ +#define DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */ +#define DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */ +#define DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */ +#define DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */ +#define DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */ +#define DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */ +#define DUMP_FREE 0x200 /* dump every object free */ +#define DUMP_GC 0x400 /* dump the occurrence of the automatic GC */ +#define DUMP_GC_FREE 0x800 /* dump objects freed by the GC */ +#define DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */ +#define DUMP_PROMISE 0x2000 /* dump promise steps */ +#define DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */ +#define DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */ +#define DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */ +#define DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ +#define DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ +#define DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ #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 + enum { /* classid tag */ /* union usage | properties */ JS_CLASS_OBJECT = 1, /* must be first */ @@ -145,20 +147,18 @@ enum { JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */ + JS_CLASS_FLOAT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_DATAVIEW, /* u.typed_array */ JS_CLASS_BIG_INT, /* u.object_data */ -#ifdef CONFIG_BIGNUM - JS_CLASS_BIG_FLOAT, /* u.object_data */ - JS_CLASS_FLOAT_ENV, /* u.float_env */ - JS_CLASS_BIG_DECIMAL, /* u.object_data */ - JS_CLASS_OPERATOR_SET, /* u.operator_set */ -#endif JS_CLASS_MAP, /* u.map_state */ JS_CLASS_SET, /* u.map_state */ JS_CLASS_WEAKMAP, /* u.map_state */ JS_CLASS_WEAKSET, /* u.map_state */ + JS_CLASS_ITERATOR, + JS_CLASS_ITERATOR_HELPER, /* u.iterator_helper_data */ + JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */ JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ @@ -175,6 +175,9 @@ enum { JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ + JS_CLASS_WEAK_REF, + JS_CLASS_FINALIZATION_REGISTRY, + JS_CLASS_CALL_SITE, JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; @@ -193,8 +196,9 @@ typedef enum JSErrorEnum { JS_URI_ERROR, JS_INTERNAL_ERROR, 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 @@ -207,31 +211,26 @@ typedef struct JSShape JSShape; typedef struct JSString JSString; typedef struct JSString JSAtomStruct; +#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) + typedef enum { JS_GC_PHASE_NONE, JS_GC_PHASE_DECREF, JS_GC_PHASE_REMOVE_CYCLES, } JSGCPhaseEnum; -typedef enum OPCodeEnum OPCodeEnum; +typedef struct JSMallocState { + size_t malloc_count; + size_t malloc_size; + size_t malloc_limit; + void *opaque; /* user opaque */ +} JSMallocState; -/* function pointers are used for numeric operations so that it is - possible to remove some numeric types */ -typedef struct { - JSValue (*to_string)(JSContext *ctx, JSValueConst val); - JSValue (*from_string)(JSContext *ctx, const char *buf, - int radix, int flags, slimb_t *pexponent); - int (*unary_arith)(JSContext *ctx, - JSValue *pres, OPCodeEnum op, JSValue op1); - int (*binary_arith)(JSContext *ctx, OPCodeEnum op, - JSValue *pres, JSValue op1, JSValue op2); - int (*compare)(JSContext *ctx, OPCodeEnum op, - JSValue op1, JSValue op2); - /* only for bigfloat: */ - JSValue (*mul_pow10_to_float64)(JSContext *ctx, const bf_t *a, - int64_t exponent); - int (*mul_pow10)(JSContext *ctx, JSValue *sp); -} JSNumericOperations; +typedef struct JSRuntimeFinalizerState { + struct JSRuntimeFinalizerState *next; + JSRuntimeFinalizer *finalizer; + void *arg; +} JSRuntimeFinalizerState; struct JSRuntime { JSMallocFunctions mf; @@ -246,6 +245,7 @@ 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; @@ -254,7 +254,7 @@ struct JSRuntime { by the garbage collector) */ struct list_head gc_obj_list; /* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */ - struct list_head gc_zero_ref_count_list; + struct list_head gc_zero_ref_count_list; struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold; @@ -265,10 +265,14 @@ struct JSRuntime { uintptr_t stack_size; /* in bytes, 0 if no limit */ uintptr_t stack_top; uintptr_t stack_limit; /* lower stack limit */ - + JSValue current_exception; /* true if inside an out of memory error, to avoid recursing */ BOOL in_out_of_memory : 8; + /* and likewise if inside Error.prepareStackTrace() */ + BOOL in_prepare_stack_trace : 8; + /* true if inside JS_FreeRuntime */ + BOOL in_free : 8; struct JSStackFrame *current_stack_frame; @@ -277,7 +281,7 @@ struct JSRuntime { JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; - + struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; @@ -285,24 +289,22 @@ struct JSRuntime { 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 : 8; /* TRUE if Atomics.wait can block */ + uint32_t dump_flags : 24; + /* Shape hash table */ int shape_hash_bits; int shape_hash_size; int shape_hash_count; /* number of hashed shapes */ JSShape **shape_hash; bf_context_t bf_ctx; - JSNumericOperations bigint_ops; -#ifdef CONFIG_BIGNUM - JSNumericOperations bigfloat_ops; - JSNumericOperations bigdecimal_ops; - uint32_t operator_count; -#endif void *user_opaque; + void *libc_opaque; + JSRuntimeFinalizerState *finalizers; }; struct JSClass { @@ -315,23 +317,18 @@ struct JSClass { const JSClassExoticMethods *exotic; }; -#define JS_MODE_STRICT (1 << 0) -#define JS_MODE_STRIP (1 << 1) -#define JS_MODE_MATH (1 << 2) -#define JS_MODE_ASYNC (1 << 3) /* async function */ - 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.var_ref_link */ - const uint8_t *cur_pc; /* only used in bytecode functions : PC of the + struct list_head var_ref_list; /* list of JSVarRef.link */ + uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ - int arg_count; - int js_mode; /* for C functions, only JS_MODE_MATH may be set */ + uint32_t arg_count : 31; + uint32_t is_strict_mode : 1; /* only used in generators. Current stack pointer value. NULL if - the function is running. */ + the function is running. */ JSValue *cur_sp; } JSStackFrame; @@ -362,7 +359,12 @@ typedef struct JSVarRef { struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ - uint8_t is_detached : 1; + + /* 0 : the JSVarRef is on the stack. header.link is an element + of JSStackFrame.var_ref_list. + 1 : the JSVarRef is detached. header.link has the normal meanning + */ + uint8_t is_detached : 1; uint8_t is_arg : 1; uint16_t var_idx; /* index of the corresponding function variable on the stack */ @@ -370,34 +372,19 @@ typedef struct JSVarRef { }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ - 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 */ - }; + JSValue value; /* used when the variable is no longer on the stack */ } JSVarRef; -/* the same structure is used for big integers and big floats. Big - integers are never infinite or NaNs */ -typedef struct JSBigFloat { +typedef struct JSRefCountHeader { + int ref_count; +} JSRefCountHeader; + +/* the same structure is used for big integers. + Big integers are never infinite or NaNs */ +typedef struct JSBigInt { JSRefCountHeader header; /* must come first, 32-bit */ bf_t num; -} JSBigFloat; - -#ifdef CONFIG_BIGNUM -typedef struct JSFloatEnv { - limb_t prec; - bf_flags_t flags; - unsigned int status; -} JSFloatEnv; - -typedef struct JSBigDecimal { - JSRefCountHeader header; /* must come first, 32-bit */ - bfdec_t num; -} JSBigDecimal; -#endif +} JSBigInt; typedef enum { JS_AUTOINIT_ID_PROTOTYPE, @@ -426,6 +413,10 @@ struct JSContext { JSValue regexp_ctor; JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; + JSValue error_ctor; + JSValue error_prepare_stack; + int error_stack_trace_limit; + JSValue iterator_ctor; JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; @@ -435,23 +426,20 @@ struct JSContext { JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ + double time_origin; + uint64_t random_state; bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */ -#ifdef CONFIG_BIGNUM - JSFloatEnv fp_env; /* global FP environment */ - BOOL bignum_ext : 8; /* enable math mode */ - BOOL allow_operator_overloading : 8; -#endif /* when the counter reaches zero, JSRutime.interrupt_handler is called */ int interrupt_counter; struct list_head loaded_modules; /* list of JSModuleDef.link */ /* if NULL, RegExp compilation is not supported */ - JSValue (*compile_regexp)(JSContext *ctx, JSValueConst pattern, - JSValueConst flags); + JSValue (*compile_regexp)(JSContext *ctx, JSValue pattern, + JSValue flags); /* if NULL, eval is not supported */ - JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj, + JSValue (*eval_internal)(JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); void *user_opaque; @@ -463,6 +451,22 @@ 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; + enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, @@ -493,12 +497,13 @@ struct JSString { 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 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]; + __extension__ uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */ + __extension__ uint16_t str16[0]; } u; }; @@ -544,7 +549,7 @@ typedef struct JSVarDef { JSAtom var_name; /* index into fd->scopes of this variable lexical scope */ int scope_level; - /* during compilation: + /* during compilation: - if scope_level = 0: scope in which the variable is defined - if scope_level != 0: index into fd->vars of the next variable in the same or enclosing lexical scope @@ -552,7 +557,7 @@ typedef struct JSVarDef { index into fd->vars of the next variable in the same or enclosing lexical scope */ - int scope_next; + int scope_next; uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t is_captured : 1; @@ -581,9 +586,82 @@ typedef enum JSFunctionKindEnum { JS_FUNC_ASYNC_GENERATOR = (JS_FUNC_GENERATOR | JS_FUNC_ASYNC), } JSFunctionKindEnum; +#define IC_CACHE_ITEM_CAPACITY 4 + +typedef struct JSInlineCacheRingSlot { + /* SoA for space optimization: 56 bytes */ + JSShape* shape[IC_CACHE_ITEM_CAPACITY]; + uint32_t prop_offset[IC_CACHE_ITEM_CAPACITY]; + JSAtom atom; + uint8_t index; +} JSInlineCacheRingSlot; + +typedef struct JSInlineCacheHashSlot { + JSAtom atom; + uint32_t index; + struct JSInlineCacheHashSlot *next; +} JSInlineCacheHashSlot; + +typedef struct JSInlineCache { + uint32_t count; + uint32_t capacity; + uint32_t hash_bits; + JSInlineCacheHashSlot **hash; + JSInlineCacheRingSlot *cache; +} JSInlineCache; + +#define INLINE_CACHE_MISS ((uint32_t)-1) // sentinel + +// This is a struct so we don't tie up two argument registers in calls to +// JS_GetPropertyInternal2 and JS_SetPropertyInternal2 in the common case +// where there is no IC and therefore no offset to update. +typedef struct JSInlineCacheUpdate { + JSInlineCache *ic; + uint32_t offset; +} JSInlineCacheUpdate; + +static JSInlineCache *init_ic(JSContext *ctx); +static int rebuild_ic(JSContext *ctx, JSInlineCache *ic); +static int resize_ic_hash(JSContext *ctx, JSInlineCache *ic); +static int free_ic(JSRuntime *rt, JSInlineCache *ic); +static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu, + JSAtom atom, JSObject *object, uint32_t prop_offset); + +static uint32_t get_ic_prop_offset(const JSInlineCacheUpdate *icu, + JSShape *shape) +{ + uint32_t i, cache_offset = icu->offset; + JSInlineCache *ic = icu->ic; + JSInlineCacheRingSlot *cr; + JSShape *shape_slot; + assert(cache_offset < ic->capacity); + cr = ic->cache + cache_offset; + i = cr->index; + for (;;) { + shape_slot = *(cr->shape + i); + if (likely(shape_slot == shape)) { + cr->index = i; + return cr->prop_offset[i]; + } + + i = (i + 1) % countof(cr->shape); + if (unlikely(i == cr->index)) { + break; + } + } + + return INLINE_CACHE_MISS; +} + +static force_inline JSAtom get_ic_atom(JSInlineCache *ic, uint32_t cache_offset) +{ + assert(cache_offset < ic->capacity); + return ic->cache[cache_offset].atom; +} + typedef struct JSFunctionBytecode { JSGCObjectHeader header; /* must come first */ - uint8_t js_mode; + uint8_t is_strict_mode : 1; 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; @@ -594,11 +672,8 @@ typedef struct JSFunctionBytecode { uint8_t super_call_allowed : 1; uint8_t super_allowed : 1; uint8_t arguments_allowed : 1; - uint8_t has_debug : 1; uint8_t backtrace_barrier : 1; /* stop backtrace on this function */ - uint8_t read_only_bytecode : 1; - uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */ - /* XXX: 4 bits available */ + /* XXX: 5 bits available */ uint8_t *byte_code_buf; /* (self pointer) */ int byte_code_len; JSAtom func_name; @@ -612,22 +687,21 @@ typedef struct JSFunctionBytecode { JSValue *cpool; /* constant pool (self pointer) */ int cpool_count; int closure_var_count; - struct { - /* debug info, move to separate structure to save memory? */ - JSAtom filename; - int line_num; - int source_len; - int pc2line_len; - uint8_t *pc2line_buf; - char *source; - } debug; + JSInlineCache *ic; + JSAtom filename; + int line_num; + int col_num; + int source_len; + int pc2line_len; + uint8_t *pc2line_buf; + char *source; } JSFunctionBytecode; typedef struct JSBoundFunction { JSValue func_obj; JSValue this_val; int argc; - JSValue argv[0]; + JSValue argv[]; } JSBoundFunction; typedef enum JSIteratorKindEnum { @@ -636,13 +710,23 @@ 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 { @@ -659,6 +743,7 @@ typedef struct JSProxyData { typedef struct JSArrayBuffer { int byte_length; /* 0 if detached */ + int max_byte_length; /* -1 if not resizable; >= byte_length otherwise */ uint8_t detached; uint8_t shared; /* if shared, the array buffer cannot be detached */ uint8_t *data; /* NULL if detached */ @@ -671,67 +756,26 @@ typedef struct JSTypedArray { struct list_head link; /* link to arraybuffer */ JSObject *obj; /* back pointer to the TypedArray/DataView object */ JSObject *buffer; /* based array buffer */ - uint32_t offset; /* offset in the array buffer */ - uint32_t length; /* length in the 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 */ } JSTypedArray; typedef struct JSAsyncFunctionState { - JSGCObjectHeader header; - JSValue this_val; /* 'this' argument */ + JSValue this_val; /* 'this' generator argument */ int argc; /* number of function arguments */ 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; -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; +/* 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 struct JSReqModuleEntry { JSAtom module_name; @@ -817,10 +861,9 @@ struct JSModuleDef { 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 : 8; + BOOL eval_has_exception : 8; JSValue eval_exception; JSValue meta_obj; /* for import.meta */ }; @@ -830,7 +873,7 @@ typedef struct JSJobEntry { JSContext *ctx; JSJobFunc *job_func; int argc; - JSValue argv[0]; + JSValue argv[]; } JSJobEntry; typedef struct JSProperty { @@ -879,7 +922,7 @@ struct JSShape { int deleted_prop_count; JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ JSObject *proto; - JSShapeProperty prop[0]; /* prop_size elements */ + JSShapeProperty prop[]; /* prop_size elements */ }; struct JSObject { @@ -888,7 +931,7 @@ struct JSObject { struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ - + 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 */ @@ -904,7 +947,7 @@ struct JSObject { JSShape *shape; /* prototype and property names + flag */ JSProperty *prop; /* array of properties */ /* byte offsets: 24/40 */ - struct JSMapRecord *first_weak_ref; /* XXX: use a bit and an external hash table? */ + JSWeakRefRecord *first_weak_ref; /* byte offsets: 28/48 */ union { void *opaque; @@ -913,19 +956,17 @@ struct JSObject { struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */ struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */ struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */ -#ifdef CONFIG_BIGNUM - struct JSFloatEnv *float_env; /* JS_CLASS_FLOAT_ENV */ - struct JSOperatorSetData *operator_set; /* JS_CLASS_OPERATOR_SET */ -#endif struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */ struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */ 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 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 JSAsyncFunctionState *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */ + struct JSAsyncFunctionData *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 */ @@ -948,7 +989,7 @@ struct JSObject { struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ } u1; union { - JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ + JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ @@ -958,6 +999,7 @@ struct JSObject { uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */ int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */ uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */ + uint16_t *fp16_ptr; /* JS_CLASS_FLOAT16_ARRAY */ float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */ double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */ } u; @@ -968,6 +1010,16 @@ struct JSObject { } 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; + enum { __JS_ATOM_NULL = JS_ATOM_NULL, #define DEF(name, str) JS_ATOM_ ## name, @@ -992,7 +1044,7 @@ typedef enum OPCodeFormat { #undef FMT } OPCodeFormat; -enum OPCodeEnum { +typedef 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) @@ -1012,114 +1064,120 @@ 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, int atom_type); static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p); static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b); -static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags); -static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags); -static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, JSValueConst new_target, +static JSValue js_call_c_function(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags); +static JSValue js_call_bound_function(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags); +static JSValue JS_CallInternal(JSContext *ctx, JSValue func_obj, + JSValue this_obj, JSValue new_target, int argc, JSValue *argv, int flags); static JSValue JS_CallConstructorInternal(JSContext *ctx, - JSValueConst func_obj, - JSValueConst new_target, + JSValue func_obj, + JSValue new_target, 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_CallFree(JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv); static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, - int argc, JSValueConst *argv); + int argc, JSValue *argv); static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, JSValue val, BOOL is_array_ctor); -static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, - JSValueConst val, int flags, int scope_idx); +static JSValue JS_EvalObject(JSContext *ctx, JSValue this_obj, + JSValue val, int flags, int scope_idx); 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_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_DumpValueShort(JSRuntime *rt, - JSValueConst val); -static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val); -static __maybe_unused void JS_PrintValue(JSContext *ctx, - const char *str, - JSValueConst val); +static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val); +static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); static __maybe_unused void JS_DumpShapes(JSRuntime *rt); -static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic); + +static JSValue js_function_apply(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic); static void js_array_finalizer(JSRuntime *rt, JSValue val); -static void js_array_mark(JSRuntime *rt, JSValueConst val, +static void js_array_mark(JSRuntime *rt, JSValue 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, +static void js_object_data_mark(JSRuntime *rt, JSValue 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, +static void js_c_function_mark(JSRuntime *rt, JSValue 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, +static void js_bytecode_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_bound_function_finalizer(JSRuntime *rt, JSValue val); -static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, +static void js_bound_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val); -static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_for_in_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); 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, +static void js_typed_array_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_proxy_finalizer(JSRuntime *rt, JSValue val); -static void js_proxy_mark(JSRuntime *rt, JSValueConst val, +static void js_proxy_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_map_finalizer(JSRuntime *rt, JSValue val); -static void js_map_mark(JSRuntime *rt, JSValueConst val, +static void js_map_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val); -static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_map_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val); -static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_array_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); +static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val); +static void js_iterator_helper_mark(JSRuntime *rt, JSValue val, + JS_MarkFunc *mark_func); +static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val); +static void js_iterator_wrap_mark(JSRuntime *rt, JSValue val, + JS_MarkFunc *mark_func); static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val); -static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_generator_finalizer(JSRuntime *rt, JSValue obj); -static void js_generator_mark(JSRuntime *rt, JSValueConst val, +static void js_generator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_promise_finalizer(JSRuntime *rt, JSValue val); -static void js_promise_mark(JSRuntime *rt, JSValueConst val, +static void js_promise_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val); -static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, +static void js_promise_resolve_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); -#ifdef CONFIG_BIGNUM -static void js_operator_set_finalizer(JSRuntime *rt, JSValue val); -static void js_operator_set_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -#endif + +#define HINT_STRING 0 +#define HINT_NUMBER 1 +#define HINT_NONE 2 +#define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive +static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint); static JSValue JS_ToStringFree(JSContext *ctx, JSValue val); static int JS_ToBoolFree(JSContext *ctx, JSValue val); static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val); static int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val); static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val); -static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, - JSValueConst flags); -static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, +static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len); +static JSValue js_compile_regexp(JSContext *ctx, JSValue pattern, + JSValue flags); +static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValue ctor, JSValue pattern, JSValue bc); 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); typedef enum JSStrictEqModeEnum { JS_EQ_STRICT, @@ -1130,117 +1188,104 @@ typedef enum JSStrictEqModeEnum { 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 JSValue JS_ToObject(JSContext *ctx, JSValueConst val); +static BOOL js_same_value(JSContext *ctx, JSValue op1, JSValue op2); +static BOOL js_same_value_zero(JSContext *ctx, JSValue op1, JSValue op2); +static JSValue JS_ToObject(JSContext *ctx, JSValue val); static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); static JSValue JS_NewBigInt(JSContext *ctx); -static inline bf_t *JS_GetBigInt(JSValueConst val) +static inline bf_t *JS_GetBigInt(JSValue val) { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); return &p->num; } -static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val, - BOOL convert_to_safe_integer); +static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val); static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val); static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); -static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val); +static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValue val); +static bf_t *JS_ToBigInt1(JSContext *ctx, bf_t *buf, JSValue val); static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf); -#ifdef CONFIG_BIGNUM -static void js_float_env_finalizer(JSRuntime *rt, JSValue val); -static JSValue JS_NewBigFloat(JSContext *ctx); -static inline bf_t *JS_GetBigFloat(JSValueConst val) -{ - JSBigFloat *p = JS_VALUE_GET_PTR(val); - return &p->num; -} -static JSValue JS_NewBigDecimal(JSContext *ctx); -static inline bfdec_t *JS_GetBigDecimal(JSValueConst val) -{ - JSBigDecimal *p = JS_VALUE_GET_PTR(val); - return &p->num; -} -static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val); -static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val, - BOOL allow_null_or_undefined); -static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val); -#endif 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 JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValue obj); +static int js_proxy_setPrototypeOf(JSContext *ctx, JSValue obj, + JSValue proto_val, BOOL throw_flag); +static int js_proxy_isExtensible(JSContext *ctx, JSValue obj); +static int js_proxy_preventExtensions(JSContext *ctx, JSValue obj); +static int js_proxy_isArray(JSContext *ctx, JSValue obj); static int JS_CreateProperty(JSContext *ctx, JSObject *p, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags); static int js_string_memcmp(const JSString *p1, const JSString *p2, int len); -static void reset_weak_ref(JSRuntime *rt, JSObject *p); +static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref); +static BOOL is_valid_weakref_target(JSValue val); +static void insert_weakref_record(JSValue target, struct JSWeakRefRecord *wr); static JSValue js_array_buffer_constructor3(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id, + JSValue new_target, + uint64_t len, uint64_t *max_len, + JSClassID class_id, uint8_t *buf, JSFreeArrayBufferDataFunc *free_func, void *opaque, BOOL alloc_flag); -static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); +static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr); +static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValue obj); +static BOOL array_buffer_is_resizable(const JSArrayBuffer *abuf); static JSValue js_typed_array_constructor(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, + JSValue this_val, + int argc, JSValue *argv, int classid); static JSValue js_typed_array_constructor_ta(JSContext *ctx, - JSValueConst new_target, - JSValueConst src_obj, - int classid); -static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p); + JSValue new_target, + JSValue src_obj, + int classid, uint32_t len); +static BOOL typed_array_is_oob(JSObject *p); static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p); 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); -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, +static JSValue js_generator_function_call(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags); static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val); -static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, +static void js_async_function_resolve_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); -static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, +static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); static void js_free_module_def(JSContext *ctx, 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, JSValue specifier); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, - JSValueConst ctor); + JSValue ctor); static __exception int perform_promise_then(JSContext *ctx, - JSValueConst promise, - JSValueConst *resolve_reject, - JSValueConst *cap_resolving_funcs); -static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic); + JSValue promise, + JSValue *resolve_reject, + JSValue *cap_resolving_funcs); +static JSValue js_promise_resolve(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic); static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); -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, +static BOOL js_string_eq(const JSString *p1, const JSString *p2); +static int js_string_compare(const JSString *p1, const JSString *p2); +static JSValue JS_ToNumber(JSContext *ctx, JSValue val); +static int JS_SetPropertyValue(JSContext *ctx, JSValue 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 int JS_NumberIsInteger(JSContext *ctx, JSValue val); +static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValue 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 void js_free_shape(JSRuntime *rt, JSShape *sh); static void js_free_shape_null(JSRuntime *rt, JSShape *sh); @@ -1248,40 +1293,136 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, JSShapeProperty **pprs); static int init_shape_hash(JSRuntime *rt); static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, - JSValueConst obj); + JSValue obj); static __exception int js_get_length64(JSContext *ctx, int64_t *pres, - JSValueConst obj); + JSValue obj); +static __exception int js_set_length64(JSContext *ctx, JSValue 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 BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, + JSValue array_arg); +static BOOL js_get_fast_array(JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp); static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, - JSValueConst sync_iter); + JSValue sync_iter); static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val); -static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, +static void js_c_function_data_mark(JSRuntime *rt, JSValue 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 JSValue js_c_function_data_call(JSContext *ctx, JSValue func_obj, + JSValue this_val, + int argc, JSValue *argv, int flags); 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); -void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag); -static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_map); +void JS_SetUncatchableError(JSContext *ctx, JSValue 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(JSValue obj, void *opaque); 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 JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT; + +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); +} + +#define JS_NewInt64(ctx, val) js_int64(val) + +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(JS_BOOL v) +{ + return JS_MKVAL(JS_TAG_BOOL, (v != 0)); +} + +static JSValue js_dup(JSValue v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return v; +} + +JSValue JS_DupValue(JSContext *ctx, JSValue v) +{ + return js_dup(v); +} + +JSValue JS_DupValueRT(JSRuntime *rt, JSValue v) +{ + return js_dup(v); +} static void js_trigger_gc(JSRuntime *rt, size_t size) { @@ -1294,8 +1435,10 @@ static void js_trigger_gc(JSRuntime *rt, size_t size) #endif if (force_gc) { #ifdef DUMP_GC - printf("GC: size=%" PRIu64 "\n", - (uint64_t)rt->malloc_state.malloc_size); + if (check_dump_flag(rt, 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 + @@ -1308,19 +1451,99 @@ 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) { - return rt->mf.js_malloc(&rt->malloc_state, 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; } void js_free_rt(JSRuntime *rt, void *ptr) { - rt->mf.js_free(&rt->malloc_state, 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); } void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size) { - return rt->mf.js_realloc(&rt->malloc_state, ptr, 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; +} + +static void *js_dbuf_realloc(void *opaque, void *ptr, size_t size) +{ + JSRuntime *rt = opaque; + return js_realloc_rt(rt, ptr, size); } size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr) @@ -1328,13 +1551,16 @@ 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) { - void *ptr; - ptr = js_malloc_rt(rt, size); - if (!ptr) - return NULL; - return memset(ptr, 0, size); + return js_calloc_rt(rt, 1, size); } /* called by libbf */ @@ -1344,6 +1570,18 @@ static void *js_bf_realloc(void *opaque, void *ptr, size_t size) return js_realloc_rt(rt, ptr, 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); + return NULL; + } + return ptr; +} + /* Throw out of memory in case of error */ void *js_malloc(JSContext *ctx, size_t size) { @@ -1452,13 +1690,17 @@ static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size, static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) { - dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt); + dbuf_init2(s, ctx->rt, js_dbuf_realloc); } static inline int is_digit(int c) { return c >= '0' && c <= '9'; } +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 { JSAtom class_name; JSClassFinalizer *finalizer; @@ -1495,20 +1737,18 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */ { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */ { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */ + { JS_ATOM_Float16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT16_ARRAY */ { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */ { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */ { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */ { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */ -#ifdef CONFIG_BIGNUM - { JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_FLOAT */ - { JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL }, /* JS_CLASS_FLOAT_ENV */ - { JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_DECIMAL */ - { JS_ATOM_OperatorSet, js_operator_set_finalizer, js_operator_set_mark }, /* JS_CLASS_OPERATOR_SET */ -#endif { 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, 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_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 */ { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */ { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */ @@ -1534,73 +1774,6 @@ static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab, return 0; } -static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx) -{ - return JS_ThrowTypeError(ctx, "unsupported operation"); -} - -static JSValue invalid_to_string(JSContext *ctx, JSValueConst val) -{ - return JS_ThrowUnsupportedOperation(ctx); -} - -static JSValue invalid_from_string(JSContext *ctx, const char *buf, - int radix, int flags, slimb_t *pexponent) -{ - return JS_NAN; -} - -static int invalid_unary_arith(JSContext *ctx, - JSValue *pres, OPCodeEnum op, JSValue op1) -{ - JS_FreeValue(ctx, op1); - JS_ThrowUnsupportedOperation(ctx); - return -1; -} - -static int invalid_binary_arith(JSContext *ctx, OPCodeEnum op, - JSValue *pres, JSValue op1, JSValue op2) -{ - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - JS_ThrowUnsupportedOperation(ctx); - return -1; -} - -static JSValue invalid_mul_pow10_to_float64(JSContext *ctx, const bf_t *a, - int64_t exponent) -{ - return JS_ThrowUnsupportedOperation(ctx); -} - -static int invalid_mul_pow10(JSContext *ctx, JSValue *sp) -{ - JS_ThrowUnsupportedOperation(ctx); - return -1; -} - -static void set_dummy_numeric_ops(JSNumericOperations *ops) -{ - ops->to_string = invalid_to_string; - ops->from_string = invalid_from_string; - ops->unary_arith = invalid_unary_arith; - ops->binary_arith = invalid_binary_arith; - ops->mul_pow10_to_float64 = invalid_mul_pow10_to_float64; - ops->mul_pow10 = invalid_mul_pow10; -} - -#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 /* Note: OS and CPU dependent */ static inline uintptr_t js_get_stack_pointer(void) { @@ -1613,7 +1786,6 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) sp = js_get_stack_pointer() - alloca_size; return unlikely(sp < rt->stack_limit); } -#endif JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) { @@ -1622,32 +1794,29 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) memset(&ms, 0, sizeof(ms)); ms.opaque = opaque; - ms.malloc_limit = -1; + ms.malloc_limit = 0; - rt = mf->js_malloc(&ms, sizeof(JSRuntime)); + rt = mf->js_calloc(opaque, 1, 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; bf_context_init(&rt->bf_ctx, js_bf_realloc, rt); - set_dummy_numeric_ops(&rt->bigint_ops); -#ifdef CONFIG_BIGNUM - set_dummy_numeric_ops(&rt->bigfloat_ops); - set_dummy_numeric_ops(&rt->bigdecimal_ops); -#endif init_list_head(&rt->context_list); init_list_head(&rt->gc_obj_list); init_list_head(&rt->gc_zero_ref_count_list); rt->gc_phase = JS_GC_PHASE_NONE; - + #ifdef DUMP_LEAKS init_list_head(&rt->string_list); #endif @@ -1671,10 +1840,16 @@ 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_NULL; + rt->current_exception = JS_UNINITIALIZED; return rt; fail: @@ -1692,84 +1867,45 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque) rt->user_opaque = opaque; } -/* default memory allocation functions with memory limitation */ -static size_t js_def_malloc_usable_size(const void *ptr) +int JS_AddRuntimeFinalizer(JSRuntime *rt, JSRuntimeFinalizer *finalizer, + void *arg) { -#if defined(__APPLE__) - return malloc_size(ptr); -#elif defined(_WIN32) - return _msize((void *)ptr); -#elif defined(EMSCRIPTEN) + 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; return 0; -#elif defined(__linux__) - 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_malloc(JSMallocState *s, size_t size) +static void *js_def_calloc(void *opaque, size_t count, 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); - if (!ptr) - return NULL; - - s->malloc_count++; - s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - return ptr; + return calloc(count, size); } -static void js_def_free(JSMallocState *s, void *ptr) +static void *js_def_malloc(void *opaque, size_t size) { - if (!ptr) - return; + return malloc(size); +} - s->malloc_count--; - s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; +static void js_def_free(void *opaque, void *ptr) +{ free(ptr); } -static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size) +static void *js_def_realloc(void *opaque, void *ptr, size_t 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; + return realloc(ptr, size); } static const JSMallocFunctions def_malloc_funcs = { + js_def_calloc, js_def_malloc, js_def_free, js_def_realloc, - js_def_malloc_usable_size, + js__malloc_usable_size }; JSRuntime *JS_NewRuntime(void) @@ -1782,6 +1918,15 @@ void JS_SetMemoryLimit(JSRuntime *rt, size_t limit) rt->malloc_state.malloc_limit = limit; } +void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags) +{ + rt->dump_flags = flags; +} + +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) { @@ -1811,12 +1956,14 @@ void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, /* return 0 if OK, < 0 if exception */ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, - int argc, JSValueConst *argv) + int argc, JSValue *argv) { JSRuntime *rt = ctx->rt; JSJobEntry *e; int i; + assert(!rt->in_free); + e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue)); if (!e) return -1; @@ -1824,7 +1971,7 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, e->job_func = job_func; e->argc = argc; for(i = 0; i < argc; i++) { - e->argv[i] = JS_DupValue(ctx, argv[i]); + e->argv[i] = js_dup(argv[i]); } list_add_tail(&e->link, &rt->job_list); return 0; @@ -1853,7 +2000,7 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) e = list_entry(rt->job_list.next, JSJobEntry, link); list_del(&e->link); ctx = e->ctx; - res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv); + res = e->job_func(e->ctx, e->argc, e->argv); for(i = 0; i < e->argc; i++) JS_FreeValue(ctx, e->argv[i]); if (JS_IsException(res)) @@ -1937,6 +2084,7 @@ void JS_FreeRuntime(JSRuntime *rt) 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) { @@ -1951,7 +2099,7 @@ void JS_FreeRuntime(JSRuntime *rt) #ifdef DUMP_LEAKS /* leaking objects */ - { + if (check_dump_flag(rt, DUMP_LEAKS)) { BOOL header_done; JSGCObjectHeader *p; int count; @@ -1988,6 +2136,7 @@ void JS_FreeRuntime(JSRuntime *rt) printf("Secondary object leaks: %d\n", count); } #endif + assert(list_empty(&rt->gc_obj_list)); /* free the classes */ @@ -2001,9 +2150,9 @@ void JS_FreeRuntime(JSRuntime *rt) bf_context_end(&rt->bf_ctx); -#ifdef DUMP_LEAKS +#ifdef DUMP_ATOM_LEAKS /* only the atoms defined in JS_InitAtoms() should be left */ - { + if (check_dump_flag(rt, DUMP_ATOM_LEAKS)) { BOOL header_done = FALSE; for(i = 0; i < rt->atom_size; i++) { @@ -2073,7 +2222,7 @@ void JS_FreeRuntime(JSRuntime *rt) js_free_rt(rt, rt->atom_hash); js_free_rt(rt, rt->shape_hash); #ifdef DUMP_LEAKS - if (!list_empty(&rt->string_list)) { + if (check_dump_flag(rt, DUMP_LEAKS) && !list_empty(&rt->string_list)) { if (rt->rt_info) { printf("%s:1: string leakage:", rt->rt_info); } else { @@ -2100,7 +2249,17 @@ void JS_FreeRuntime(JSRuntime *rt) 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 DUMP_LEAKS + if (check_dump_flag(rt, DUMP_LEAKS)) { JSMallocState *s = &rt->malloc_state; if (s->malloc_count > 1) { if (rt->rt_info) @@ -2113,8 +2272,8 @@ void JS_FreeRuntime(JSRuntime *rt) #endif { - JSMallocState ms = rt->malloc_state; - rt->mf.js_free(&ms, rt); + JSMallocState *ms = &rt->malloc_state; + rt->mf.js_free(ms->opaque, rt); } } @@ -2138,15 +2297,15 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->rt = rt; list_add_tail(&ctx->link, &rt->context_list); ctx->bf_ctx = &rt->bf_ctx; -#ifdef CONFIG_BIGNUM - ctx->fp_env.prec = 113; - ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL; -#endif for(i = 0; i < rt->class_count; i++) ctx->class_proto[i] = JS_NULL; ctx->array_ctor = JS_NULL; + ctx->iterator_ctor = JS_NULL; ctx->regexp_ctor = JS_NULL; ctx->promise_ctor = JS_NULL; + ctx->error_ctor = JS_NULL; + ctx->error_prepare_stack = JS_UNDEFINED; + ctx->error_stack_trace_limit = 10; init_list_head(&ctx->loaded_modules); JS_AddIntrinsicBasicObjects(ctx); @@ -2164,7 +2323,6 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicBaseObjects(ctx); JS_AddIntrinsicDate(ctx); JS_AddIntrinsicEval(ctx); - JS_AddIntrinsicStringNormalize(ctx); JS_AddIntrinsicRegExp(ctx); JS_AddIntrinsicJSON(ctx); JS_AddIntrinsicProxy(ctx); @@ -2172,6 +2330,10 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicTypedArrays(ctx); JS_AddIntrinsicPromise(ctx); JS_AddIntrinsicBigInt(ctx); + JS_AddIntrinsicWeakRef(ctx); + + JS_AddPerformance(ctx); + return ctx; } @@ -2197,16 +2359,19 @@ static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val) void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj) { - JSRuntime *rt = ctx->rt; - assert(class_id < rt->class_count); + assert(class_id < ctx->rt->class_count); set_value(ctx, &ctx->class_proto[class_id], obj); } JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id) { - JSRuntime *rt = ctx->rt; - assert(class_id < rt->class_count); - return JS_DupValue(ctx, ctx->class_proto[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); } typedef enum JSFreeModuleEnum { @@ -2257,10 +2422,12 @@ 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_prepare_stack, mark_func); for(i = 0; i < rt->class_count; i++) { JS_MarkValue(rt, ctx->class_proto[i], mark_func); } - JS_MarkValue(rt, ctx->iterator_proto, mark_func); + JS_MarkValue(rt, ctx->iterator_ctor, 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); @@ -2280,15 +2447,17 @@ void JS_FreeContext(JSContext *ctx) if (--ctx->header.ref_count > 0) return; assert(ctx->header.ref_count == 0); - + #ifdef DUMP_ATOMS - JS_DumpAtoms(ctx->rt); + if (check_dump_flag(rt, DUMP_ATOMS)) + JS_DumpAtoms(ctx->rt); #endif #ifdef DUMP_SHAPES - JS_DumpShapes(ctx->rt); + if (check_dump_flag(rt, DUMP_SHAPES)) + JS_DumpShapes(ctx->rt); #endif #ifdef DUMP_OBJECTS - { + if (check_dump_flag(rt, DUMP_OBJECTS)) { struct list_head *el; JSGCObjectHeader *p; printf("JSObjects: {\n"); @@ -2301,7 +2470,7 @@ void JS_FreeContext(JSContext *ctx) } #endif #ifdef DUMP_MEM - { + if (check_dump_flag(rt, DUMP_MEM)) { JSMemoryUsage stats; JS_ComputeMemoryUsage(rt, &stats); JS_DumpMemoryUsage(stdout, &stats, rt); @@ -2320,11 +2489,13 @@ 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_prepare_stack); 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_proto); + JS_FreeValue(ctx, ctx->iterator_ctor); JS_FreeValue(ctx, ctx->async_iterator_proto); JS_FreeValue(ctx, ctx->promise_ctor); JS_FreeValue(ctx, ctx->array_ctor); @@ -2346,11 +2517,15 @@ 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) @@ -2368,22 +2543,9 @@ void JS_UpdateStackTop(JSRuntime *rt) static inline BOOL is_strict_mode(JSContext *ctx) { JSStackFrame *sf = ctx->rt->current_stack_frame; - return (sf && (sf->js_mode & JS_MODE_STRICT)); + return sf && sf->is_strict_mode; } -#ifdef CONFIG_BIGNUM -static inline BOOL is_math_mode(JSContext *ctx) -{ - JSStackFrame *sf = ctx->rt->current_stack_frame; - return (sf && (sf->js_mode & JS_MODE_MATH)); -} -#else -static inline BOOL is_math_mode(JSContext *ctx) -{ - return FALSE; -} -#endif - /* JSAtom support */ #define JS_ATOM_TAG_INT (1U << 31) @@ -2395,11 +2557,7 @@ static inline BOOL is_math_mode(JSContext *ctx) static inline BOOL __JS_AtomIsConst(JSAtom v) { -#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1 - return (int32_t)v <= 0; -#else - return (int32_t)v < JS_ATOM_END; -#endif + return (int32_t)v < JS_ATOM_END; } static inline BOOL __JS_AtomIsTaggedInt(JSAtom v) @@ -2432,10 +2590,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p) len = p->len; if (len == 0 || len > 10) return FALSE; - if (p->is_wide_char) - c = p->u.str16[0]; - else - c = p->u.str8[0]; + c = string_get(p, 0); if (is_num(c)) { if (c == '0') { if (len != 1) @@ -2444,10 +2599,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p) } else { n = c - '0'; for(i = 1; i < len; i++) { - if (p->is_wide_char) - c = p->u.str16[i]; - else - c = p->u.str8[i]; + c = string_get(p, i); if (!is_num(c)) return FALSE; n64 = (uint64_t)n * 10 + (c - '0'); @@ -2501,14 +2653,14 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt, printf(""); return; } - printf("%d", p->header.ref_count); - sep = (p->header.ref_count == 1) ? '\"' : '\''; + if (p->header.ref_count != 1) + printf("%d", p->header.ref_count); + if (p->is_wide_char) + putchar('L'); + sep = '\"'; putchar(sep); for(i = 0; i < p->len; i++) { - if (p->is_wide_char) - c = p->u.str16[i]; - else - c = p->u.str8[i]; + c = string_get(p, i); if (c == sep || c == '\\') { putchar('\\'); putchar(c); @@ -2668,11 +2820,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v) default: abort(); } -} - -static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v) -{ - return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING; + return (JSAtomKindEnum){-1}; // pacify compiler } static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p) @@ -2700,9 +2848,6 @@ 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) { @@ -2828,6 +2973,7 @@ 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++; @@ -2849,7 +2995,8 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) return i; } -/* only works with zero terminated 8 bit strings */ +// XXX: `str` must be pure ASCII. No UTF-8 encoded strings +// XXX: `str` must not be the string representation of a small integer static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, int atom_type) { @@ -2862,6 +3009,7 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, return __JS_NewAtom(rt, p, atom_type); } +// XXX: `str` must be raw 8-bit contents. No UTF-8 encoded strings static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, int atom_type) { @@ -2890,12 +3038,6 @@ 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; @@ -2922,6 +3064,9 @@ 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 DUMP_LEAKS list_del(&p->link); @@ -2956,11 +3101,14 @@ 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 */ 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`. JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING); if (atom) return atom; @@ -2971,6 +3119,7 @@ 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)); @@ -2981,10 +3130,9 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n) if (n <= JS_ATOM_MAX_INT) { return __JS_AtomFromUInt32(n); } else { - char buf[11]; - JSValue val; - snprintf(buf, sizeof(buf), "%u", n); - val = JS_NewString(ctx, buf); + char buf[16]; + size_t len = u32toa(buf, n); + JSValue 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), @@ -2998,9 +3146,8 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) return __JS_AtomFromUInt32((uint32_t)n); } else { char buf[24]; - JSValue val; - snprintf(buf, sizeof(buf), "%" PRId64 , n); - val = JS_NewString(ctx, buf); + size_t len = i64toa(buf, n); + JSValue 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), @@ -3009,7 +3156,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n) } /* 'p' is freed */ -static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type) +static JSValue JS_NewSymbolInternal(JSContext *ctx, JSString *p, int atom_type) { JSRuntime *rt = ctx->rt; JSAtom atom; @@ -3029,8 +3176,17 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr, assert(!__JS_AtomIsTaggedInt(descr)); assert(descr < rt->atom_size); p = rt->atom_array[descr]; - JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); - return JS_NewSymbol(ctx, p, atom_type); + 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, JS_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); } #define ATOM_GET_STR_BUF_SIZE 64 @@ -3041,45 +3197,32 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, { if (__JS_AtomIsTaggedInt(atom)) { snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom)); - } else { - JSAtomStruct *p; + } else if (atom == JS_ATOM_NULL) { + snprintf(buf, buf_size, ""); + } else if (atom >= rt->atom_size) { 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]; + snprintf(buf, buf_size, "", atom); + } else { + JSAtomStruct *p = rt->atom_array[atom]; + *buf = '\0'; + if (atom_is_free(p)) { 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; - } + 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, str->u.str16, str->len); + } else { + /* special case ASCII strings */ + int i, c = 0; for(i = 0; i < str->len; i++) { - if (str->is_wide_char) - c = str->u.str16[i]; - else - c = str->u.str8[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); - } + c |= str->u.str8[i]; } + if (c < 0x80) + return (const char *)str->u.str8; + utf8_encode_buf8(buf, buf_size, str->u.str8, str->len); } - *q = '\0'; } } return buf; @@ -3095,8 +3238,8 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string) char buf[ATOM_GET_STR_BUF_SIZE]; if (__JS_AtomIsTaggedInt(atom)) { - snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom)); - return JS_NewString(ctx, buf); + size_t len = u32toa(buf, __JS_AtomToUInt32(atom)); + return js_new_string8_len(ctx, buf, len); } else { JSRuntime *rt = ctx->rt; JSAtomStruct *p; @@ -3110,9 +3253,9 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string) p = rt->atom_array[JS_ATOM_empty_string]; } ret_string: - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } else { - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p)); + return js_dup(JS_MKPTR(JS_TAG_SYMBOL, p)); } } } @@ -3164,7 +3307,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) JSValue num, str; if (__JS_AtomIsTaggedInt(atom)) - return JS_NewInt32(ctx, __JS_AtomToUInt32(atom)); + return js_int32(__JS_AtomToUInt32(atom)); assert(atom < rt->atom_size); p1 = rt->atom_array[atom]; if (p1->atom_type != JS_ATOM_TYPE_STRING) @@ -3206,7 +3349,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) /* -0 case is specific */ if (c == '0' && len == 2) { minus_zero: - return __JS_NewFloat64(ctx, -0.0); + return js_float64(-0.0); } } if (!is_num(c)) { @@ -3215,8 +3358,6 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) return JS_UNDEFINED; } } - /* XXX: bignum: would be better to only accept integer to avoid - relying on current floating point precision */ /* this is ECMA CanonicalNumericIndexString primitive */ num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p)); if (JS_IsException(num)) @@ -3226,9 +3367,9 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) JS_FreeValue(ctx, num); return str; } - ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str)); + ret = js_string_eq(p, JS_VALUE_GET_STRING(str)); JS_FreeValue(ctx, str); - if (ret == 0) { + if (ret) { return num; } else { JS_FreeValue(ctx, num); @@ -3330,6 +3471,8 @@ const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) } /* 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; @@ -3337,7 +3480,7 @@ static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) const char *cstr; char *cstr2; size_t len, len1; - + str = JS_AtomToString(ctx, name); if (JS_IsException(str)) return JS_ATOM_NULL; @@ -3365,39 +3508,37 @@ static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n) { char buf[16]; - snprintf(buf, sizeof(buf), "%u", n); + u32toa(buf, n); return js_atom_concat_str(ctx, name, buf); } -static inline BOOL JS_IsEmptyString(JSValueConst v) +static inline BOOL JS_IsEmptyString(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0; } /* JSClass support */ -#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) +/* a new class ID is allocated if *pclass_id == 0, otherwise *pclass_id is left unchanged */ +JSClassID JS_NewClassID(JSRuntime *rt, JSClassID *pclass_id) { - JSClassID class_id; -#ifdef CONFIG_ATOMICS - pthread_mutex_lock(&js_class_id_mutex); -#endif - class_id = *pclass_id; + JSClassID class_id = *pclass_id; if (class_id == 0) { - class_id = js_class_id_alloc++; + class_id = rt->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(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; +} + BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id) { return (class_id < rt->class_count && @@ -3460,6 +3601,7 @@ 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) { @@ -3472,13 +3614,11 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def) return ret; } -static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len) +// 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; @@ -3487,7 +3627,14 @@ static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len) return JS_MKPTR(JS_TAG_STRING, str); } -static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len) +// 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) +{ + return js_new_string8_len(ctx, str, strlen(str)); +} + +static JSValue js_new_string16_len(JSContext *ctx, const uint16_t *buf, int len) { JSString *str; str = js_alloc_string(ctx, len, 1); @@ -3500,11 +3647,11 @@ static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len) static JSValue js_new_string_char(JSContext *ctx, uint16_t c) { if (c < 0x100) { - uint8_t ch8 = c; - return js_new_string8(ctx, &ch8, 1); + char ch8 = c; + return js_new_string8_len(ctx, &ch8, 1); } else { uint16_t ch16 = c; - return js_new_string16(ctx, &ch16, 1); + return js_new_string16_len(ctx, &ch16, 1); } } @@ -3512,9 +3659,12 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) { int len = end - start; if (start == 0 && end == p->len) { - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } - if (p->is_wide_char && len > 0) { + if (len <= 0) { + return JS_AtomToString(ctx, JS_ATOM_empty_string); + } + if (p->is_wide_char) { JSString *str; int i; uint16_t c = 0; @@ -3522,7 +3672,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) c |= p->u.str16[i]; } if (c > 0xFF) - return js_new_string16(ctx, p->u.str16 + start, len); + return js_new_string16_len(ctx, p->u.str16 + start, len); str = js_alloc_string(ctx, len, 0); if (!str) @@ -3533,7 +3683,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) str->u.str8[len] = '\0'; return JS_MKPTR(JS_TAG_STRING, str); } else { - return js_new_string8(ctx, p->u.str8 + start, len); + return js_new_string8_len(ctx, (const char *)(p->u.str8 + start), len); } } @@ -3622,7 +3772,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_ThrowInternalError(s->ctx, "string too long"); + JS_ThrowRangeError(s->ctx, "invalid string length"); return string_buffer_set_error(s); } new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX); @@ -3692,28 +3842,23 @@ static int string_buffer_putc(StringBuffer *s, uint32_t c) { if (unlikely(c >= 0x10000)) { /* surrogate pair */ - c -= 0x10000; - if (string_buffer_putc16(s, (c >> 10) + 0xd800)) + if (string_buffer_putc16(s, get_hi_surrogate(c))) return -1; - c = (c & 0x3ff) + 0xdc00; + c = get_lo_surrogate(c); } return string_buffer_putc16(s, c); } -static int string_get(const JSString *p, int idx) { - return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx]; -} - static int string_getc(const JSString *p, int *pidx) { int idx, c, c1; idx = *pidx; if (p->is_wide_char) { c = p->u.str16[idx++]; - if (c >= 0xd800 && c < 0xdc00 && idx < p->len) { + if (is_hi_surrogate(c) && idx < p->len) { c1 = p->u.str16[idx]; - if (c1 >= 0xdc00 && c1 < 0xe000) { - c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; + if (is_lo_surrogate(c1)) { + c = from_surrogate(c, c1); idx++; } } @@ -3787,7 +3932,7 @@ static int string_buffer_concat(StringBuffer *s, const JSString *p, return string_buffer_write8(s, p->u.str8 + from, to - from); } -static int string_buffer_concat_value(StringBuffer *s, JSValueConst v) +static int string_buffer_concat_value(StringBuffer *s, JSValue v) { JSString *p; JSValue v1; @@ -3880,62 +4025,44 @@ 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) { - 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; - p = p_start; - while (p < p_end && *p < 128) - p++; - len1 = p - p_start; - if (len1 > JS_STRING_LEN_MAX) - return JS_ThrowInternalError(ctx, "string too long"); - if (p == p_end) { - /* ASCII string */ - return js_new_string8(ctx, (const uint8_t *)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 */ - c -= 0x10000; - string_buffer_putc16(b, (c >> 10) + 0xd800); - c = (c & 0x3ff) + 0xdc00; - } 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 string_buffer_end(b); + JSString *str; + size_t len; + int kind; - fail: - string_buffer_free(b); - return JS_EXCEPTION; + if (buf_len <= 0) { + return JS_AtomToString(ctx, JS_ATOM_empty_string); + } + /* 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(str->u.str8, buf, len); + str->u.str8[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(str->u.str8, 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(str->u.str16, len, buf, buf_len); + break; + } + return JS_MKPTR(JS_TAG_STRING, str); } static JSValue JS_ConcatString3(JSContext *ctx, const char *str1, @@ -3969,11 +4096,7 @@ static JSValue JS_ConcatString3(JSContext *ctx, const char *str1, return JS_EXCEPTION; } -JSValue JS_NewString(JSContext *ctx, const char *str) -{ - return JS_NewStringLen(ctx, str, strlen(str)); -} - +/* `str` may be pure ASCII or UTF-8 encoded */ JSValue JS_NewAtomString(JSContext *ctx, const char *str) { JSAtom atom = JS_NewAtom(ctx, str); @@ -3987,21 +4110,41 @@ 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, JSValue 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_ToString(ctx, val1); - if (JS_IsException(val)) - goto fail; - } else { - val = JS_DupValue(ctx, val1); + 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; + } + +go: str = JS_VALUE_GET_STRING(val); len = str->len; if (!str->is_wide_char) { @@ -4051,13 +4194,12 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BO if (c < 0x80) { *q++ = c; } else { - if (c >= 0xd800 && c < 0xdc00) { + if (is_hi_surrogate(c)) { if (pos < len && !cesu8) { c1 = src[pos]; - if (c1 >= 0xdc00 && c1 < 0xe000) { + if (is_lo_surrogate(c1)) { pos++; - /* surrogate pair */ - c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; + c = from_surrogate(c, c1); } else { /* Keep unmatched surrogate code points */ /* c = 0xfffd; */ /* error */ @@ -4067,7 +4209,7 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BO /* c = 0xfffd; */ /* error */ } } - q += unicode_to_utf8(q, c); + q += utf8_encode(q, c); } } } @@ -4134,21 +4276,20 @@ static int js_string_memcmp(const JSString *p1, const JSString *p2, int len) return res; } +static BOOL js_string_eq(const JSString *p1, const 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(JSContext *ctx, - const JSString *p1, const JSString *p2) +static int js_string_compare(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) { - if (p1->len == p2->len) - res = 0; - else if (p1->len < p2->len) - res = -1; - else - res = 1; - } + if (res == 0) + res = compare_u32(p1->len, p2->len); return res; } @@ -4174,7 +4315,7 @@ static JSValue JS_ConcatString1(JSContext *ctx, len = p1->len + p2->len; if (len > JS_STRING_LEN_MAX) - return JS_ThrowInternalError(ctx, "string too long"); + return JS_ThrowRangeError(ctx, "invalid string length"); is_wide_char = p1->is_wide_char | p2->is_wide_char; p = js_alloc_string(ctx, len, is_wide_char); if (!p) @@ -4368,7 +4509,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_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto)); + js_dup(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); @@ -4376,7 +4517,7 @@ 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; - + /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = TRUE; @@ -4413,7 +4554,7 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); sh->is_hashed = FALSE; if (sh->proto) { - JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); + js_dup(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); @@ -4469,7 +4610,6 @@ 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); @@ -4485,21 +4625,19 @@ 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, @@ -4511,12 +4649,20 @@ 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 { - /* 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); + /* 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); } - js_free(ctx, get_alloc_from_shape(old_sh)); *psh = sh; sh->prop_size = new_size; return 0; @@ -4531,7 +4677,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) uint32_t new_hash_size, i, j, new_hash_mask, new_size; JSShapeProperty *old_pr, *pr; JSProperty *prop, *new_prop; - + sh = p->shape; assert(!sh->is_hashed); @@ -4553,7 +4699,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) list_del(&old_sh->header.link); memcpy(sh, old_sh, sizeof(JSShape)); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); - + memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); @@ -4582,7 +4728,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) p->shape = sh; js_free(ctx, get_alloc_from_shape(old_sh)); - + /* reduce the size of the object properties */ new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size); if (new_prop) @@ -4709,7 +4855,7 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt) struct list_head *el; JSObject *p; JSGCObjectHeader *gp; - + printf("JSShapes: {\n"); printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS"); for(i = 0; i < rt->shape_hash_size; i++) { @@ -4779,7 +4925,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_NewInt32(ctx, 0); + pr->u.value = js_int32(0); } break; case JS_CLASS_C_FUNCTION: @@ -4795,6 +4941,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas case JS_CLASS_UINT32_ARRAY: case JS_CLASS_BIG_INT64_ARRAY: case JS_CLASS_BIG_UINT64_ARRAY: + case JS_CLASS_FLOAT16_ARRAY: case JS_CLASS_FLOAT32_ARRAY: case JS_CLASS_FLOAT64_ARRAY: p->is_exotic = 1; @@ -4812,10 +4959,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas case JS_CLASS_SYMBOL: case JS_CLASS_DATE: case JS_CLASS_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_CLASS_BIG_FLOAT: - case JS_CLASS_BIG_DECIMAL: -#endif p->u.object_data = JS_UNDEFINED; goto set_exotic; case JS_CLASS_REGEXP: @@ -4834,7 +4977,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas return JS_MKPTR(JS_TAG_OBJECT, p); } -static JSObject *get_proto_obj(JSValueConst proto_val) +static JSObject *get_proto_obj(JSValue proto_val) { if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) return NULL; @@ -4843,7 +4986,7 @@ static JSObject *get_proto_obj(JSValueConst proto_val) } /* WARNING: proto must be an object or JS_NULL */ -JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, +JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValue proto_val, JSClassID class_id) { JSShape *sh; @@ -4861,8 +5004,7 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, return JS_NewObjectFromShape(ctx, sh, class_id); } -#if 0 -static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj) +static int JS_SetObjectData(JSContext *ctx, JSValue obj, JSValue val) { JSObject *p; @@ -4875,34 +5017,6 @@ static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj) case JS_CLASS_SYMBOL: case JS_CLASS_DATE: case JS_CLASS_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_CLASS_BIG_FLOAT: - case JS_CLASS_BIG_DECIMAL: -#endif - return JS_DupValue(ctx, p->u.object_data); - } - } - return JS_UNDEFINED; -} -#endif - -static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) -{ - 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: -#ifdef CONFIG_BIGNUM - case JS_CLASS_BIG_FLOAT: - case JS_CLASS_BIG_DECIMAL: -#endif JS_FreeValue(ctx, p->u.object_data); p->u.object_data = val; return 0; @@ -4919,7 +5033,7 @@ JSValue JS_NewObjectClass(JSContext *ctx, int class_id) return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id); } -JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto) +JSValue JS_NewObjectProto(JSContext *ctx, JSValue proto) { return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT); } @@ -4936,11 +5050,11 @@ JSValue JS_NewObject(JSContext *ctx) return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT); } -static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj, +static void js_function_set_properties(JSContext *ctx, JSValue 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_NewInt32(ctx, len), + JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, js_int32(len), JS_PROP_CONFIGURABLE); JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE); @@ -4955,7 +5069,7 @@ static BOOL js_class_has_bytecode(JSClassID class_id) } /* return NULL without exception if not a function or no bytecode */ -static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val) +static JSFunctionBytecode *JS_GetFunctionBytecode(JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -4966,8 +5080,8 @@ static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val) return p->u.func.function_bytecode; } -static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj, - JSValueConst home_obj) +static void js_method_set_home_object(JSContext *ctx, JSValue func_obj, + JSValue home_obj) { JSObject *p, *p1; JSFunctionBytecode *b; @@ -4984,7 +5098,7 @@ static void js_method_set_home_object(JSContext *ctx, JSValueConst 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_DupValue(ctx, home_obj)); + p1 = JS_VALUE_GET_OBJ(js_dup(home_obj)); else p1 = NULL; p->u.func.home_object = p1; @@ -5006,8 +5120,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, JSValueConst func_obj, - JSAtom name, int flags, JSValueConst home_obj) +static int js_method_set_properties(JSContext *ctx, JSValue func_obj, + JSAtom name, int flags, JSValue home_obj) { JSValue name_str; @@ -5027,15 +5141,16 @@ static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj, } /* Note: at least 'length' arguments will be readable in 'argv' */ +/* `name` may be NULL, pure ASCII or UTF-8 encoded */ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val) + JSValue proto_val) { JSValue func_obj; JSObject *p; JSAtom name_atom; - + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); if (JS_IsException(func_obj)) return func_obj; @@ -5071,7 +5186,7 @@ typedef struct JSCFunctionDataRecord { uint8_t length; uint8_t data_len; uint16_t magic; - JSValue data[0]; + JSValue data[]; } JSCFunctionDataRecord; static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val) @@ -5087,7 +5202,7 @@ static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val) } } -static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, +static void js_c_function_data_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); @@ -5100,12 +5215,12 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, } } -static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_val, - int argc, JSValueConst *argv, int flags) +static JSValue js_c_function_data_call(JSContext *ctx, JSValue func_obj, + JSValue this_val, + int argc, JSValue *argv, int flags) { JSCFunctionDataRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA); - JSValueConst *arg_buf; + JSValue *arg_buf; int i; /* XXX: could add the function on the stack for debug */ @@ -5124,7 +5239,7 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, int length, int magic, int data_len, - JSValueConst *data) + JSValue *data) { JSCFunctionDataRecord *s; JSValue func_obj; @@ -5144,8 +5259,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_DupValue(ctx, data[i]); - JS_SetOpaque(func_obj, s); + s->data[i] = js_dup(data[i]); + JS_SetOpaqueInternal(func_obj, s); js_function_set_properties(ctx, func_obj, JS_ATOM_empty_string, length); return func_obj; @@ -5234,8 +5349,33 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, return NULL; } +static force_inline JSShapeProperty* find_own_property_ic(JSProperty** ppr, JSObject* p, + JSAtom atom, uint32_t* offset) +{ + JSShape* sh; + JSShapeProperty *pr, *prop; + intptr_t h, i; + sh = p->shape; + h = (uintptr_t)atom & sh->prop_hash_mask; + h = prop_hash_end(sh)[-h - 1]; + prop = get_shape_prop(sh); + while (h) { + i = h - 1; + pr = &prop[i]; + if (likely(pr->atom == atom)) { + *ppr = &p->prop[i]; + *offset = i; + /* the compiler should be able to assume that pr != NULL here */ + return pr; + } + h = pr->hash_next; + } + *ppr = NULL; + 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 set_cycle_flag(JSContext *ctx, JSValue obj) { } @@ -5246,12 +5386,10 @@ 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->var_ref_link); /* still on the stack */ - if (var_ref->async_func) - async_func_free(rt, var_ref->async_func); + list_del(&var_ref->header.link); /* still on the stack */ } - remove_gc_object(&var_ref->header); js_free_rt(rt, var_ref); } } @@ -5268,7 +5406,7 @@ static void js_array_finalizer(JSRuntime *rt, JSValue val) js_free_rt(rt, p->u.array.u.values); } -static void js_array_mark(JSRuntime *rt, JSValueConst val, +static void js_array_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5286,7 +5424,7 @@ static void js_object_data_finalizer(JSRuntime *rt, JSValue val) p->u.object_data = JS_UNDEFINED; } -static void js_object_data_mark(JSRuntime *rt, JSValueConst val, +static void js_object_data_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5301,7 +5439,7 @@ static void js_c_function_finalizer(JSRuntime *rt, JSValue val) JS_FreeContext(p->u.cfunc.realm); } -static void js_c_function_mark(JSRuntime *rt, JSValueConst val, +static void js_c_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5333,7 +5471,7 @@ static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val) } } -static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, +static void js_bytecode_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5349,7 +5487,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) { + if (var_ref && var_ref->is_detached) { mark_func(rt, &var_ref->header); } } @@ -5374,7 +5512,7 @@ static void js_bound_function_finalizer(JSRuntime *rt, JSValue val) js_free_rt(rt, bf); } -static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, +static void js_bound_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5391,19 +5529,11 @@ 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); } -static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_for_in_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -5437,7 +5567,7 @@ static void free_object(JSRuntime *rt, JSObject *p) p->prop = NULL; if (unlikely(p->first_weak_ref)) { - reset_weak_ref(rt, p); + reset_weak_ref(rt, &p->first_weak_ref); } finalizer = rt->class_array[p->class_id].finalizer; @@ -5467,9 +5597,6 @@ 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; default: abort(); } @@ -5479,7 +5606,7 @@ static void free_zero_refcount(JSRuntime *rt) { struct list_head *el; JSGCObjectHeader *p; - + rt->gc_phase = JS_GC_PHASE_DECREF; for(;;) { el = rt->gc_zero_ref_count_list.next; @@ -5493,18 +5620,22 @@ static void free_zero_refcount(JSRuntime *rt) } /* called with the ref_count of 'v' reaches zero. */ -void __JS_FreeValueRT(JSRuntime *rt, JSValue v) +static void js_free_value_rt(JSRuntime *rt, JSValue v) { uint32_t tag = JS_VALUE_GET_TAG(v); #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"); + if (check_dump_flag(rt, 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"); + } } } #endif @@ -5540,24 +5671,12 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v) abort(); /* never freed here */ break; case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { - JSBigFloat *bf = JS_VALUE_GET_PTR(v); + JSBigInt *bf = JS_VALUE_GET_PTR(v); bf_delete(&bf->num); js_free_rt(rt, bf); } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_DECIMAL: - { - JSBigDecimal *bf = JS_VALUE_GET_PTR(v); - bfdec_delete(&bf->num); - js_free_rt(rt, bf); - } - break; -#endif case JS_TAG_SYMBOL: { JSAtomStruct *p = JS_VALUE_GET_PTR(v); @@ -5565,14 +5684,24 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v) } break; default: - printf("__JS_FreeValue: unknown tag=%d\n", tag); + printf("js_free_value_rt: unknown tag=%d\n", tag); abort(); } } -void __JS_FreeValue(JSContext *ctx, JSValue v) +void JS_FreeValueRT(JSRuntime *rt, JSValue v) { - __JS_FreeValueRT(ctx->rt, 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); + } + } +} + +void JS_FreeValue(JSContext *ctx, JSValue v) +{ + JS_FreeValueRT(ctx->rt, v); } /* garbage collection */ @@ -5590,7 +5719,7 @@ static void remove_gc_object(JSGCObjectHeader *h) list_del(&h->link); } -void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) +void JS_MarkValue(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { if (JS_VALUE_HAS_REF_COUNT(val)) { switch(JS_VALUE_GET_TAG(val)) { @@ -5628,9 +5757,11 @@ 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) { - /* Note: the tag does not matter - provided it is a GC object */ - mark_func(rt, &pr->u.var_ref->header); + 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); + } } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { js_autoinit_mark(rt, pr, mark_func); } @@ -5652,6 +5783,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: /* the template objects can be part of a cycle */ { + JSShape **shape, *(*shapes)[IC_CACHE_ITEM_CAPACITY]; JSFunctionBytecode *b = (JSFunctionBytecode *)gp; int i; for(i = 0; i < b->cpool_count; i++) { @@ -5659,37 +5791,29 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, } if (b->realm) mark_func(rt, &b->realm->header); + if (b->ic) { + for (i = 0; i < b->ic->count; i++) { + shapes = &b->ic->cache[i].shape; + for (shape = *shapes; shape != endof(*shapes); shape++) + if (*shape) + mark_func(rt, &(*shape)->header); + } + } } break; case JS_GC_OBJ_TYPE_VAR_REF: { JSVarRef *var_ref = (JSVarRef *)gp; - 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); - } + /* only detached variable referenced are taken into account */ + assert(var_ref->is_detached); + JS_MarkValue(rt, *var_ref->pvalue, mark_func); } break; case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: { - 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); - } - } + JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp; + if (s->is_active) + async_func_mark(rt, &s->func_state, mark_func); JS_MarkValue(rt, s->resolving_funcs[0], mark_func); JS_MarkValue(rt, s->resolving_funcs[1], mark_func); } @@ -5727,7 +5851,7 @@ static void gc_decref(JSRuntime *rt) { struct list_head *el, *el1; JSGCObjectHeader *p; - + init_list_head(&rt->tmp_obj_list); /* decrement the refcount of all the children of all the GC @@ -5774,7 +5898,7 @@ static void gc_scan(JSRuntime *rt) p->mark = 0; /* reset the mark for the next GC call */ mark_children(rt, p, gc_scan_incref_child); } - + /* restore the refcount of the objects to be deleted. */ list_for_each(el, &rt->tmp_obj_list) { p = list_entry(el, JSGCObjectHeader, link); @@ -5797,20 +5921,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 - or async functions. The rest will be automatically removed - because they must be referenced by them. */ + /* Only need to free the GC object associated with JS + values. 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: - case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: #ifdef DUMP_GC_FREE - if (!header_done) { - printf("Freeing cycles:\n"); - JS_DumpObjectHeader(rt); - header_done = TRUE; + if (check_dump_flag(rt, DUMP_GC_FREE)) { + if (!header_done) { + printf("Freeing cycles:\n"); + JS_DumpObjectHeader(rt); + header_done = TRUE; + } + JS_DumpGCObject(rt, p); } - JS_DumpGCObject(rt, p); #endif free_gc_object(rt, p); break; @@ -5821,12 +5946,11 @@ static void gc_free_cycles(JSRuntime *rt) } } rt->gc_phase = JS_GC_PHASE_NONE; - + 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 || - p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION); + p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); js_free_rt(rt, p); } @@ -5849,7 +5973,7 @@ void JS_RunGC(JSRuntime *rt) /* 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, JSValue obj) { JSObject *p; if (!JS_IsObject(obj)) @@ -5871,7 +5995,7 @@ typedef struct JSMemoryUsage_helper { int64_t js_func_pc2line_size; } JSMemoryUsage_helper; -static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp); +static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp); static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp) { @@ -5888,52 +6012,43 @@ 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 = offsetof(JSFunctionBytecode, debug); + js_func_size = sizeof(*b); 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++) { - JSValueConst val = b->cpool[i]; + JSValue 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->read_only_bytecode && b->byte_code_buf) { + if (b->byte_code_buf) { hp->js_func_code_size += b->byte_code_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; - } + 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; } hp->js_func_size += js_func_size; hp->js_func_count += 1; hp->memory_used_count += memory_used_count; } -static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp) +static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp) { switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_STRING: compute_jsstring_size(JS_VALUE_GET_STRING(val), hp); break; case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - case JS_TAG_BIG_DECIMAL: -#endif - /* should track JSBigFloat usage */ + /* should track JSBigInt usage */ break; } } @@ -5950,7 +6065,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(JSValue) * rt->class_count; + s->memory_used_size = sizeof(JSRuntime) + sizeof(JSClass) * rt->class_count; list_for_each(el, &rt->context_list) { JSContext *ctx = list_entry(el, JSContext, link); @@ -6059,10 +6174,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) case JS_CLASS_SYMBOL: /* u.object_data */ case JS_CLASS_DATE: /* u.object_data */ case JS_CLASS_BIG_INT: /* u.object_data */ -#ifdef CONFIG_BIGNUM - case JS_CLASS_BIG_FLOAT: /* u.object_data */ - case JS_CLASS_BIG_DECIMAL: /* u.object_data */ -#endif compute_value_size(p->u.object_data, hp); break; case JS_CLASS_C_FUNCTION: /* u.cfunc */ @@ -6153,12 +6264,10 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */ + case JS_CLASS_FLOAT16_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */ case JS_CLASS_DATAVIEW: /* u.typed_array */ -#ifdef CONFIG_BIGNUM - case JS_CLASS_FLOAT_ENV: /* u.float_env */ -#endif case JS_CLASS_MAP: /* u.map_state */ case JS_CLASS_SET: /* u.map_state */ case JS_CLASS_WEAKMAP: /* u.map_state */ @@ -6228,13 +6337,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) { - fprintf(fp, "QuickJS memory usage -- " -#ifdef CONFIG_BIGNUM - "BigNum " -#endif - CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n", - (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit); -#if 1 + 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); if (rt) { static const struct { const char *name; @@ -6279,10 +6383,10 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) if (obj_classes[0]) fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none"); for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) { - if (obj_classes[class_id] && class_id < rt->class_count) { + if (obj_classes[class_id]) { char buf[ATOM_GET_STR_BUF_SIZE]; fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id, - JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name)); + JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name)); } } if (obj_classes[JS_CLASS_INIT_COUNT]) @@ -6290,7 +6394,6 @@ 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) { @@ -6357,7 +6460,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) JSValue JS_GetGlobalObject(JSContext *ctx) { - return JS_DupValue(ctx, ctx->global_obj); + return js_dup(ctx->global_obj); } /* WARNING: obj is freed */ @@ -6375,10 +6478,15 @@ JSValue JS_GetException(JSContext *ctx) JSValue val; JSRuntime *rt = ctx->rt; val = rt->current_exception; - rt->current_exception = JS_NULL; + rt->current_exception = JS_UNINITIALIZED; return val; } +JS_BOOL JS_HasException(JSContext *ctx) +{ + return !JS_IsUninitialized(ctx->rt->current_exception); +} + static void dbuf_put_leb128(DynBuf *s, uint32_t v) { uint32_t a; @@ -6435,21 +6543,20 @@ static int get_sleb128(int32_t *pval, const uint8_t *buf, } static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, - uint32_t pc_value) + uint32_t pc_value, int *col) { const uint8_t *p_end, *p; - int new_line_num, line_num, pc, v, ret; + int new_line_num, new_col_num, line_num, col_num, pc, v, ret; unsigned int op; - if (!b->has_debug || !b->debug.pc2line_buf) { - /* function was stripped */ - return -1; - } - - p = b->debug.pc2line_buf; - p_end = p + b->debug.pc2line_len; + *col = 1; + p = b->pc2line_buf; + if (!p) + goto fail; + p_end = p + b->pc2line_len; pc = 0; - line_num = b->debug.line_num; + line_num = b->line_num; + col_num = b->col_num; while (p < p_end) { op = *p++; if (op == 0) { @@ -6460,11 +6567,8 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, pc += val; p += ret; ret = get_sleb128(&v, p, p_end); - if (ret < 0) { - fail: - /* should never happen */ - return b->debug.line_num; - } + if (ret < 0) + goto fail; p += ret; new_line_num = line_num + v; } else { @@ -6472,22 +6576,32 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, 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_col_num = col_num + v; if (pc_value < pc) - return line_num; + break; line_num = new_line_num; + col_num = new_col_num; } + *col = col_num; return line_num; +fail: + /* should never happen */ + return b->line_num; } /* 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) +static const char *get_func_name(JSContext *ctx, JSValue func) { JSProperty *pr; JSShapeProperty *prs; - JSValueConst val; - + JSValue 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); @@ -6504,89 +6618,181 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func) #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_obj, - const char *filename, int line_num, +static void build_backtrace(JSContext *ctx, JSValue error_obj, JSValue filter_func, + const char *filename, int line_num, int col_num, int backtrace_flags) { - JSStackFrame *sf; - JSValue str; + JSStackFrame *sf, *sf_start; + JSValue stack, prepare, saved_exception; DynBuf dbuf; const char *func_name_str; const char *str1; JSObject *p; - BOOL backtrace_barrier; - - js_dbuf_init(ctx, &dbuf); - if (filename) { - dbuf_printf(&dbuf, " at %s", filename); - if (line_num != -1) - dbuf_printf(&dbuf, ":%d", line_num); - dbuf_putc(&dbuf, '\n'); - str = JS_NewString(ctx, filename); - JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL) - goto done; + JSFunctionBytecode *b; + BOOL backtrace_barrier, has_prepare; + JSRuntime *rt; + JSCallSiteData csd[64]; + uint32_t i; + int stack_trace_limit; + + stack_trace_limit = ctx->error_stack_trace_limit; + stack_trace_limit = min_int(stack_trace_limit, countof(csd)); + stack_trace_limit = max_int(stack_trace_limit, 0); + rt = ctx->rt; + has_prepare = FALSE; + i = 0; + + if (!rt->in_prepare_stack_trace && !JS_IsNull(ctx->error_ctor)) { + prepare = js_dup(ctx->error_prepare_stack); + has_prepare = JS_IsFunction(ctx, prepare); + rt->in_prepare_stack_trace = TRUE; } - for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) { + + if (has_prepare) { + saved_exception = rt->current_exception; + rt->current_exception = JS_NULL; + 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 (backtrace_flags & JS_BACKTRACE_FLAG_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; + } + } + } + + for (sf = sf_start; sf != NULL && i < stack_trace_limit; sf = sf->prev_frame) { if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) { backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL; continue; } - 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); p = JS_VALUE_GET_OBJ(sf->cur_func); + b = NULL; backtrace_barrier = FALSE; - if (js_class_has_bytecode(p->class_id)) { - JSFunctionBytecode *b; - const char *atom_str; - int line_num1; + if (js_class_has_bytecode(p->class_id)) { b = p->u.func.function_bytecode; backtrace_barrier = b->backtrace_barrier; - if (b->has_debug) { + } + + 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) { + const char *atom_str; + int line_num1, col_num1; + + /* Bytecode functions must have cur_pc set in the stack frame. */ + if (sf->cur_pc == NULL) + abort(); + line_num1 = find_line_num(ctx, b, - sf->cur_pc - b->byte_code_buf - 1); - atom_str = JS_AtomToCString(ctx, b->debug.filename); - dbuf_printf(&dbuf, " (%s", - atom_str ? atom_str : ""); + sf->cur_pc - b->byte_code_buf - 1, + &col_num1); + atom_str = b->filename ? JS_AtomToCString(ctx, b->filename) : NULL; + dbuf_printf(&dbuf, " (%s", atom_str ? atom_str : ""); JS_FreeCString(ctx, atom_str); if (line_num1 != -1) - dbuf_printf(&dbuf, ":%d", line_num1); + dbuf_printf(&dbuf, ":%d:%d", line_num1, col_num1); dbuf_putc(&dbuf, ')'); + } else { + dbuf_printf(&dbuf, " (native)"); } - } else { - dbuf_printf(&dbuf, " (native)"); + dbuf_putc(&dbuf, '\n'); } - dbuf_putc(&dbuf, '\n'); + i++; + /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */ if (backtrace_barrier) break; } done: - 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); + 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); + } + JSValue args[] = { + error_obj, + 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_FreeValue(ctx, rt->current_exception); + rt->current_exception = saved_exception; + } else { + if (dbuf_error(&dbuf)) + stack = JS_NULL; + else + stack = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); + dbuf_free(&dbuf); + } + + rt->in_prepare_stack_trace = FALSE; + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, stack, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } /* Note: it is important that no exception is returned by this function */ -static BOOL is_backtrace_needed(JSContext *ctx, JSValueConst obj) +static BOOL is_backtrace_needed(JSContext *ctx, JSValue obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) @@ -6604,28 +6810,45 @@ JSValue JS_NewError(JSContext *ctx) return JS_NewObjectClass(ctx, JS_CLASS_ERROR); } +static JSValue JS_MakeError(JSContext *ctx, JSErrorEnum error_num, + const char *message, BOOL add_backtrace) +{ + JSValue obj, msg; + + if (error_num == JS_PLAIN_ERROR) { + obj = JS_NewError(ctx); + } 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; +} + +/* fmt and arguments may be pure ASCII or UTF-8 encoded contents */ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num, const char *fmt, va_list ap, BOOL add_backtrace) { char buf[256]; - JSValue obj, ret; + JSValue obj; vsnprintf(buf, sizeof(buf), fmt, ap); - obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num], - JS_CLASS_ERROR); + obj = JS_MakeError(ctx, error_num, buf, add_backtrace); 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); - } - ret = JS_Throw(ctx, obj); - return ret; + return JS_Throw(ctx, obj); } static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, @@ -6642,6 +6865,17 @@ static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num, return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace); } +JSValue __attribute__((format(printf, 2, 3))) JS_ThrowPlainError(JSContext *ctx, const char *fmt, ...) +{ + JSValue val; + va_list ap; + + va_start(ap, fmt); + val = JS_ThrowError(ctx, JS_PLAIN_ERROR, fmt, ap); + va_end(ap); + return val; +} + JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...) { JSValue val; @@ -6757,7 +6991,7 @@ JSValue JS_ThrowOutOfMemory(JSContext *ctx) static JSValue JS_ThrowStackOverflow(JSContext *ctx) { - return JS_ThrowInternalError(ctx, "stack overflow"); + return JS_ThrowRangeError(ctx, "Maximum call stack size exceeded"); } static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx) @@ -6773,7 +7007,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)); } @@ -6833,8 +7067,8 @@ static inline __exception int js_poll_interrupts(JSContext *ctx) } /* return -1 (exception) or TRUE/FALSE */ -static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, - JSValueConst proto_val, +static int JS_SetPrototypeInternal(JSContext *ctx, JSValue obj, + JSValue proto_val, BOOL throw_flag) { JSObject *proto, *p, *p1; @@ -6868,6 +7102,13 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, sh = p->shape; if (sh->proto == proto) return TRUE; + if (p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) { + if (throw_flag) { + JS_ThrowTypeError(ctx, "'Immutable prototype object \'Object.prototype\' cannot have their prototype set'"); + return -1; + } + return FALSE; + } if (!p->extensible) { if (throw_flag) { JS_ThrowTypeError(ctx, "object is not extensible"); @@ -6891,7 +7132,7 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, /* Note: for Proxy objects, proto is NULL */ p1 = p1->shape->proto; } while (p1 != NULL); - JS_DupValue(ctx, proto_val); + js_dup(proto_val); } if (js_shape_prepare_update(ctx, p, NULL)) @@ -6904,26 +7145,18 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, } /* return -1 (exception) or TRUE/FALSE */ -int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val) +int JS_SetPrototype(JSContext *ctx, JSValue obj, JSValue proto_val) { 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) +static JSValue JS_GetPrototypePrimitive(JSContext *ctx, JSValue val) { switch(JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_BIG_INT: val = ctx->class_proto[JS_CLASS_BIG_INT]; break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - val = ctx->class_proto[JS_CLASS_BIG_FLOAT]; - break; - case JS_TAG_BIG_DECIMAL: - val = ctx->class_proto[JS_CLASS_BIG_DECIMAL]; - break; -#endif case JS_TAG_INT: case JS_TAG_FLOAT64: val = ctx->class_proto[JS_CLASS_NUMBER]; @@ -6948,7 +7181,7 @@ static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val) } /* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */ -JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) +JSValue JS_GetPrototype(JSContext *ctx, JSValue obj) { JSValue val; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { @@ -6961,10 +7194,10 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) if (!p) val = JS_NULL; else - val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + val = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); } } else { - val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj)); + val = js_dup(JS_GetPrototypePrimitive(ctx, obj)); } return val; } @@ -6977,9 +7210,17 @@ static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj) return obj1; } +int JS_GetLength(JSContext *ctx, JSValue obj, int64_t *pres) { + return js_get_length64(ctx, pres, obj); +} + +int JS_SetLength(JSContext *ctx, JSValue obj, int64_t len) { + return js_set_length64(ctx, obj, len); +} + /* return TRUE, FALSE or (-1) in case of exception */ -static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, - JSValueConst obj) +static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValue val, + JSValue obj) { JSValue obj_proto; JSObject *proto; @@ -7012,7 +7253,7 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, /* slow case if proxy in the prototype chain */ if (unlikely(p->class_id == JS_CLASS_PROXY)) { JSValue obj1; - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); for(;;) { obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsException(obj1)) { @@ -7052,7 +7293,7 @@ done: } /* return TRUE, FALSE or (-1) in case of exception */ -int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) +int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj) { JSValue method; @@ -7109,15 +7350,17 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, return 0; } -JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValueConst this_obj, - BOOL throw_ref_error) +static JSValue JS_GetPropertyInternal2(JSContext *ctx, JSValue obj, + JSAtom prop, JSValue this_obj, + JSInlineCacheUpdate *icu, + BOOL throw_ref_error) { JSObject *p; JSProperty *pr; JSShapeProperty *prs; - uint32_t tag; + uint32_t tag, offset, proto_depth; + offset = proto_depth = 0; tag = JS_VALUE_GET_TAG(obj); if (unlikely(tag != JS_TAG_OBJECT)) { switch(tag) { @@ -7134,14 +7377,11 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, uint32_t idx, ch; idx = __JS_AtomToUInt32(prop); if (idx < p1->len) { - if (p1->is_wide_char) - ch = p1->u.str16[idx]; - else - ch = p1->u.str8[idx]; + ch = string_get(p1, idx); return js_new_string_char(ctx, ch); } } else if (prop == JS_ATOM_length) { - return JS_NewInt32(ctx, p1->len); + return js_int32(p1->len); } } break; @@ -7157,7 +7397,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } for(;;) { - prs = find_own_property(&pr, p, prop); + prs = find_own_property_ic(&pr, p, prop, &offset); if (prs) { /* found */ if (unlikely(prs->flags & JS_PROP_TMASK)) { @@ -7167,14 +7407,14 @@ 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_DupValue(ctx, func); + func = js_dup(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_DupValue(ctx, val); + return js_dup(val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) @@ -7182,7 +7422,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, continue; } } else { - return JS_DupValue(ctx, pr->u.value); + if (proto_depth == 0) + add_ic_slot(ctx, icu, prop, p, offset); + return js_dup(pr->u.value); } } if (unlikely(p->is_exotic)) { @@ -7215,7 +7457,7 @@ 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_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); retval = em->get_property(ctx, obj1, prop, this_obj); JS_FreeValue(ctx, obj1); return retval; @@ -7227,7 +7469,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, /* Note: if 'p' is a prototype, it can be freed in the called function */ - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); if (ret < 0) @@ -7244,6 +7486,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } } + proto_depth++; p = p->shape->proto; if (!p) break; @@ -7255,6 +7498,36 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } +static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValue obj, + JSAtom prop, JSValue this_obj, + BOOL throw_ref_error) +{ + return JS_GetPropertyInternal2(ctx, obj, prop, this_obj, NULL, throw_ref_error); +} + +JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop) +{ + return JS_GetPropertyInternal2(ctx, this_obj, prop, this_obj, NULL, FALSE); +} + +static JSValue JS_GetPropertyInternalWithIC(JSContext *ctx, JSValue obj, + JSAtom prop, JSValue this_obj, + JSInlineCacheUpdate *icu, + BOOL throw_ref_error) +{ + uint32_t tag, offset; + JSObject *p; + tag = JS_VALUE_GET_TAG(obj); + if (unlikely(tag != JS_TAG_OBJECT)) + goto slow_path; + p = JS_VALUE_GET_OBJ(obj); + offset = get_ic_prop_offset(icu, p->shape); + if (likely(offset != INLINE_CACHE_MISS)) + return js_dup(p->prop[offset].u.value); +slow_path: + return JS_GetPropertyInternal2(ctx, obj, prop, this_obj, icu, throw_ref_error); +} + static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) { return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist", @@ -7263,8 +7536,8 @@ 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, - JSValueConst name, JSValue val) +static int JS_DefinePrivateField(JSContext *ctx, JSValue obj, + JSValue name, JSValue val) { JSObject *p; JSShapeProperty *prs; @@ -7280,7 +7553,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, name); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (prs) { @@ -7298,8 +7571,8 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, return 0; } -static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj, - JSValueConst name) +static JSValue JS_GetPrivateField(JSContext *ctx, JSValue obj, + JSValue name) { JSObject *p; JSShapeProperty *prs; @@ -7311,18 +7584,18 @@ 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, 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_DupValue(ctx, pr->u.value); + return js_dup(pr->u.value); } -static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, - JSValueConst name, JSValue val) +static int JS_SetPrivateField(JSContext *ctx, JSValue obj, + JSValue name, JSValue val) { JSObject *p; JSShapeProperty *prs; @@ -7338,7 +7611,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, name); p = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p, prop); if (!prs) { @@ -7353,14 +7626,14 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, /* add a private brand field to 'home_obj' if not already present and if obj is != null add a private brand to it */ -static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) +static int JS_AddBrand(JSContext *ctx, JSValue obj, JSValue home_obj) { JSObject *p, *p1; JSShapeProperty *prs; JSProperty *pr; JSValue brand; JSAtom brand_atom; - + if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; @@ -7377,12 +7650,12 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) JS_FreeValue(ctx, brand); return -1; } - pr->u.value = JS_DupValue(ctx, brand); + pr->u.value = js_dup(brand); } else { - brand = JS_DupValue(ctx, pr->u.value); + brand = js_dup(pr->u.value); } brand_atom = js_symbol_to_atom(ctx, brand); - + if (JS_IsObject(obj)) { p1 = JS_VALUE_GET_OBJ(obj); prs = find_own_property(&pr, p1, brand_atom); @@ -7399,18 +7672,19 @@ 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, JSValueConst obj, JSValueConst func) +static int JS_CheckBrand(JSContext *ctx, JSValue obj, JSValue func) { JSObject *p, *p1, *home_obj; JSShapeProperty *prs; JSProperty *pr; - JSValueConst brand; - + JSValue brand; + /* get the home object of 'func' */ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) goto not_obj; @@ -7429,7 +7703,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) /* safety check */ if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL)) goto not_obj; - + /* get the brand array of 'obj' */ if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { not_obj: @@ -7437,12 +7711,12 @@ 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, brand)); return (prs != NULL); } static uint32_t js_string_obj_get_length(JSContext *ctx, - JSValueConst obj) + JSValue obj) { JSObject *p; JSString *p1; @@ -7503,7 +7777,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, BOOL is_enumerable, num_sorted; uint32_t num_key; JSAtomKindEnum kind; - + /* clear pointer for consistency in case of failure */ *ptab = NULL; *plen = 0; @@ -7680,7 +7954,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, } int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, JSValueConst obj, int flags) + uint32_t *plen, JSValue obj, int flags) { if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); @@ -7711,16 +7985,16 @@ retry: if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { desc->flags |= JS_PROP_GETSET; if (pr->u.getset.getter) - desc->getter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); + desc->getter = js_dup(JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter)); if (pr->u.getset.setter) - desc->setter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter)); + desc->setter = js_dup(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_DupValue(ctx, val); + desc->value = js_dup(val); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { /* Instantiate property and retry */ if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) @@ -7728,7 +8002,7 @@ retry: goto retry; } } else { - desc->value = JS_DupValue(ctx, pr->u.value); + desc->value = js_dup(pr->u.value); } } else { /* for consistency, send the exception even if desc is NULL */ @@ -7772,7 +8046,7 @@ retry: } int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop) + JSValue obj, JSAtom prop) { if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); @@ -7781,8 +8055,14 @@ 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 */ -int JS_IsExtensible(JSContext *ctx, JSValueConst obj) +int JS_IsExtensible(JSContext *ctx, JSValue obj) { JSObject *p; @@ -7796,7 +8076,7 @@ int JS_IsExtensible(JSContext *ctx, JSValueConst obj) } /* return -1 if exception (Proxy object only) or TRUE/FALSE */ -int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) +int JS_PreventExtensions(JSContext *ctx, JSValue obj) { JSObject *p; @@ -7810,7 +8090,7 @@ int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) } /* return -1 if exception otherwise TRUE or FALSE */ -int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) +int JS_HasProperty(JSContext *ctx, JSValue obj, JSAtom prop) { JSObject *p; int ret; @@ -7824,14 +8104,14 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->has_property) { /* has_property can free the prototype */ - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + obj1 = js_dup(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_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + js_dup(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) @@ -7860,7 +8140,7 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val) } /* return JS_ATOM_NULL in case of exception */ -JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) +JSAtom JS_ValueToAtom(JSContext *ctx, JSValue val) { JSAtom atom; uint32_t tag; @@ -7886,120 +8166,154 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) return atom; } -static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, +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, JSValue this_obj, JSValue prop) { JSAtom atom; JSValue ret; + uint32_t tag; - 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_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; + 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; } } else { - slow_path: - 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; + switch(tag) { + case JS_TAG_NULL: + JS_FreeValue(ctx, prop); + return JS_ThrowTypeError(ctx, "cannot read property of null"); + case JS_TAG_UNDEFINED: + JS_FreeValue(ctx, prop); + return JS_ThrowTypeError(ctx, "cannot read property of 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; } -JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, +JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue this_obj, uint32_t idx) { - return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx)); + return JS_GetPropertyInt64(ctx, this_obj, idx); } /* Check if an object has a generalized numeric property. Return value: - -1 for exception, + -1 for exception, *pval set to JS_EXCEPTION TRUE if property exists, stored into *pval, - FALSE if proprty does not exist. + FALSE if property does not exist. *pval set to JS_UNDEFINED. */ -static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval) +static int JS_TryGetPropertyInt64(JSContext *ctx, JSValue obj, int64_t idx, JSValue *pval) { - JSValue val = JS_UNDEFINED; + JSValue val; JSAtom prop; int present; - if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) { - /* fast path */ - present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx)); + 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 (present > 0) { - val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); + val = JS_GetProperty(ctx, obj, prop); if (unlikely(JS_IsException(val))) present = -1; + } else if (present == FALSE) { + val = JS_UNDEFINED; } - } 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); - } + JS_FreeAtom(ctx, prop); } *pval = val; return present; } -static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx) +JSValue JS_GetPropertyInt64(JSContext *ctx, JSValue obj, int64_t idx) { JSAtom prop; JSValue val; - if ((uint64_t)idx <= INT32_MAX) { - /* fast path for fast arrays */ - return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx)); + 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; } prop = JS_NewAtomInt64(ctx, idx); if (prop == JS_ATOM_NULL) @@ -8010,7 +8324,8 @@ static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx return val; } -JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, +/* `prop` may be pure ASCII or UTF-8 encoded */ +JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj, const char *prop) { JSAtom atom; @@ -8187,14 +8502,14 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) } static int call_setter(JSContext *ctx, JSObject *setter, - JSValueConst this_obj, JSValue val, int flags) + JSValue this_obj, JSValue val, int flags) { JSValue ret, func; if (likely(setter)) { func = JS_MKPTR(JS_TAG_OBJECT, setter); /* Note: the field could be removed in the setter */ - func = JS_DupValue(ctx, func); - ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val); + func = js_dup(func); + ret = JS_CallFree(ctx, func, this_obj, 1, &val); JS_FreeValue(ctx, val); if (JS_IsException(ret)) return -1; @@ -8234,7 +8549,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } p->u.array.count = len; } - p->prop[0].u.value = JS_NewUint32(ctx, len); + p->prop[0].u.value = js_uint32(len); } else { /* Note: length is always a uint32 because the object is an array */ @@ -8294,7 +8609,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } else { cur_len = len; } - set_value(ctx, &p->prop[0].u.value, JS_NewUint32(ctx, cur_len)); + set_value(ctx, &p->prop[0].u.value, js_uint32(cur_len)); if (unlikely(cur_len > len)) { return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable"); } @@ -8337,7 +8652,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_NewInt32(ctx, new_len); + p->prop[0].u.value = js_int32(new_len); } } if (unlikely(new_len > p->u.array.u1.size)) { @@ -8351,30 +8666,6 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, 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 void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) { JS_FreeValue(ctx, desc->getter); @@ -8385,58 +8676,48 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) /* 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. '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) + 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, JSValue obj, JSAtom prop, + JSValue val, JSValue this_obj, int flags, + JSInlineCacheUpdate *icu) { JSObject *p, *p1; JSShapeProperty *prs; JSProperty *pr; - uint32_t tag; JSPropertyDescriptor desc; int ret; -#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 { + uint32_t offset = 0; + + 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: p = JS_VALUE_GET_OBJ(this_obj); p1 = JS_VALUE_GET_OBJ(obj); - if (unlikely(p != p1)) - goto retry2; + 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; } - /* fast path if obj == this_obj */ - retry: - prs = find_own_property(&pr, p1, prop); +retry: + prs = find_own_property_ic(&pr, p1, prop, &offset); if (prs) { if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { /* fast case */ + add_ic_slot(ctx, icu, prop, p, offset); set_value(ctx, &pr->u.value, val); return TRUE; } else if (prs->flags & JS_PROP_LENGTH) { @@ -8455,16 +8736,14 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, 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)) { - JS_FreeValue(ctx, val); - return -1; - } + if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) + goto fail; goto retry; } else { goto read_only_prop; } } - + for(;;) { if (p1->is_exotic) { if (p1->fast_array) { @@ -8472,7 +8751,7 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, uint32_t idx = __JS_AtomToUInt32(prop); if (idx < p1->u.array.count) { if (unlikely(p == p1)) - return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags); + return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, flags); else break; } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && @@ -8483,12 +8762,10 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { - if (ret < 0) { - JS_FreeValue(ctx, val); - return -1; - } + if (ret < 0) + goto fail; typed_array_oob: - /* must convert the argument even if out of bound access */ + // 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; @@ -8509,7 +8786,7 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, JSValue obj1; if (em->set_property) { /* set_property can free the prototype */ - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->set_property(ctx, obj1, prop, val, this_obj, flags); JS_FreeValue(ctx, obj1); @@ -8518,14 +8795,12 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, } if (em->get_own_property) { /* get_own_property can free the prototype */ - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); ret = em->get_own_property(ctx, &desc, obj1, prop); JS_FreeValue(ctx, obj1); - if (ret < 0) { - JS_FreeValue(ctx, val); - return ret; - } + if (ret < 0) + goto fail; if (ret) { if (desc.flags & JS_PROP_GETSET) { JSObject *setter; @@ -8578,22 +8853,21 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, } if (unlikely(flags & JS_PROP_NO_ADD)) { - JS_FreeValue(ctx, val); JS_ThrowReferenceErrorNotDefined(ctx, prop); - return -1; + goto fail; } if (unlikely(!p)) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); + ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object"); + goto done; } if (unlikely(!p->extensible)) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); + ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); + goto done; } - if (likely(p == JS_VALUE_GET_OBJ(obj))) { + if (p == JS_VALUE_GET_OBJ(obj)) { if (p->is_exotic) { if (p->class_id == JS_CLASS_ARRAY && p->fast_array && __JS_AtomIsTaggedInt(prop)) { @@ -8601,65 +8875,94 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, 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 (unlikely(!pr)) { - JS_FreeValue(ctx, val); - return -1; - } + if (!pr) + goto fail; pr->u.value = val; return TRUE; } - } else { - /* 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; - } } + + // 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); + } + +done: + JS_FreeValue(ctx, val); + return ret; +fail: + JS_FreeValue(ctx, val); + return -1; +} + +static int JS_SetPropertyInternal(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, int flags) +{ + return JS_SetPropertyInternal2(ctx, this_obj, prop, val, this_obj, + flags, NULL); +} + +int JS_SetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop, JSValue val) +{ + return JS_SetPropertyInternal2(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW, NULL); +} + +// XXX(bnoordhuis) only used by OP_put_field_ic, maybe inline at call site +static int JS_SetPropertyInternalWithIC(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, int flags, + JSInlineCacheUpdate *icu) { + uint32_t tag, offset; + JSObject *p; + tag = JS_VALUE_GET_TAG(this_obj); + if (unlikely(tag != JS_TAG_OBJECT)) + goto slow_path; + p = JS_VALUE_GET_OBJ(this_obj); + offset = get_ic_prop_offset(icu, p->shape); + if (likely(offset != INLINE_CACHE_MISS)) { + set_value(ctx, &p->prop[offset].u.value, val); + return TRUE; + } +slow_path: + return JS_SetPropertyInternal2(ctx, this_obj, prop, val, this_obj, + flags, icu); } /* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */ -static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, +static int JS_SetPropertyValue(JSContext *ctx, JSValue this_obj, JSValue prop, JSValue val, int flags) { if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT && @@ -8709,7 +9012,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, break; case JS_CLASS_UINT8C_ARRAY: if (JS_ToUint8ClampFree(ctx, &v, val)) - return -1; + goto ta_cvt_fail; /* 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)) @@ -8719,7 +9022,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)) - return -1; + goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint8_ptr[idx] = v; @@ -8727,7 +9030,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)) - return -1; + goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint16_ptr[idx] = v; @@ -8735,7 +9038,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)) - return -1; + goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint32_ptr[idx] = v; @@ -8746,25 +9049,41 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, { int64_t v; if (JS_ToBigInt64Free(ctx, &v, val)) - return -1; + goto ta_cvt_fail; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint64_ptr[idx] = v; } break; + case JS_CLASS_FLOAT16_ARRAY: + if (JS_ToFloat64Free(ctx, &d, val)) + goto ta_cvt_fail; + 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)) - return -1; + goto ta_cvt_fail; 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)) + if (JS_ToFloat64Free(ctx, &d, val)) { + ta_cvt_fail: + if (flags & JS_PROP_REFLECT_DEFINE_PROPERTY) { + JS_FreeValue(ctx, JS_GetException(ctx)); + return FALSE; + } return -1; + } if (unlikely(idx >= (uint32_t)p->u.array.count)) { ta_out_of_bound: - return TRUE; + 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 } p->u.array.u.double_ptr[idx] = d; break; @@ -8782,20 +9101,20 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); return -1; } - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags); JS_FreeAtom(ctx, atom); return ret; } } -int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, +int JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj, uint32_t idx, JSValue val) { - return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val, + return JS_SetPropertyValue(ctx, this_obj, js_uint32(idx), val, JS_PROP_THROW); } -int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, +int JS_SetPropertyInt64(JSContext *ctx, JSValue this_obj, int64_t idx, JSValue val) { JSAtom prop; @@ -8803,7 +9122,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_NewInt32(ctx, idx), val, + return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), val, JS_PROP_THROW); } prop = JS_NewAtomInt64(ctx, idx); @@ -8816,13 +9135,14 @@ int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, return res; } -int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, +/* `prop` may be pure ASCII or UTF-8 encoded */ +int JS_SetPropertyStr(JSContext *ctx, JSValue this_obj, const char *prop, JSValue val) { JSAtom atom; int ret; atom = JS_NewAtom(ctx, prop); - ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW); + ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW); JS_FreeAtom(ctx, atom); return ret; } @@ -8839,8 +9159,8 @@ static int get_prop_flags(int flags, int def_flags) } static int JS_CreateProperty(JSContext *ctx, JSObject *p, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags) { JSProperty *pr; @@ -8863,7 +9183,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_DupValue(ctx, val), flags); + js_dup(val), flags); } else { goto convert_to_array; } @@ -8888,7 +9208,7 @@ 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_NewUint32(ctx, len)); + set_value(ctx, &plen->u.value, js_uint32(len)); } } } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && @@ -8933,16 +9253,16 @@ 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_DupValue(ctx, getter)); + JS_VALUE_GET_OBJ(js_dup(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_DupValue(ctx, setter)); + JS_VALUE_GET_OBJ(js_dup(setter)); } } else { if (flags & JS_PROP_HAS_VALUE) { - pr->u.value = JS_DupValue(ctx, val); + pr->u.value = js_dup(val); } else { pr->u.value = JS_UNDEFINED; } @@ -9031,9 +9351,9 @@ static int js_update_property_flags(JSContext *ctx, JSObject *p, define_own_property callback. return -1 (exception), FALSE or TRUE. */ -int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, int flags) +int JS_DefineProperty(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags) { JSObject *p; JSShapeProperty *prs; @@ -9053,11 +9373,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_DupValue(ctx, val), FALSE)) { + js_dup(val), FALSE)) { return -1; } /* this code relies on the fact that Uint32 are never allocated */ - val = (JSValueConst)JS_NewUint32(ctx, array_length); + val = js_uint32(array_length); /* prs may have been modified */ prs = find_own_property(&pr, p, prop); assert(prs != NULL); @@ -9121,14 +9441,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_DupValue(ctx, getter); + js_dup(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_DupValue(ctx, setter); + js_dup(setter); pr->u.getset.setter = new_setter; } } else { @@ -9162,22 +9482,18 @@ 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_DupValue(ctx, *pr->u.var_ref->pvalue); + val1 = js_dup(*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); @@ -9186,7 +9502,7 @@ 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_DupValue(ctx, val), + res = set_array_length(ctx, p, js_dup(val), flags); } else { res = TRUE; @@ -9206,7 +9522,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_DupValue(ctx, val); + pr->u.value = js_dup(val); } if (flags & JS_PROP_HAS_WRITABLE) { if (js_update_property_flags(ctx, p, &prs, @@ -9247,7 +9563,7 @@ 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_DupValue(ctx, val)); + set_value(ctx, &p->u.array.u.values[idx], js_dup(val)); } return TRUE; } @@ -9283,7 +9599,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, } idx = __JS_AtomToUInt32(prop); /* if the typed array is detached, p->u.array.count = 0 */ - if (idx >= p->u.array.count) { + if (idx >= typed_array_get_length(ctx, p)) { typed_array_oob: return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array"); } @@ -9293,7 +9609,7 @@ 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_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags); + return JS_SetPropertyValue(ctx, this_obj, js_int32(idx), js_dup(val), flags); } return TRUE; typed_array_done: ; @@ -9303,7 +9619,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags); } -static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, +static int JS_DefineAutoInitProperty(JSContext *ctx, JSValue this_obj, JSAtom prop, JSAutoInitIDEnum id, void *opaque, int flags) { @@ -9334,7 +9650,7 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, } /* shortcut to add or redefine a new property value */ -int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, +int JS_DefinePropertyValue(JSContext *ctx, JSValue this_obj, JSAtom prop, JSValue val, int flags) { int ret; @@ -9344,7 +9660,7 @@ int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, return ret; } -int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, +int JS_DefinePropertyValueValue(JSContext *ctx, JSValue this_obj, JSValue prop, JSValue val, int flags) { JSAtom atom; @@ -9360,21 +9676,22 @@ int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, return ret; } -int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, +int JS_DefinePropertyValueUint32(JSContext *ctx, JSValue this_obj, uint32_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx), + return JS_DefinePropertyValueValue(ctx, this_obj, js_uint32(idx), val, flags); } -int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj, +int JS_DefinePropertyValueInt64(JSContext *ctx, JSValue this_obj, int64_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), + return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(idx), val, flags); } -int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, +/* `prop` may be pure ASCII or UTF-8 encoded */ +int JS_DefinePropertyValueStr(JSContext *ctx, JSValue this_obj, const char *prop, JSValue val, int flags) { JSAtom atom; @@ -9386,7 +9703,7 @@ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, } /* shortcut to add getter & setter */ -int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, +int JS_DefinePropertyGetSet(JSContext *ctx, JSValue this_obj, JSAtom prop, JSValue getter, JSValue setter, int flags) { @@ -9399,23 +9716,23 @@ int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, return ret; } -static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, +static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValue this_obj, int64_t idx, JSValue val, int flags) { - return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx), + return JS_DefinePropertyValueValue(ctx, this_obj, js_int64(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, JSValueConst obj) +static BOOL js_object_has_name(JSContext *ctx, JSValue obj) { JSProperty *pr; JSShapeProperty *prs; - JSValueConst val; + JSValue val; JSString *p; - + prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name); if (!prs) return FALSE; @@ -9428,7 +9745,7 @@ static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) return (p->len != 0); } -static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, +static int JS_DefineObjectName(JSContext *ctx, JSValue obj, JSAtom name, int flags) { if (name != JS_ATOM_NULL @@ -9440,8 +9757,8 @@ static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, return 0; } -static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, - JSValueConst str, int flags) +static int JS_DefineObjectNameComputed(JSContext *ctx, JSValue obj, + JSValue str, int flags) { if (JS_IsObject(obj) && !js_object_has_name(ctx, obj)) { @@ -9546,7 +9863,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, - JSValueConst func, int def_flags) + JSValue func, int def_flags) { JSObject *p; @@ -9580,7 +9897,7 @@ 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_DupValue(ctx, pr->u.value); + return js_dup(pr->u.value); } return JS_GetPropertyInternal(ctx, ctx->global_obj, prop, ctx->global_obj, throw_ref_error); @@ -9607,14 +9924,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_DupValue(ctx, ctx->global_var_obj); + sp[0] = js_dup(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_DupValue(ctx, ctx->global_obj); + sp[0] = js_dup(ctx->global_obj); } else { sp[0] = JS_UNDEFINED; } @@ -9675,20 +9992,20 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, return 0; } flags = JS_PROP_THROW_STRICT; - if (is_strict_mode(ctx)) + if (is_strict_mode(ctx)) flags |= JS_PROP_NO_ADD; - return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags); + return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags); } /* 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) +int JS_DeleteProperty(JSContext *ctx, JSValue obj, JSAtom prop, int flags) { JSValue obj1; JSObject *p; int res; - + obj1 = JS_ToObject(ctx, obj); if (JS_IsException(obj1)) return -1; @@ -9705,7 +10022,7 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) return FALSE; } -int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags) +int JS_DeletePropertyInt64(JSContext *ctx, JSValue obj, int64_t idx, int flags) { JSAtom prop; int res; @@ -9722,7 +10039,7 @@ 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, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9738,7 +10055,7 @@ BOOL JS_IsFunction(JSContext *ctx, JSValueConst val) } } -BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic) +BOOL JS_IsCFunction(JSContext *ctx, JSValue val, JSCFunction *func, int magic) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9750,7 +10067,7 @@ BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int mag return FALSE; } -BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val) +BOOL JS_IsConstructor(JSContext *ctx, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9759,7 +10076,7 @@ BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val) return p->is_constructor; } -BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val) +BOOL JS_SetConstructorBit(JSContext *ctx, JSValue func_obj, BOOL val) { JSObject *p; if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) @@ -9769,7 +10086,7 @@ BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val) return TRUE; } -BOOL JS_IsError(JSContext *ctx, JSValueConst val) +BOOL JS_IsError(JSContext *ctx, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9779,7 +10096,7 @@ BOOL JS_IsError(JSContext *ctx, JSValueConst val) } /* used to avoid catching interrupt exceptions */ -BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val) +BOOL JS_IsUncatchableError(JSContext *ctx, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9788,7 +10105,7 @@ BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val) return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error; } -void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag) +void JS_SetUncatchableError(JSContext *ctx, JSValue val, BOOL flag) { JSObject *p; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -9803,17 +10120,33 @@ void JS_ResetUncatchableError(JSContext *ctx) JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE); } -void JS_SetOpaque(JSValue obj, void *opaque) +int JS_SetOpaque(JSValue obj, void *opaque) { - JSObject *p; + JSObject *p; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(obj); - p->u.opaque = opaque; + // User code can't set the opaque of internal objects. + if (p->class_id >= JS_CLASS_INIT_COUNT) { + p->u.opaque = opaque; + return 0; + } } + + return -1; +} + +/* |obj| must be a JSObject of an internal class. */ +static void JS_SetOpaqueInternal(JSValue 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 */ -void *JS_GetOpaque(JSValueConst obj, JSClassID class_id) +void *JS_GetOpaque(JSValue obj, JSClassID class_id) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) @@ -9824,7 +10157,7 @@ void *JS_GetOpaque(JSValueConst obj, JSClassID class_id) return p->u.opaque; } -void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id) +void *JS_GetOpaque2(JSContext *ctx, JSValue obj, JSClassID class_id) { void *p = JS_GetOpaque(obj, class_id); if (unlikely(!p)) { @@ -9833,11 +10166,17 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id) return p; } -#define HINT_STRING 0 -#define HINT_NUMBER 1 -#define HINT_NONE 2 -/* don't try Symbol.toPrimitive */ -#define HINT_FORCE_ORDINARY (1 << 4) +void *JS_GetAnyOpaque(JSValue obj, JSClassID *class_id) +{ + JSObject *p; + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { + *class_id = 0; + return NULL; + } + p = JS_VALUE_GET_OBJ(obj); + *class_id = p->class_id; + return p->u.opaque; +} static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) { @@ -9872,7 +10211,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) break; } arg = JS_AtomToString(ctx, atom); - ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg); + ret = JS_CallFree(ctx, method, val, 1, &arg); JS_FreeValue(ctx, arg); if (JS_IsException(ret)) goto exception; @@ -9913,12 +10252,12 @@ exception: return JS_EXCEPTION; } -static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint) +static JSValue JS_ToPrimitive(JSContext *ctx, JSValue val, int hint) { - return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint); + return JS_ToPrimitiveFree(ctx, js_dup(val), hint); } -void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj) +void JS_SetIsHTMLDDA(JSContext *ctx, JSValue obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) @@ -9927,7 +10266,7 @@ void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj) p->is_HTMLDDA = TRUE; } -static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) +static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValue obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) @@ -9935,7 +10274,7 @@ static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) p = JS_VALUE_GET_OBJ(obj); return p->is_HTMLDDA; } - + static int JS_ToBoolFree(JSContext *ctx, JSValue val) { uint32_t tag = JS_VALUE_GET_TAG(val); @@ -9955,26 +10294,13 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) return ret; } case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); BOOL ret; ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN; JS_FreeValue(ctx, val); return ret; } -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_DECIMAL: - { - JSBigDecimal *p = JS_VALUE_GET_PTR(val); - BOOL ret; - ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN; - JS_FreeValue(ctx, val); - return ret; - } -#endif case JS_TAG_OBJECT: { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -9995,11 +10321,12 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) } } -int JS_ToBool(JSContext *ctx, JSValueConst val) +int JS_ToBool(JSContext *ctx, JSValue val) { - return JS_ToBoolFree(ctx, JS_DupValue(ctx, val)); + return JS_ToBoolFree(ctx, js_dup(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; @@ -10007,19 +10334,19 @@ static int skip_spaces(const char *pc) p = p_start = (const uint8_t *)pc; for (;;) { - c = *p; - if (c < 128) { + c = *p++; + if (c < 0x80) { if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20))) break; - p++; } else { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next); + c = utf8_decode(p - 1, &p_next); + /* no need to test for invalid UTF-8, 0xFFFD is not a space */ if (!lre_is_space(c)) break; p = p_next; } } - return p - p_start; + return p - 1 - p_start; } static inline int to_digit(int c) @@ -10039,12 +10366,12 @@ static double js_strtod(const char *str, int radix, BOOL is_float) { double d; int c; - + if (!is_float || radix != 10) { const char *p = str; uint64_t n_max, n; int int_exp, is_neg; - + is_neg = 0; if (*p == '-') { is_neg = 1; @@ -10061,10 +10388,7 @@ static double js_strtod(const char *str, int radix, BOOL is_float) n_max = ((uint64_t)-1 - (radix - 1)) / radix; /* XXX: could be more precise */ int_exp = 0; - while (*p != '\0') { - c = to_digit((uint8_t)*p); - if (c >= radix) - break; + while ((c = to_digit(*p)) < radix) { if (n <= n_max) { n = n * radix + c; } else { @@ -10087,33 +10411,9 @@ static double js_strtod(const char *str, int radix, BOOL is_float) return d; } -#define ATOD_INT_ONLY (1 << 0) -/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */ -#define ATOD_ACCEPT_BIN_OCT (1 << 2) -/* accept O prefix as octal if radix == 0 and properly formed (Annex B) */ -#define ATOD_ACCEPT_LEGACY_OCTAL (1 << 4) -/* accept _ between digits as a digit separator */ -#define ATOD_ACCEPT_UNDERSCORES (1 << 5) -/* allow a suffix to override the type */ -#define ATOD_ACCEPT_SUFFIX (1 << 6) -/* default type */ -#define ATOD_TYPE_MASK (3 << 7) -#define ATOD_TYPE_FLOAT64 (0 << 7) -#define ATOD_TYPE_BIG_INT (1 << 7) -#ifdef CONFIG_BIGNUM -#define ATOD_TYPE_BIG_FLOAT (2 << 7) -#define ATOD_TYPE_BIG_DECIMAL (3 << 7) -/* assume bigint mode: floats are parsed as integers if no decimal - point nor exponent */ -#define ATOD_MODE_BIGINT (1 << 9) -#endif -/* accept -0x1 */ -#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10) - -static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, - int radix, int flags, slimb_t *pexponent) +static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, int radix) { - bf_t a_s, *a = &a_s; + bf_t *a; int ret; JSValue val; val = JS_NewBigInt(ctx); @@ -10125,211 +10425,136 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf, JS_FreeValue(ctx, val); return JS_ThrowOutOfMemory(ctx); } -#ifdef CONFIG_BIGNUM - val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0); -#else - val = JS_CompactBigInt1(ctx, val, FALSE); -#endif - return val; + return JS_CompactBigInt1(ctx, val); } -#ifdef CONFIG_BIGNUM -static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf, - int radix, int flags, slimb_t *pexponent) -{ - bf_t *a; - int ret; - JSValue val; - - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - return val; - a = JS_GetBigFloat(val); - if (flags & ATOD_ACCEPT_SUFFIX) { - /* return the exponent to get infinite precision */ - ret = bf_atof2(a, pexponent, buf, NULL, radix, BF_PREC_INF, - BF_RNDZ | BF_ATOF_EXPONENT); - } else { - ret = bf_atof(a, buf, NULL, radix, ctx->fp_env.prec, - ctx->fp_env.flags); - } - if (ret & BF_ST_MEM_ERROR) { - JS_FreeValue(ctx, val); - return JS_ThrowOutOfMemory(ctx); - } - return val; -} +/* `js_atof(ctx, p, len, pp, radix, flags)` + Convert the string pointed to by `p` to a number value. + Return an exception in case of memory error. + Return `JS_NAN` if invalid syntax. + - `p` points to a null terminated UTF-8 encoded char array, + - `len` the length of the array, + - `pp` if not null receives a pointer to the next character, + - `radix` must be in range 2 to 36, else return `JS_NAN`. + - `flags` is a combination of the flags below. + There is a null byte at `p[len]`, but there might be embedded null + bytes between `p[0]` and `p[len]` which must produce `JS_NAN` if + the `ATOD_NO_TRAILING_CHARS` flag is present. + */ -static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf, - int radix, int flags, slimb_t *pexponent) -{ - bfdec_t *a; - int ret; - JSValue val; - - val = JS_NewBigDecimal(ctx); - if (JS_IsException(val)) - return val; - a = JS_GetBigDecimal(val); - ret = bfdec_atof(a, buf, NULL, BF_PREC_INF, - BF_RNDZ | BF_ATOF_NO_NAN_INF); - if (ret & BF_ST_MEM_ERROR) { - JS_FreeValue(ctx, val); - return JS_ThrowOutOfMemory(ctx); - } - return val; -} -#endif +#define ATOD_TRIM_SPACES (1 << 0) /* trim white space */ +#define ATOD_ACCEPT_EMPTY (1 << 1) /* accept an empty string, value is 0 */ +#define ATOD_ACCEPT_FLOAT (1 << 2) /* parse decimal floating point syntax */ +#define ATOD_ACCEPT_INFINITY (1 << 3) /* parse Infinity as a float point number */ +#define ATOD_ACCEPT_BIN_OCT (1 << 4) /* accept 0o and 0b prefixes */ +#define ATOD_ACCEPT_HEX_PREFIX (1 << 5) /* accept 0x prefix for radix 16 */ +#define ATOD_ACCEPT_UNDERSCORES (1 << 6) /* accept _ between digits as a digit separator */ +#define ATOD_ACCEPT_SUFFIX (1 << 7) /* allow 'n' suffix to produce BigInt */ +#define ATOD_WANT_BIG_INT (1 << 8) /* return type must be BigInt */ +#define ATOD_DECIMAL_AFTER_SIGN (1 << 9) /* only accept decimal number after sign */ +#define ATOD_NO_TRAILING_CHARS (1 << 10) /* do not accept trailing characters */ -/* return an exception in case of memory error. Return JS_NAN if - invalid syntax */ -#ifdef CONFIG_BIGNUM -static JSValue js_atof2(JSContext *ctx, const char *str, const char **pp, - int radix, int flags, slimb_t *pexponent) -#else -static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, - int radix, int flags) -#endif +static JSValue js_atof(JSContext *ctx, const char *p, size_t len, + const char **pp, int radix, int flags) { - const char *p, *p_start; - int sep, is_neg; - 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; - JSValue val; - + const char *p_start; + const char *end = p + len; + int sep; + BOOL is_float; + char buf1[64], *buf = buf1; + size_t i, j; + JSValue val = JS_NAN; + double d; + char sign; + + if (radix < 2 || radix > 36) + goto done; + /* optional separator between digits */ sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256; - has_legacy_octal = FALSE; - - p = str; - p_start = p; - is_neg = 0; - if (p[0] == '+') { + sign = 0; + if (flags & ATOD_TRIM_SPACES) + p += skip_spaces(p); + if (p == end && (flags & ATOD_ACCEPT_EMPTY)) { + if (pp) *pp = p; + if (flags & ATOD_WANT_BIG_INT) + return JS_NewBigInt64(ctx, 0); + else + return js_int32(0); + } + if (*p == '+' || *p == '-') { + sign = *p; p++; - p_start++; - if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN)) - goto no_radix_prefix; - } else if (p[0] == '-') { - p++; - p_start++; - is_neg = 1; - if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN)) - goto no_radix_prefix; + if (flags & ATOD_DECIMAL_AFTER_SIGN) + flags &= ~(ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT); } if (p[0] == '0') { if ((p[1] == 'x' || p[1] == 'X') && - (radix == 0 || radix == 16)) { + ((flags & ATOD_ACCEPT_HEX_PREFIX) || radix == 16)) { p += 2; radix = 16; - } else if ((p[1] == 'o' || p[1] == 'O') && - radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) { - p += 2; - radix = 8; - } else if ((p[1] == 'b' || p[1] == 'B') && - radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) { - p += 2; - radix = 2; - } else if ((p[1] >= '0' && p[1] <= '9') && - radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) { - int i; - has_legacy_octal = TRUE; - sep = 256; - for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) - continue; - if (p[i] == '8' || p[i] == '9') - goto no_prefix; - p += 1; - radix = 8; - } else { - goto no_prefix; - } - /* there must be a digit after the prefix */ - 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 -#ifdef CONFIG_BIGNUM - || atod_type == ATOD_TYPE_BIG_FLOAT -#endif - ) && - strstart(p, "Infinity", &p)) { -#ifdef CONFIG_BIGNUM - if (atod_type == ATOD_TYPE_BIG_FLOAT) { - bf_t *a; - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - goto done; - a = JS_GetBigFloat(val); - bf_set_inf(a, is_neg); - } else -#endif - { - double d = 1.0 / 0.0; - if (is_neg) - d = -d; - val = JS_NewFloat64(ctx, d); + } else if (flags & ATOD_ACCEPT_BIN_OCT) { + if (p[1] == 'o' || p[1] == 'O') { + p += 2; + radix = 8; + } else if (p[1] == 'b' || p[1] == 'B') { + p += 2; + radix = 2; } + } + } else { + if (*p == 'I' && (flags & ATOD_ACCEPT_INFINITY) && js__strstart(p, "Infinity", &p)) { + d = INF; + if (sign == '-') + d = -d; + val = js_float64(d); goto done; } } - if (radix == 0) - radix = 10; is_float = FALSE; p_start = p; - while (to_digit((uint8_t)*p) < radix - || (*p == sep && (radix != 10 || - p != p_start + 1 || p[-1] != '0') && - to_digit((uint8_t)p[1]) < radix)) { + while (to_digit(*p) < radix) { p++; + if (*p == sep && to_digit(p[1]) < radix) + p++; } - if (!(flags & ATOD_INT_ONLY)) { - if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) { + if ((flags & ATOD_ACCEPT_FLOAT) && radix == 10) { + if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) { is_float = TRUE; p++; - if (*p == sep) - goto fail; - while (to_digit((uint8_t)*p) < radix || - (*p == sep && to_digit((uint8_t)p[1]) < radix)) + while (to_digit(*p) < radix) { p++; - } - 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; - if (*p1 == '+') { - p1++; - } else if (*p1 == '-') { - p1++; + if (*p == sep && to_digit(p[1]) < radix) + p++; } - if (is_digit((uint8_t)*p1)) { - p = p1 + 1; - while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1]))) + } + if (p > p_start && (*p == 'e' || *p == 'E')) { + i = 1; + if (p[1] == '+' || p[1] == '-') { + i++; + } + if (is_digit(p[i])) { + is_float = TRUE; + p += i + 1; + while (is_digit(*p) || (*p == sep && is_digit(p[1]))) p++; } } } if (p == p_start) - goto fail; + goto done; - buf = buf1; - 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; + if (!buf) { + if (pp) *pp = p; + return JS_ThrowOutOfMemory(ctx); + } } - /* remove the separators and the radix prefixes */ + /* remove the separators and the radix prefix */ j = 0; - if (is_neg) + if (sign == '-') buf[j++] = '-'; for (i = 0; i < len; i++) { if (p_start[i] != '_') @@ -10340,96 +10565,33 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, if (flags & ATOD_ACCEPT_SUFFIX) { if (*p == 'n') { p++; - atod_type = ATOD_TYPE_BIG_INT; - } else -#ifdef CONFIG_BIGNUM - if (*p == 'l') { - p++; - atod_type = ATOD_TYPE_BIG_FLOAT; - } else if (*p == 'm') { - p++; - atod_type = ATOD_TYPE_BIG_DECIMAL; - } else if (flags & ATOD_MODE_BIGINT) { - if (!is_float) - atod_type = ATOD_TYPE_BIG_INT; - if (has_legacy_octal) - goto fail; - } else -#endif - { - if (is_float && radix != 10) - goto fail; + flags |= ATOD_WANT_BIG_INT; } + } + + if (flags & ATOD_WANT_BIG_INT) { + if (!is_float) + val = js_string_to_bigint(ctx, buf, radix); } else { - if (atod_type == ATOD_TYPE_FLOAT64) { -#ifdef CONFIG_BIGNUM - if (flags & ATOD_MODE_BIGINT) { - if (!is_float) - atod_type = ATOD_TYPE_BIG_INT; - if (has_legacy_octal) - goto fail; - } else -#endif - { - if (is_float && radix != 10) - goto fail; - } - } + d = js_strtod(buf, radix, is_float); + val = js_number(d); /* return int or float64 */ } - switch(atod_type) { - case ATOD_TYPE_FLOAT64: - { - double d; - d = js_strtod(buf, radix, is_float); - /* return int or float64 */ - val = JS_NewFloat64(ctx, d); + done: + if (flags & ATOD_NO_TRAILING_CHARS) { + if (flags & ATOD_TRIM_SPACES) + p += skip_spaces(p); + if (p != end) { + JS_FreeValue(ctx, val); + val = JS_NAN; } - break; - case ATOD_TYPE_BIG_INT: - if (has_legacy_octal || is_float) - goto fail; - val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL); - break; -#ifdef CONFIG_BIGNUM - case ATOD_TYPE_BIG_FLOAT: - if (has_legacy_octal) - goto fail; - val = ctx->rt->bigfloat_ops.from_string(ctx, buf, radix, flags, - pexponent); - break; - case ATOD_TYPE_BIG_DECIMAL: - if (radix != 10) - goto fail; - val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL); - break; -#endif - default: - abort(); } - -done: - if (buf_allocated) + if (buf != buf1) js_free_rt(ctx->rt, buf); - if (pp) - *pp = p; + if (pp) *pp = p; return val; - fail: - val = JS_NAN; - goto done; - mem_error: - val = JS_ThrowOutOfMemory(ctx); - goto done; } -#ifdef CONFIG_BIGNUM -static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, - int radix, int flags) -{ - return js_atof2(ctx, str, pp, radix, flags, NULL); -} -#endif - typedef enum JSToNumberHintEnum { TON_FLAG_NUMBER, TON_FLAG_NUMERIC, @@ -10447,26 +10609,10 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, case JS_TAG_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; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_DECIMAL: - if (flag != TON_FLAG_NUMERIC) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number"); - } - ret = val; - break; - case JS_TAG_BIG_FLOAT: - if (flag != TON_FLAG_NUMERIC) { - JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert bigfloat to number"); - } - ret = val; - break; -#endif case JS_TAG_FLOAT64: case JS_TAG_INT: case JS_TAG_EXCEPTION: @@ -10474,7 +10620,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, break; case JS_TAG_BOOL: case JS_TAG_NULL: - ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val)); + ret = js_int32(JS_VALUE_GET_INT(val)); break; case JS_TAG_UNDEFINED: ret = JS_NAN; @@ -10487,28 +10633,18 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, case JS_TAG_STRING: { const char *str; - const char *p; size_t len; - + int flags; + str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) return JS_EXCEPTION; - p = str; - p += skip_spaces(p); - if ((p - str) == len) { - ret = JS_NewInt32(ctx, 0); - } else { - int flags = ATOD_ACCEPT_BIN_OCT; - ret = js_atof(ctx, p, &p, 0, flags); - if (!JS_IsException(ret)) { - p += skip_spaces(p); - if ((p - str) != len) { - JS_FreeValue(ctx, ret); - ret = JS_NAN; - } - } - } + flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY | + ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY | + ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT | + ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS; + ret = js_atof(ctx, str, len, NULL, 10, flags); JS_FreeCString(ctx, str); } break; @@ -10533,9 +10669,9 @@ static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val) return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMERIC); } -static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val) +static JSValue JS_ToNumeric(JSContext *ctx, JSValue val) { - return JS_ToNumericFree(ctx, JS_DupValue(ctx, val)); + return JS_ToNumericFree(ctx, js_dup(val)); } static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, @@ -10558,11 +10694,8 @@ static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres, d = JS_VALUE_GET_FLOAT64(val); break; case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); /* XXX: there can be a double rounding issue with some primitives (such as JS_ToUint8ClampFree()), but it is not critical to fix it. */ @@ -10593,14 +10726,14 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val) } } -int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val) +int JS_ToFloat64(JSContext *ctx, double *pres, JSValue val) { - return JS_ToFloat64Free(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToFloat64Free(ctx, pres, js_dup(val)); } -static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val) +static JSValue JS_ToNumber(JSContext *ctx, JSValue val) { - return JS_ToNumberFree(ctx, JS_DupValue(ctx, val)); + return JS_ToNumberFree(ctx, js_dup(val)); } /* same as JS_ToNumber() but return 0 in case of NaN/Undefined */ @@ -10616,52 +10749,20 @@ static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_UNDEFINED: - ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val)); + ret = js_int32(JS_VALUE_GET_INT(val)); break; case JS_TAG_FLOAT64: { double d = JS_VALUE_GET_FLOAT64(val); if (isnan(d)) { - ret = JS_NewInt32(ctx, 0); + ret = js_int32(0); } else { /* convert -0 to +0 */ d = trunc(d) + 0.0; - ret = JS_NewFloat64(ctx, d); + ret = js_number(d); } } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - bf_t a_s, *a, r_s, *r = &r_s; - BOOL is_nan; - - a = JS_ToBigFloat(ctx, &a_s, val); - if (!a) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - if (!bf_is_finite(a)) { - is_nan = bf_is_nan(a); - if (is_nan) - ret = JS_NewInt32(ctx, 0); - else - ret = JS_DupValue(ctx, val); - } else { - ret = JS_NewBigInt(ctx); - if (!JS_IsException(ret)) { - r = JS_GetBigInt(ret); - bf_set(r, a); - bf_rint(r, BF_RNDZ); - ret = JS_CompactBigInt(ctx, ret); - } - } - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, val); - } - break; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) @@ -10704,15 +10805,6 @@ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val) } } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - bf_get_int32(&ret, &p->num, 0); - JS_FreeValue(ctx, val); - } - break; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { @@ -10725,15 +10817,15 @@ static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val) return 0; } -int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val) +int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValue val) { - return JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToInt32SatFree(ctx, pres, js_dup(val)); } -int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val, +int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValue val, int min, int max, int min_offset) { - int res = JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val)); + int res = JS_ToInt32SatFree(ctx, pres, js_dup(val)); if (res == 0) { if (*pres < min) { *pres += min_offset; @@ -10771,22 +10863,13 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val) } else { if (d < INT64_MIN) *pres = INT64_MIN; - else if (d > INT64_MAX) + else if (d >= 0x1p63) *pres = INT64_MAX; else *pres = (int64_t)d; } } return 0; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - bf_get_int64(pres, &p->num, 0); - JS_FreeValue(ctx, val); - } - return 0; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { @@ -10797,15 +10880,15 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val) } } -int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val) +int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValue val) { - return JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToInt64SatFree(ctx, pres, js_dup(val)); } -int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val, +int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValue val, int64_t min, int64_t max, int64_t neg_offset) { - int res = JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val)); + int res = JS_ToInt64SatFree(ctx, pres, js_dup(val)); if (res == 0) { if (*pres < 0) *pres += neg_offset; @@ -10852,21 +10935,13 @@ 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) - ret = -ret; + if (ret != INT64_MIN) + ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - bf_get_int64(&ret, &p->num, BF_GET_INT_MOD); - JS_FreeValue(ctx, val); - } - break; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { @@ -10879,12 +10954,12 @@ static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val) return 0; } -int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val) +int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValue val) { - return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToInt64Free(ctx, pres, js_dup(val)); } -int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val) +int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValue val) { if (JS_IsBigInt(ctx, val)) return JS_ToBigInt64(ctx, pres, val); @@ -10927,21 +11002,13 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) ret = v >> 32; /* take the sign into account */ if (u.u64 >> 63) - ret = -ret; + if (ret != INT32_MIN) + ret = -ret; } else { ret = 0; /* also handles NaN and +inf */ } } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - bf_get_int32(&ret, &p->num, BF_GET_INT_MOD); - JS_FreeValue(ctx, val); - } - break; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { @@ -10954,9 +11021,9 @@ static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val) return 0; } -int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val) +int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValue val) { - return JS_ToInt32Free(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToInt32Free(ctx, pres, js_dup(val)); } static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val) @@ -10977,9 +11044,6 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val) case JS_TAG_NULL: case JS_TAG_UNDEFINED: res = JS_VALUE_GET_INT(val); -#ifdef CONFIG_BIGNUM - int_clamp: -#endif res = max_int(0, min_int(255, res)); break; case JS_TAG_FLOAT64: @@ -10997,20 +11061,6 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val) } } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - bf_t r_s, *r = &r_s; - bf_init(ctx->bf_ctx, r); - bf_set(r, &p->num); - bf_rint(r, BF_RNDN); - bf_get_int32(&res, r, 0); - bf_delete(r); - JS_FreeValue(ctx, val); - } - goto int_clamp; -#endif default: val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) { @@ -11042,11 +11092,8 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, } break; case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); bf_t a; BOOL res; bf_get_int32((int32_t *)&len, &p->num, BF_GET_INT_MOD); @@ -11063,6 +11110,8 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, if (JS_TAG_IS_FLOAT64(tag)) { double d; d = JS_VALUE_GET_FLOAT64(val); + if (!(d >= 0 && d <= UINT32_MAX)) + goto fail; len = (uint32_t)d; if (len != d) goto fail; @@ -11109,7 +11158,7 @@ static BOOL is_safe_integer(double d) fabs(d) <= (double)MAX_SAFE_INTEGER; } -int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val) +int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValue val) { int64_t v; if (JS_ToInt64Sat(ctx, &v, val)) @@ -11134,7 +11183,7 @@ static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen, } /* Note: can return an exception */ -static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val) +static int JS_NumberIsInteger(JSContext *ctx, JSValue val) { double d; if (!JS_IsNumber(val)) @@ -11144,7 +11193,7 @@ static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val) return isfinite(d) && floor(d) == d; } -static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) +static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValue val) { uint32_t tag; @@ -11164,35 +11213,22 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val) } case JS_TAG_BIG_INT: { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); /* Note: integer zeros are not necessarily positive */ return p->num.sign && !bf_is_zero(&p->num); } -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - return p->num.sign; - } - break; - case JS_TAG_BIG_DECIMAL: - { - JSBigDecimal *p = JS_VALUE_GET_PTR(val); - return p->num.sign; - } - break; -#endif default: return FALSE; } } -static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) +static JSValue js_bigint_to_string1(JSContext *ctx, JSValue val, int radix) { JSValue ret; bf_t a_s, *a; char *str; int saved_sign; + size_t len; a = JS_ToBigInt(ctx, &a_s, val); if (!a) @@ -11200,398 +11236,458 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix) saved_sign = a->sign; if (a->expn == BF_EXP_ZERO) a->sign = 0; - str = bf_ftoa(NULL, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC | + str = bf_ftoa(&len, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC | BF_FTOA_JS_QUIRKS); a->sign = saved_sign; JS_FreeBigInt(ctx, a, &a_s); if (!str) return JS_ThrowOutOfMemory(ctx); - ret = JS_NewString(ctx, str); + ret = js_new_string8_len(ctx, str, len); bf_free(ctx->bf_ctx, str); return ret; } -static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val) +static JSValue js_bigint_to_string(JSContext *ctx, JSValue val) { return js_bigint_to_string1(ctx, val, 10); } -#ifdef CONFIG_BIGNUM +/*---- floating point number to string conversions ----*/ -static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix, - limb_t prec, bf_flags_t flags) +/* JavaScript rounding is specified as round to nearest tie away + from zero (RNDNA), but in `printf` the "ties" case is not + specified (in most cases it is RNDN, round to nearest, tie to even), + so we must round manually. We generate 2 extra places and make + an extra call to snprintf if these are exactly '50'. + We set the current rounding mode to FE_DOWNWARD to check if the + last 2 places become '49'. If not, we must round up, which is + performed in place using the string digits. + + Note that we cannot rely on snprintf for rounding up: + the code below fails on macOS for `0.5.toFixed(0)`: gives `0` expected `1` + fesetround(FE_UPWARD); + snprintf(dest, size, "%.*f", n_digits, d); + fesetround(FE_TONEAREST); + */ + +/* `js_fcvt` minimum buffer length: + - up to 21 digits in integral part + - 1 potential decimal point + - up to 102 decimals + - 1 null terminator + */ +#define JS_FCVT_BUF_SIZE (21+1+102+1) + +/* `js_ecvt` minimum buffer length: + - 1 leading digit + - 1 potential decimal point + - up to 102 decimals + - 5 exponent characters (from 'e-324' to 'e+308') + - 1 null terminator + */ +#define JS_ECVT_BUF_SIZE (1+1+102+5+1) + +/* `js_dtoa` minimum buffer length: + - 8 byte prefix + - either JS_FCVT_BUF_SIZE or JS_ECVT_BUF_SIZE + - JS_FCVT_BUF_SIZE is larger than JS_ECVT_BUF_SIZE + */ +#define JS_DTOA_BUF_SIZE (8+JS_FCVT_BUF_SIZE) + +/* `js_ecvt1`: compute the digits and decimal point spot for a double + - `d` is finite, positive or zero + - `n_digits` number of significant digits in range 1..103 + - `buf` receives the printf result + - `buf` has a fixed format: n_digits with a decimal point at offset 1 + and exponent 'e{+/-}xx[x]' at offset n_digits+1 + Return n_digits + Store the position of the decimal point into `*decpt` + */ +static int js_ecvt1(double d, int n_digits, + char dest[minimum_length(JS_ECVT_BUF_SIZE)], + size_t size, int *decpt) { - JSValue val, ret; - bf_t a_s, *a; - char *str; - int saved_sign; - - val = JS_ToNumeric(ctx, val1); - if (JS_IsException(val)) - return val; - a = JS_ToBigFloat(ctx, &a_s, val); - if (!a) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - saved_sign = a->sign; - if (a->expn == BF_EXP_ZERO) - a->sign = 0; - flags |= BF_FTOA_JS_QUIRKS; - if ((flags & BF_FTOA_FORMAT_MASK) == BF_FTOA_FORMAT_FREE_MIN) { - /* Note: for floating point numbers with a radix which is not - a power of two, the current precision is used to compute - the number of digits. */ - if ((radix & (radix - 1)) != 0) { - bf_t r_s, *r = &r_s; - int prec, flags1; - /* must round first */ - if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) { - prec = ctx->fp_env.prec; - flags1 = ctx->fp_env.flags & - (BF_FLAG_SUBNORMAL | (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)); - } else { - prec = 53; - flags1 = bf_set_exp_bits(11) | BF_FLAG_SUBNORMAL; - } - bf_init(ctx->bf_ctx, r); - bf_set(r, a); - bf_round(r, prec, flags1 | BF_RNDN); - str = bf_ftoa(NULL, r, radix, prec, flags1 | flags); - bf_delete(r); - } else { - str = bf_ftoa(NULL, a, radix, BF_PREC_INF, flags); - } - } else { - str = bf_ftoa(NULL, a, radix, prec, flags); - } - a->sign = saved_sign; - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, val); - if (!str) - return JS_ThrowOutOfMemory(ctx); - ret = JS_NewString(ctx, str); - bf_free(ctx->bf_ctx, str); - return ret; -} - -static JSValue js_bigfloat_to_string(JSContext *ctx, JSValueConst val) -{ - return js_ftoa(ctx, val, 10, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN); -} - -static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val, - limb_t prec, int flags) -{ - JSValue ret; - bfdec_t *a; - char *str; - int saved_sign; - - a = JS_ToBigDecimal(ctx, val); - if (!a) - return JS_EXCEPTION; - saved_sign = a->sign; - if (a->expn == BF_EXP_ZERO) - a->sign = 0; - str = bfdec_ftoa(NULL, a, prec, flags | BF_FTOA_JS_QUIRKS); - a->sign = saved_sign; - if (!str) - return JS_ThrowOutOfMemory(ctx); - ret = JS_NewString(ctx, str); - bf_free(ctx->bf_ctx, str); - return ret; -} - -static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val) -{ - return js_bigdecimal_to_string1(ctx, val, 0, - BF_RNDZ | BF_FTOA_FORMAT_FREE); -} - -#endif /* CONFIG_BIGNUM */ - -/* 2 <= base <= 36 */ -static char *i64toa(char *buf_end, int64_t n, unsigned int base) -{ - char *q = buf_end; - int digit, is_neg; - - is_neg = 0; - if (n < 0) { - is_neg = 1; - n = -n; - } - *--q = '\0'; - do { - digit = (uint64_t)n % base; - n = (uint64_t)n / base; - if (digit < 10) - digit += '0'; - else - digit += 'a' - 10; - *--q = digit; - } while (n != 0); - if (is_neg) - *--q = '-'; - return q; -} - -/* buf1 contains the printf result */ -static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf, - int rounding_mode, char *buf1, int buf1_size) -{ - if (rounding_mode != FE_TONEAREST) - fesetround(rounding_mode); - snprintf(buf1, buf1_size, "%+.*e", n_digits - 1, d); - if (rounding_mode != FE_TONEAREST) - fesetround(FE_TONEAREST); - *sign = (buf1[0] == '-'); - /* mantissa */ - buf[0] = buf1[1]; - if (n_digits > 1) - memcpy(buf + 1, buf1 + 3, n_digits - 1); - buf[n_digits] = '\0'; - /* exponent */ - *decpt = atoi(buf1 + n_digits + 2 + (n_digits > 1)) + 1; -} - -/* maximum buffer size for js_dtoa */ -#define JS_DTOA_BUF_SIZE 128 - -/* needed because ecvt usually limits the number of digits to - 17. Return the number of digits. */ -static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf, - BOOL is_fixed) -{ - int rounding_mode; - char buf_tmp[JS_DTOA_BUF_SIZE]; - - if (!is_fixed) { - unsigned int n_digits_min, n_digits_max; - /* find the minimum amount of digits (XXX: inefficient but simple) */ - n_digits_min = 1; - n_digits_max = 17; - while (n_digits_min < n_digits_max) { - n_digits = (n_digits_min + n_digits_max) / 2; - js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST, - buf_tmp, sizeof(buf_tmp)); - if (strtod(buf_tmp, NULL) == d) { - /* no need to keep the trailing zeros */ - while (n_digits >= 2 && buf[n_digits - 1] == '0') - n_digits--; - n_digits_max = n_digits; - } else { - n_digits_min = n_digits + 1; - } - } - n_digits = n_digits_max; - rounding_mode = FE_TONEAREST; - } else { - rounding_mode = FE_TONEAREST; -#ifdef CONFIG_PRINTF_RNDN - { - char buf1[JS_DTOA_BUF_SIZE], buf2[JS_DTOA_BUF_SIZE]; - int decpt1, sign1, decpt2, sign2; - /* The JS rounding is specified as round to nearest ties away - from zero (RNDNA), but in printf the "ties" case is not - specified (for example it is RNDN for glibc, RNDNA for - Windows), so we must round manually. */ - js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_TONEAREST, - buf_tmp, sizeof(buf_tmp)); - /* XXX: could use 2 digits to reduce the average running time */ - if (buf1[n_digits] == '5') { - js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_DOWNWARD, - buf_tmp, sizeof(buf_tmp)); - js_ecvt1(d, n_digits + 1, &decpt2, &sign2, buf2, FE_UPWARD, - buf_tmp, sizeof(buf_tmp)); - if (memcmp(buf1, buf2, n_digits + 1) == 0 && decpt1 == decpt2) { - /* exact result: round away from zero */ - if (sign1) - rounding_mode = FE_DOWNWARD; - else - rounding_mode = FE_UPWARD; - } - } - } -#endif /* CONFIG_PRINTF_RNDN */ - } - js_ecvt1(d, n_digits, decpt, sign, buf, rounding_mode, - buf_tmp, sizeof(buf_tmp)); + /* d is positive, ensure decimal point is always present */ + snprintf(dest, size, "%#.*e", n_digits - 1, d); + /* dest contents: + 0: first digit + 1: '.' decimal point (locale specific) + 2..n_digits: (n_digits-1) additional digits + n_digits+1: 'e' exponent mark + n_digits+2..: exponent sign, value and null terminator + */ + /* extract the exponent (actually the position of the decimal point) */ + *decpt = 1 + atoi(dest + n_digits + 2); return n_digits; } -static int js_fcvt1(char *buf, int buf_size, double d, int n_digits, - int rounding_mode) +/* `js_ecvt`: compute the digits and decimal point spot for a double + with proper javascript rounding. We cannot use `ecvt` for multiple + resasons: portability, because of the number of digits is typically + limited to 17, finally because the default rounding is inadequate. + `d` is finite and positive or zero. + `n_digits` number of significant digits in range 1..101 + or 0 for automatic (only as many digits as necessary) + Return the number of digits produced in `dest`. + Store the position of the decimal point into `*decpt` + */ +static int js_ecvt(double d, int n_digits, + char dest[minimum_length(JS_ECVT_BUF_SIZE)], + size_t size, int *decpt) { - int n; - if (rounding_mode != FE_TONEAREST) - fesetround(rounding_mode); - n = snprintf(buf, buf_size, "%.*f", n_digits, d); - if (rounding_mode != FE_TONEAREST) - fesetround(FE_TONEAREST); - assert(n < buf_size); - return n; -} - -static void js_fcvt(char *buf, int buf_size, double d, int n_digits) -{ - int rounding_mode; - rounding_mode = FE_TONEAREST; -#ifdef CONFIG_PRINTF_RNDN - { - int n1, n2; - char buf1[JS_DTOA_BUF_SIZE]; - char buf2[JS_DTOA_BUF_SIZE]; - - /* The JS rounding is specified as round to nearest ties away from - zero (RNDNA), but in printf the "ties" case is not specified - (for example it is RNDN for glibc, RNDNA for Windows), so we - must round manually. */ - n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_TONEAREST); - rounding_mode = FE_TONEAREST; - /* XXX: could use 2 digits to reduce the average running time */ - if (buf1[n1 - 1] == '5') { - n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_DOWNWARD); - n2 = js_fcvt1(buf2, sizeof(buf2), d, n_digits + 1, FE_UPWARD); - if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) { - /* exact result: round away from zero */ - if (buf1[0] == '-') - rounding_mode = FE_DOWNWARD; - else - rounding_mode = FE_UPWARD; + if (n_digits == 0) { + /* find the minimum number of digits (XXX: inefficient but simple) */ + // TODO(chqrlie) use direct method from quickjs-printf + unsigned int n_digits_min = 1; + unsigned int n_digits_max = 17; + for (;;) { + n_digits = (n_digits_min + n_digits_max) / 2; + js_ecvt1(d, n_digits, dest, size, decpt); + if (n_digits_min == n_digits_max) + return n_digits; + /* dest contents: + 0: first digit + 1: '.' decimal point (locale specific) + 2..n_digits: (n_digits-1) additional digits + n_digits+1: 'e' exponent mark + n_digits+2..: exponent sign, value and null terminator + */ + if (strtod(dest, NULL) == d) { + unsigned int n0 = n_digits; + /* enough digits */ + /* strip the trailing zeros */ + while (dest[n_digits] == '0') + n_digits--; + if (n_digits == n_digits_min) + return n_digits; + /* done if trailing zeros and not denormal or huge */ + if (n_digits < n0 && d > 3e-308 && d < 8e307) + return n_digits; + n_digits_max = n_digits; + } else { + /* need at least one more digit */ + n_digits_min = n_digits + 1; } } - } -#endif /* CONFIG_PRINTF_RNDN */ - js_fcvt1(buf, buf_size, d, n_digits, rounding_mode); -} - -/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */ -/* use as many digits as necessary */ -#define JS_DTOA_VAR_FORMAT (0 << 0) -/* use n_digits significant digits (1 <= n_digits <= 101) */ -#define JS_DTOA_FIXED_FORMAT (1 << 0) -/* force fractional format: [-]dd.dd with n_digits fractional digits */ -#define JS_DTOA_FRAC_FORMAT (2 << 0) -/* force exponential notation either in fixed or variable format */ -#define JS_DTOA_FORCE_EXP (1 << 2) - -/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough. - XXX: radix != 10 is only supported for small integers -*/ -static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) -{ - char *q; - - if (!isfinite(d)) { - if (isnan(d)) { - strcpy(buf, "NaN"); - } else { - q = buf; - if (d < 0) - *q++ = '-'; - strcpy(q, "Infinity"); - } - } else if (flags == JS_DTOA_VAR_FORMAT) { - int64_t i64; - char buf1[70], *ptr; - i64 = (int64_t)d; - if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER) - goto generic_conv; - /* fast path for integers */ - ptr = i64toa(buf1 + sizeof(buf1), i64, radix); - strcpy(buf, ptr); } else { - if (d == 0.0) - d = 0.0; /* convert -0 to 0 */ - if (flags == JS_DTOA_FRAC_FORMAT) { - js_fcvt(buf, JS_DTOA_BUF_SIZE, d, n_digits); - } else { - char buf1[JS_DTOA_BUF_SIZE]; - int sign, decpt, k, n, i, p, n_max; - BOOL is_fixed; - generic_conv: - is_fixed = ((flags & 3) == JS_DTOA_FIXED_FORMAT); - if (is_fixed) { - n_max = n_digits; - } else { - n_max = 21; - } - /* the number has k digits (k >= 1) */ - k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed); - n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */ - q = buf; - if (sign) - *q++ = '-'; - if (flags & JS_DTOA_FORCE_EXP) - goto force_exp; - if (n >= 1 && n <= n_max) { - if (k <= n) { - memcpy(q, buf1, k); - q += k; - for(i = 0; i < (n - k); i++) - *q++ = '0'; - *q = '\0'; - } else { - /* k > n */ - memcpy(q, buf1, n); - q += n; - *q++ = '.'; - for(i = 0; i < (k - n); i++) - *q++ = buf1[n + i]; - *q = '\0'; +#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) + int i; + /* generate 2 extra digits: 99% chances to avoid 2 calls */ + js_ecvt1(d, n_digits + 2, dest, size, decpt); + if (dest[n_digits + 1] < '5') + return n_digits; /* truncate the 2 extra digits */ + if (dest[n_digits + 1] == '5' && dest[n_digits + 2] == '0') { + /* close to half-way: try rounding toward 0 */ + fesetround(FE_DOWNWARD); + js_ecvt1(d, n_digits + 2, dest, size, decpt); + fesetround(FE_TONEAREST); + if (dest[n_digits + 1] < '5') + return n_digits; /* truncate the 2 extra digits */ + } + /* round up in the string */ + for(i = n_digits;; i--) { + /* ignore the locale specific decimal point */ + if (is_digit(dest[i])) { + if (dest[i]++ < '9') + break; + dest[i] = '0'; + if (i == 0) { + dest[0] = '1'; + (*decpt)++; + break; } - } else if (n >= -5 && n <= 0) { - *q++ = '0'; - *q++ = '.'; - for(i = 0; i < -n; i++) - *q++ = '0'; - memcpy(q, buf1, k); - q += k; - *q = '\0'; - } else { - force_exp: - /* exponential notation */ - *q++ = buf1[0]; - if (k > 1) { - *q++ = '.'; - for(i = 1; i < k; i++) - *q++ = buf1[i]; - } - *q++ = 'e'; - p = n - 1; - if (p >= 0) - *q++ = '+'; - sprintf(q, "%d", p); } } + return n_digits; /* truncate the 2 extra digits */ +#else + /* No disambiguation available, eg: __wasi__ targets */ + return js_ecvt1(d, n_digits, dest, size, decpt); +#endif } } -static JSValue js_dtoa(JSContext *ctx, - double d, int radix, int n_digits, int flags) +/* `js_fcvt`: convert a floating point value to %f format using RNDNA + `d` is finite and positive or zero. + `n_digits` number of decimal places in range 0..100 + Return the number of characters produced in `dest`. + */ +static size_t js_fcvt(double d, int n_digits, + char dest[minimum_length(JS_FCVT_BUF_SIZE)], size_t size) +{ +#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) + int i, n1; + /* generate 2 extra digits: 99% chances to avoid 2 calls */ + n1 = snprintf(dest, size, "%.*f", n_digits + 2, d) - 2; + if (dest[n1] >= '5') { + if (dest[n1] == '5' && dest[n1 + 1] == '0') { + /* close to half-way: try rounding toward 0 */ + fesetround(FE_DOWNWARD); + n1 = snprintf(dest, size, "%.*f", n_digits + 2, d) - 2; + fesetround(FE_TONEAREST); + } + if (dest[n1] >= '5') { /* number should be rounded up */ + /* d is either exactly half way or greater: round the string manually */ + for (i = n1 - 1;; i--) { + /* ignore the locale specific decimal point */ + if (is_digit(dest[i])) { + if (dest[i]++ < '9') + break; + dest[i] = '0'; + if (i == 0) { + dest[0] = '1'; + dest[n1] = '0'; + dest[n1 - n_digits - 1] = '0'; + dest[n1 - n_digits] = '.'; + n1++; + break; + } + } + } + } + } + /* truncate the extra 2 digits and the decimal point if !n_digits */ + n1 -= !n_digits; + //dest[n1] = '\0'; // optional + return n1; +#else + /* No disambiguation available, eg: __wasi__ targets */ + return snprintf(dest, size, "%.*f", n_digits, d); +#endif +} + +static JSValue js_dtoa_infinite(JSContext *ctx, double d) +{ + // TODO(chqrlie) use atoms for NaN and Infinite? + if (isnan(d)) + return js_new_string8(ctx, "NaN"); + if (d < 0) + return js_new_string8(ctx, "-Infinity"); + else + return js_new_string8(ctx, "Infinity"); +} + +#define JS_DTOA_TOSTRING 0 /* use as many digits as necessary */ +#define JS_DTOA_EXPONENTIAL 1 /* use exponential notation either fixed or variable digits */ +#define JS_DTOA_FIXED 2 /* force fixed number of fractional digits */ +#define JS_DTOA_PRECISION 3 /* use n_digits significant digits (1 <= n_digits <= 101) */ + +/* `js_dtoa`: convert a floating point number to a string + - `mode`: one of the 4 supported formats + - `n_digits`: digit number according to mode + - TOSTRING: 0 only. As many digits as necessary + - EXPONENTIAL: 0 as many decimals as necessary + - 1..101 number of significant digits + - FIXED: 0..100 number of decimal places + - PRECISION: 1..101 number of significant digits + */ +// XXX: should use libbf or quickjs-printf. +static JSValue js_dtoa(JSContext *ctx, double d, int n_digits, int mode) { char buf[JS_DTOA_BUF_SIZE]; - js_dtoa1(buf, d, radix, n_digits, flags); - return JS_NewString(ctx, buf); + size_t len; + char *start; + int sign, decpt, exp, i, k, n, n_max; + + if (!isfinite(d)) + return js_dtoa_infinite(ctx, d); + + sign = (d < 0); + start = buf + 8; + d = fabs(d); /* also converts -0 to 0 */ + + if (mode != JS_DTOA_EXPONENTIAL && n_digits == 0) { + /* fast path for exact integers in variable format: + clip to MAX_SAFE_INTEGER because to ensure insignificant + digits are generated as 0. + used for JS_DTOA_TOSTRING and JS_DTOA_FIXED without decimals. + */ + if (d <= (double)MAX_SAFE_INTEGER) { + uint64_t u64 = (uint64_t)d; + if (d == u64) { + len = u64toa(start, u64); + goto done; + } + } + } + if (mode == JS_DTOA_FIXED) { + len = js_fcvt(d, n_digits, start, sizeof(buf) - 8); + // TODO(chqrlie) patch the locale specific decimal point + goto done; + } + + n_max = (n_digits > 0) ? n_digits : 21; + /* the number has k digits (1 <= k <= n_max) */ + k = js_ecvt(d, n_digits, start, sizeof(buf) - 8, &decpt); + /* buffer contents: + 0: first digit + 1: '.' decimal point + 2..k: (k-1) additional digits + */ + n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */ + if (mode != JS_DTOA_EXPONENTIAL) { + /* mode is JS_DTOA_PRECISION or JS_DTOA_TOSTRING */ + if (n >= 1 && n <= n_max) { + /* between 1 and n_max digits before the decimal point */ + if (k <= n) { + /* all digits before the point, append zeros */ + start[1] = start[0]; + start++; + for(i = k; i < n; i++) + start[i] = '0'; + len = n; + } else { + /* k > n: move digits before the point */ + for(i = 1; i < n; i++) + start[i] = start[i + 1]; + start[i] = '.'; + len = 1 + k; + } + goto done; + } + if (n >= -5 && n <= 0) { + /* insert -n leading 0 decimals and a '0.' prefix */ + n = -n; + start[1] = start[0]; + start -= n + 1; + start[0] = '0'; + start[1] = '.'; + for(i = 0; i < n; i++) + start[2 + i] = '0'; + len = 2 + k + n; + goto done; + } + } + /* exponential notation */ + exp = n - 1; + /* count the digits and the decimal point if at least one decimal */ + len = k + (k > 1); + start[1] = '.'; /* patch the locale specific decimal point */ + start[len] = 'e'; + start[len + 1] = '+'; + if (exp < 0) { + start[len + 1] = '-'; + exp = -exp; + } + len += 2 + 1 + (exp > 9) + (exp > 99); + for (i = len - 1; exp > 9;) { + int quo = exp / 10; + start[i--] = (char)('0' + exp % 10); + exp = quo; + } + start[i] = (char)('0' + exp); + + done: + start[-1] = '-'; /* prepend the sign if negative */ + return js_new_string8_len(ctx, start - sign, len + sign); } -JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey) +/* `js_dtoa_radix`: convert a floating point number using a specific base + - `d` must be finite + - `radix` must be in range 2..36 + */ +static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix) +{ + char buf[2200], *ptr, *ptr2, *ptr3; + int sign, digit; + double frac, d0; + int64_t n0; + + if (!isfinite(d)) + return js_dtoa_infinite(ctx, d); + + sign = (d < 0); + d = fabs(d); + d0 = trunc(d); + n0 = 0; + frac = d - d0; + ptr2 = buf + 1100; /* ptr2 points to the end of the string */ + ptr = ptr2; /* ptr points to the beginning of the string */ + if (d0 <= MAX_SAFE_INTEGER) { + int64_t n = n0 = (int64_t)d0; + while (n >= radix) { + digit = n % radix; + n = n / radix; + *--ptr = digits36[digit]; + } + *--ptr = digits36[(size_t)n]; + } else { + /* no decimals */ + while (d0 >= radix) { + digit = fmod(d0, radix); + d0 = trunc(d0 / radix); + if (d0 >= MAX_SAFE_INTEGER) + digit = 0; + *--ptr = digits36[digit]; + } + *--ptr = digits36[(size_t)d0]; + goto done; + } + if (frac != 0) { + double log2_radix = log2(radix); + double prec = 1023 + 51; // handle subnormals + *ptr2++ = '.'; + while (frac != 0 && n0 <= MAX_SAFE_INTEGER/2 && prec > 0) { + frac *= radix; + digit = trunc(frac); + frac -= digit; + *ptr2++ = digits36[digit]; + n0 = n0 * radix + digit; + prec -= log2_radix; + } + if (frac * radix >= radix / 2) { + /* round up the string representation manually */ + char nine = digits36[radix - 1]; + while (ptr2[-1] == nine) { + /* strip trailing '9' or equivalent digits */ + ptr2--; + } + if (ptr2[-1] == '.') { + /* strip the 'decimal' point */ + ptr2--; + /* increment the integral part */ + for (ptr3 = ptr2;;) { + if (ptr3[-1] != nine) { + ptr3[-1] = (ptr3[-1] == '9') ? 'a' : ptr3[-1] + 1; + break; + } + *--ptr3 = '0'; + if (ptr3 <= ptr) { + /* prepend a '1' if number was all nines */ + *--ptr = '1'; + break; + } + } + } else { + /* increment the last fractional digit */ + ptr2[-1] = (ptr2[-1] == '9') ? 'a' : ptr2[-1] + 1; + } + } else { + /* strip trailing fractional zeros */ + while (ptr2[-1] == '0') + ptr2--; + /* strip the 'decimal' point if last */ + ptr2 -= (ptr2[-1] == '.'); + } + } +done: + ptr[-1] = '-'; + ptr -= sign; + return js_new_string8_len(ctx, ptr, ptr2 - ptr); +} + +JSValue JS_ToStringInternal(JSContext *ctx, JSValue val, BOOL is_ToPropertyKey) { uint32_t tag; - const char *str; char buf[32]; + size_t len; tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_STRING: - return JS_DupValue(ctx, val); + return js_dup(val); case JS_TAG_INT: - snprintf(buf, sizeof(buf), "%d", JS_VALUE_GET_INT(val)); - str = buf; - goto new_string; + len = i32toa(buf, JS_VALUE_GET_INT(val)); + return js_new_string8_len(ctx, buf, len); case JS_TAG_BOOL: return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ? JS_ATOM_true : JS_ATOM_false); @@ -11613,33 +11709,25 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToProperty } break; case JS_TAG_FUNCTION_BYTECODE: - str = "[function bytecode]"; - goto new_string; + return js_new_string8(ctx, "[function bytecode]"); case JS_TAG_SYMBOL: if (is_ToPropertyKey) { - return JS_DupValue(ctx, val); + return js_dup(val); } else { return JS_ThrowTypeError(ctx, "cannot convert symbol to string"); } case JS_TAG_FLOAT64: - return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0, - JS_DTOA_VAR_FORMAT); + return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 0, JS_DTOA_TOSTRING); case JS_TAG_BIG_INT: - return ctx->rt->bigint_ops.to_string(ctx, val); -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - return ctx->rt->bigfloat_ops.to_string(ctx, val); - case JS_TAG_BIG_DECIMAL: - return ctx->rt->bigdecimal_ops.to_string(ctx, val); -#endif + return js_bigint_to_string(ctx, val); + case JS_TAG_UNINITIALIZED: + return js_new_string8(ctx, "[uninitialized]"); default: - str = "[unsupported type]"; - new_string: - return JS_NewString(ctx, str); + return js_new_string8(ctx, "[unsupported type]"); } } -JSValue JS_ToString(JSContext *ctx, JSValueConst val) +JSValue JS_ToString(JSContext *ctx, JSValue val) { return JS_ToStringInternal(ctx, val, FALSE); } @@ -11659,12 +11747,12 @@ static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val) return JS_InvokeFree(ctx, val, JS_ATOM_toLocaleString, 0, NULL); } -JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val) +JSValue JS_ToPropertyKey(JSContext *ctx, JSValue val) { return JS_ToStringInternal(ctx, val, TRUE); } -static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val) +static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValue val) { uint32_t tag = JS_VALUE_GET_TAG(val); if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) @@ -11672,7 +11760,7 @@ static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val) return JS_ToString(ctx, val); } -static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) +static JSValue JS_ToQuotedString(JSContext *ctx, JSValue val1) { JSValue val; JSString *p; @@ -11718,9 +11806,9 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) goto fail; break; default: - if (c < 32 || (c >= 0xd800 && c < 0xe000)) { + if (c < 32 || is_surrogate(c)) { snprintf(buf, sizeof(buf), "\\u%04x", c); - if (string_buffer_puts8(b, buf)) + if (string_buffer_write8(b, (uint8_t*)buf, 6)) goto fail; } else { if (string_buffer_putc(b, c)) @@ -11778,7 +11866,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) switch (p->class_id) { case JS_CLASS_ARRAY: case JS_CLASS_ARGUMENTS: - JS_DumpValueShort(rt, p->u.array.u.values[i]); + JS_DumpValue(rt, p->u.array.u.values[i]); break; case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_INT8_ARRAY: @@ -11789,6 +11877,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) case JS_CLASS_UINT32_ARRAY: case JS_CLASS_BIG_INT64_ARRAY: case JS_CLASS_BIG_UINT64_ARRAY: + case JS_CLASS_FLOAT16_ARRAY: case JS_CLASS_FLOAT32_ARRAY: case JS_CLASS_FLOAT64_ARRAY: { @@ -11823,14 +11912,14 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) js_autoinit_get_id(pr), (void *)pr->u.init.opaque); } else { - JS_DumpValueShort(rt, pr->u.value); + JS_DumpValue(rt, pr->u.value); } is_first = FALSE; } } printf(" }"); } - + if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; JSVarRef **var_refs; @@ -11839,11 +11928,11 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) printf(" Closure:"); for(i = 0; i < b->closure_var_count; i++) { printf(" "); - JS_DumpValueShort(rt, var_refs[i]->value); + JS_DumpValue(rt, var_refs[i]->value); } if (p->u.func.home_object) { printf(" HomeObject: "); - JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object)); + JS_DumpValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object)); } } } @@ -11882,8 +11971,7 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) } } -static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, - JSValueConst val) +static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValue val) { uint32_t tag = JS_VALUE_GET_NORM_TAG(val); const char *str; @@ -11917,7 +12005,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, break; case JS_TAG_BIG_INT: { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); char *str; str = bf_ftoa(NULL, &p->num, 10, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC); @@ -11925,28 +12013,6 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, bf_realloc(&rt->bf_ctx, str, 0); } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - char *str; - str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF, - BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX); - printf("%sl", str); - bf_free(&rt->bf_ctx, str); - } - break; - case JS_TAG_BIG_DECIMAL: - { - JSBigDecimal *p = JS_VALUE_GET_PTR(val); - char *str; - str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF, - BF_RNDZ | BF_FTOA_FORMAT_FREE); - printf("%sm", str); - bf_free(&rt->bf_ctx, str); - } - break; -#endif case JS_TAG_STRING: { JSString *p; @@ -11958,7 +12024,11 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, { JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); char buf[ATOM_GET_STR_BUF_SIZE]; - printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); + if (b->func_name) { + printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); + } else { + printf("[bytecode (anonymous)]"); + } } break; case JS_TAG_OBJECT: @@ -11987,23 +12057,8 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, } } -static __maybe_unused void JS_DumpValue(JSContext *ctx, - JSValueConst val) -{ - JS_DumpValueShort(ctx->rt, val); -} - -static __maybe_unused void JS_PrintValue(JSContext *ctx, - const char *str, - JSValueConst val) -{ - printf("%s=", str); - JS_DumpValueShort(ctx->rt, val); - printf("\n"); -} - /* return -1 if exception (proxy case) or TRUE/FALSE */ -int JS_IsArray(JSContext *ctx, JSValueConst val) +int JS_IsArray(JSContext *ctx, JSValue val) { JSObject *p; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { @@ -12017,7 +12072,7 @@ int JS_IsArray(JSContext *ctx, JSValueConst val) } } -static double js_pow(double a, double b) +static double js_math_pow(double a, double b) { if (unlikely(!isfinite(b)) && fabs(a) == 1) { /* not compatible with IEEE 754 */ @@ -12027,7 +12082,7 @@ static double js_pow(double a, double b) } } -JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v) +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) { JSValue val; bf_t *a; @@ -12042,65 +12097,81 @@ JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v) return val; } -JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) -{ - if (is_math_mode(ctx) && - v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) { - return JS_NewInt64(ctx, v); - } else { - return JS_NewBigInt64_1(ctx, v); - } -} - JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) { JSValue val; - if (is_math_mode(ctx) && v <= MAX_SAFE_INTEGER) { - val = JS_NewInt64(ctx, v); - } else { - bf_t *a; - val = JS_NewBigInt(ctx); - if (JS_IsException(val)) - return val; - a = JS_GetBigInt(val); - if (bf_set_ui(a, v)) { - JS_FreeValue(ctx, val); - return JS_ThrowOutOfMemory(ctx); - } + bf_t *a; + val = JS_NewBigInt(ctx); + if (JS_IsException(val)) + return val; + a = JS_GetBigInt(val); + if (bf_set_ui(a, v)) { + JS_FreeValue(ctx, val); + return JS_ThrowOutOfMemory(ctx); } + return val; } +/* if the returned bigint is allocated it is equal to + 'buf'. Otherwise it is a pointer to the bigint in 'val'. Return + NULL in case of error. */ +// TODO(bnoordhuis) Merge with JS_ToBigInt() +static bf_t *JS_ToBigInt1(JSContext *ctx, bf_t *buf, JSValue val) +{ + uint32_t tag; + bf_t *r; + JSBigInt *p; + + tag = JS_VALUE_GET_NORM_TAG(val); + switch(tag) { + case JS_TAG_INT: + case JS_TAG_BOOL: + case JS_TAG_NULL: + r = buf; + bf_init(ctx->bf_ctx, r); + if (bf_set_si(r, JS_VALUE_GET_INT(val))) + goto fail; + break; + case JS_TAG_FLOAT64: + r = buf; + bf_init(ctx->bf_ctx, r); + if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) { + fail: + bf_delete(r); + return NULL; + } + break; + case JS_TAG_BIG_INT: + p = JS_VALUE_GET_PTR(val); + r = &p->num; + break; + case JS_TAG_UNDEFINED: + default: + r = buf; + bf_init(ctx->bf_ctx, r); + bf_set_nan(r); + break; + } + return r; +} + /* return NaN if bad bigint literal */ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val) { - const char *str, *p; + const char *str; size_t len; int flags; - + str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) return JS_EXCEPTION; - p = str; - p += skip_spaces(p); - if ((p - str) == len) { - val = JS_NewBigInt64(ctx, 0); - } else { - flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT; -#ifdef CONFIG_BIGNUM - if (is_math_mode(ctx)) - flags |= ATOD_MODE_BIGINT; -#endif - val = js_atof(ctx, p, &p, 0, flags); - p += skip_spaces(p); - if (!JS_IsException(val)) { - if ((p - str) != len) { - JS_FreeValue(ctx, val); - val = JS_NAN; - } - } - } + flags = ATOD_WANT_BIG_INT | + ATOD_TRIM_SPACES | ATOD_ACCEPT_EMPTY | + ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT | + ATOD_DECIMAL_AFTER_SIGN | ATOD_NO_TRAILING_CHARS; + val = js_atof(ctx, str, len, NULL, 10, flags); JS_FreeCString(ctx, str); return val; } @@ -12109,17 +12180,17 @@ 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; } -/* if the returned bigfloat is allocated it is equal to - 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. */ +/* if the returned bigint is allocated it is equal to + 'buf'. Otherwise it is a pointer to the bigint in 'val'. */ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val) { uint32_t tag; bf_t *r; - JSBigFloat *p; + JSBigInt *p; redo: tag = JS_VALUE_GET_NORM_TAG(val); @@ -12127,45 +12198,17 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val) case JS_TAG_INT: case JS_TAG_NULL: case JS_TAG_UNDEFINED: - if (!is_math_mode(ctx)) - goto fail; - /* fall tru */ + case JS_TAG_FLOAT64: + goto fail; case JS_TAG_BOOL: r = buf; bf_init(ctx->bf_ctx, r); bf_set_si(r, JS_VALUE_GET_INT(val)); break; - case JS_TAG_FLOAT64: - { - double d = JS_VALUE_GET_FLOAT64(val); - if (!is_math_mode(ctx)) - goto fail; - if (!isfinite(d)) - goto fail; - r = buf; - bf_init(ctx->bf_ctx, r); - d = trunc(d); - bf_set_float64(r, d); - } - break; case JS_TAG_BIG_INT: p = JS_VALUE_GET_PTR(val); r = &p->num; break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - if (!is_math_mode(ctx)) - goto fail; - p = JS_VALUE_GET_PTR(val); - if (!bf_is_finite(&p->num)) - goto fail; - r = buf; - bf_init(ctx->bf_ctx, r); - bf_set(r, &p->num); - bf_rint(r, BF_RNDZ); - JS_FreeValue(ctx, val); - break; -#endif case JS_TAG_STRING: val = JS_StringToBigIntErr(ctx, val); if (JS_IsException(val)) @@ -12179,15 +12222,15 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val) default: fail: JS_FreeValue(ctx, val); - JS_ThrowTypeError(ctx, "cannot convert to bigint"); + JS_ThrowTypeError(ctx, "cannot convert to BigInt"); return NULL; } return r; } -static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val) +static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValue val) { - return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val)); + return JS_ToBigIntFree(ctx, buf, js_dup(val)); } static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) @@ -12197,7 +12240,7 @@ static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) } else { bf_t a_s, *a, *r; int ret; - JSValue res; + JSValue res; res = JS_NewBigInt(ctx); if (JS_IsException(res)) @@ -12224,8 +12267,7 @@ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf) if (a == buf) { bf_delete(a); } else { - JSBigFloat *p = (JSBigFloat *)((uint8_t *)a - - offsetof(JSBigFloat, num)); + JSBigInt *p = (JSBigInt *)((uint8_t *)a - offsetof(JSBigInt, num)); JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_INT, p)); } } @@ -12245,25 +12287,19 @@ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) return 0; } -int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValue val) { - return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val)); + return JS_ToBigInt64Free(ctx, pres, js_dup(val)); } -static JSBigFloat *js_new_bf(JSContext *ctx) +int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValue val) { - JSBigFloat *p; - p = js_malloc(ctx, sizeof(*p)); - if (!p) - return NULL; - p->header.ref_count = 1; - bf_init(ctx->bf_ctx, &p->num); - return p; + return JS_ToBigInt64Free(ctx, (int64_t *)pres, js_dup(val)); } static JSValue JS_NewBigInt(JSContext *ctx) { - JSBigFloat *p; + JSBigInt *p; p = js_malloc(ctx, sizeof(*p)); if (!p) return JS_EXCEPTION; @@ -12272,34 +12308,24 @@ static JSValue JS_NewBigInt(JSContext *ctx) return JS_MKPTR(JS_TAG_BIG_INT, p); } -static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val, - BOOL convert_to_safe_integer) +static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val) { - int64_t v; - bf_t *a; - if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT) return val; /* fail safe */ - a = JS_GetBigInt(val); - if (convert_to_safe_integer && bf_get_int64(&v, a, 0) == 0 && - v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) { - JS_FreeValue(ctx, val); - return JS_NewInt64(ctx, v); - } else if (a->expn == BF_EXP_ZERO && a->sign) { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - assert(p->header.ref_count == 1); + bf_t *a = JS_GetBigInt(val); + if (a->expn == BF_EXP_ZERO && a->sign) { + assert(((JSBigInt*)JS_VALUE_GET_PTR(val))->header.ref_count == 1); a->sign = 0; } return val; } -/* Convert the big int to a safe integer if in math mode. normalize - the zero representation. Could also be used to convert the bigint +/* Nnormalize the zero representation. Could also be used to convert the bigint to a short bigint value. The reference count of the value must be 1. Cannot fail */ static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val) { - return JS_CompactBigInt1(ctx, val, is_math_mode(ctx)); + return JS_CompactBigInt1(ctx, val); } static JSValue throw_bf_exception(JSContext *ctx, int status) @@ -12317,535 +12343,15 @@ static JSValue throw_bf_exception(JSContext *ctx, int status) return JS_ThrowRangeError(ctx, "%s", str); } -/* if the returned bigfloat is allocated it is equal to - 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return - NULL in case of error. */ -static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val) -{ - uint32_t tag; - bf_t *r; - JSBigFloat *p; - - tag = JS_VALUE_GET_NORM_TAG(val); - switch(tag) { - case JS_TAG_INT: - case JS_TAG_BOOL: - case JS_TAG_NULL: - r = buf; - bf_init(ctx->bf_ctx, r); - if (bf_set_si(r, JS_VALUE_GET_INT(val))) - goto fail; - break; - case JS_TAG_FLOAT64: - r = buf; - bf_init(ctx->bf_ctx, r); - if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) { - fail: - bf_delete(r); - return NULL; - } - break; - case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif - p = JS_VALUE_GET_PTR(val); - r = &p->num; - break; - case JS_TAG_UNDEFINED: - default: - r = buf; - bf_init(ctx->bf_ctx, r); - bf_set_nan(r); - break; - } - return r; -} - -#ifdef CONFIG_BIGNUM -/* return NULL if invalid type */ -static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val) -{ - uint32_t tag; - JSBigDecimal *p; - bfdec_t *r; - - tag = JS_VALUE_GET_NORM_TAG(val); - switch(tag) { - case JS_TAG_BIG_DECIMAL: - p = JS_VALUE_GET_PTR(val); - r = &p->num; - break; - default: - JS_ThrowTypeError(ctx, "bigdecimal expected"); - r = NULL; - break; - } - return r; -} - -static JSValue JS_NewBigFloat(JSContext *ctx) -{ - JSBigFloat *p; - p = js_malloc(ctx, sizeof(*p)); - if (!p) - return JS_EXCEPTION; - p->header.ref_count = 1; - bf_init(ctx->bf_ctx, &p->num); - return JS_MKPTR(JS_TAG_BIG_FLOAT, p); -} - -static JSValue JS_NewBigDecimal(JSContext *ctx) -{ - JSBigDecimal *p; - p = js_malloc(ctx, sizeof(*p)); - if (!p) - return JS_EXCEPTION; - p->header.ref_count = 1; - bfdec_init(ctx->bf_ctx, &p->num); - return JS_MKPTR(JS_TAG_BIG_DECIMAL, p); -} - -/* must be kept in sync with JSOverloadableOperatorEnum */ -/* XXX: use atoms ? */ -static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = { - "+", - "-", - "*", - "/", - "%", - "**", - "|", - "&", - "^", - "<<", - ">>", - ">>>", - "==", - "<", - "pos", - "neg", - "++", - "--", - "~", -}; - -static int get_ovop_from_opcode(OPCodeEnum op) -{ - switch(op) { - case OP_add: - return JS_OVOP_ADD; - case OP_sub: - return JS_OVOP_SUB; - case OP_mul: - return JS_OVOP_MUL; - case OP_div: - return JS_OVOP_DIV; - case OP_mod: - case OP_math_mod: - return JS_OVOP_MOD; - case OP_pow: - return JS_OVOP_POW; - case OP_or: - return JS_OVOP_OR; - case OP_and: - return JS_OVOP_AND; - case OP_xor: - return JS_OVOP_XOR; - case OP_shl: - return JS_OVOP_SHL; - case OP_sar: - return JS_OVOP_SAR; - case OP_shr: - return JS_OVOP_SHR; - case OP_eq: - case OP_neq: - return JS_OVOP_EQ; - case OP_lt: - case OP_lte: - case OP_gt: - case OP_gte: - return JS_OVOP_LESS; - case OP_plus: - return JS_OVOP_POS; - case OP_neg: - return JS_OVOP_NEG; - case OP_inc: - return JS_OVOP_INC; - case OP_dec: - return JS_OVOP_DEC; - default: - abort(); - } -} - -/* return NULL if not present */ -static JSObject *find_binary_op(JSBinaryOperatorDef *def, - uint32_t operator_index, - JSOverloadableOperatorEnum op) -{ - JSBinaryOperatorDefEntry *ent; - int i; - for(i = 0; i < def->count; i++) { - ent = &def->tab[i]; - if (ent->operator_index == operator_index) - return ent->ops[op]; - } - return NULL; -} - -/* return -1 if exception, 0 if no operator overloading, 1 if - overloaded operator called */ -static __exception int js_call_binary_op_fallback(JSContext *ctx, - JSValue *pret, - JSValueConst op1, - JSValueConst op2, - OPCodeEnum op, - BOOL is_numeric, - int hint) -{ - JSValue opset1_obj, opset2_obj, method, ret, new_op1, new_op2; - JSOperatorSetData *opset1, *opset2; - JSOverloadableOperatorEnum ovop; - JSObject *p; - JSValueConst args[2]; - - if (!ctx->allow_operator_overloading) - return 0; - - opset2_obj = JS_UNDEFINED; - opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet); - if (JS_IsException(opset1_obj)) - goto exception; - if (JS_IsUndefined(opset1_obj)) - return 0; - opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET); - if (!opset1) - goto exception; - - opset2_obj = JS_GetProperty(ctx, op2, JS_ATOM_Symbol_operatorSet); - if (JS_IsException(opset2_obj)) - goto exception; - if (JS_IsUndefined(opset2_obj)) { - JS_FreeValue(ctx, opset1_obj); - return 0; - } - opset2 = JS_GetOpaque2(ctx, opset2_obj, JS_CLASS_OPERATOR_SET); - if (!opset2) - goto exception; - - if (opset1->is_primitive && opset2->is_primitive) { - JS_FreeValue(ctx, opset1_obj); - JS_FreeValue(ctx, opset2_obj); - return 0; - } - - ovop = get_ovop_from_opcode(op); - - if (opset1->operator_counter == opset2->operator_counter) { - p = opset1->self_ops[ovop]; - } else if (opset1->operator_counter > opset2->operator_counter) { - p = find_binary_op(&opset1->left, opset2->operator_counter, ovop); - } else { - p = find_binary_op(&opset2->right, opset1->operator_counter, ovop); - } - if (!p) { - JS_ThrowTypeError(ctx, "operator %s: no function defined", - js_overloadable_operator_names[ovop]); - goto exception; - } - - if (opset1->is_primitive) { - if (is_numeric) { - new_op1 = JS_ToNumeric(ctx, op1); - } else { - new_op1 = JS_ToPrimitive(ctx, op1, hint); - } - if (JS_IsException(new_op1)) - goto exception; - } else { - new_op1 = JS_DupValue(ctx, op1); - } - - if (opset2->is_primitive) { - if (is_numeric) { - new_op2 = JS_ToNumeric(ctx, op2); - } else { - new_op2 = JS_ToPrimitive(ctx, op2, hint); - } - if (JS_IsException(new_op2)) { - JS_FreeValue(ctx, new_op1); - goto exception; - } - } else { - new_op2 = JS_DupValue(ctx, op2); - } - - /* XXX: could apply JS_ToPrimitive() if primitive type so that the - operator function does not get a value object */ - - method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); - if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) { - args[0] = new_op2; - args[1] = new_op1; - } else { - args[0] = new_op1; - args[1] = new_op2; - } - ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args); - JS_FreeValue(ctx, new_op1); - JS_FreeValue(ctx, new_op2); - if (JS_IsException(ret)) - goto exception; - if (ovop == JS_OVOP_EQ) { - BOOL res = JS_ToBoolFree(ctx, ret); - if (op == OP_neq) - res ^= 1; - ret = JS_NewBool(ctx, res); - } else if (ovop == JS_OVOP_LESS) { - if (JS_IsUndefined(ret)) { - ret = JS_FALSE; - } else { - BOOL res = JS_ToBoolFree(ctx, ret); - if (op == OP_lte || op == OP_gte) - res ^= 1; - ret = JS_NewBool(ctx, res); - } - } - JS_FreeValue(ctx, opset1_obj); - JS_FreeValue(ctx, opset2_obj); - *pret = ret; - return 1; - exception: - JS_FreeValue(ctx, opset1_obj); - JS_FreeValue(ctx, opset2_obj); - *pret = JS_UNDEFINED; - return -1; -} - -/* try to call the operation on the operatorSet field of 'obj'. Only - used for "/" and "**" on the BigInt prototype in math mode */ -static __exception int js_call_binary_op_simple(JSContext *ctx, - JSValue *pret, - JSValueConst obj, - JSValueConst op1, - JSValueConst op2, - OPCodeEnum op) -{ - JSValue opset1_obj, method, ret, new_op1, new_op2; - JSOperatorSetData *opset1; - JSOverloadableOperatorEnum ovop; - JSObject *p; - JSValueConst args[2]; - - opset1_obj = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet); - if (JS_IsException(opset1_obj)) - goto exception; - if (JS_IsUndefined(opset1_obj)) - return 0; - opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET); - if (!opset1) - goto exception; - ovop = get_ovop_from_opcode(op); - - p = opset1->self_ops[ovop]; - if (!p) { - JS_FreeValue(ctx, opset1_obj); - return 0; - } - - new_op1 = JS_ToNumeric(ctx, op1); - if (JS_IsException(new_op1)) - goto exception; - new_op2 = JS_ToNumeric(ctx, op2); - if (JS_IsException(new_op2)) { - JS_FreeValue(ctx, new_op1); - goto exception; - } - - method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); - args[0] = new_op1; - args[1] = new_op2; - ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args); - JS_FreeValue(ctx, new_op1); - JS_FreeValue(ctx, new_op2); - if (JS_IsException(ret)) - goto exception; - JS_FreeValue(ctx, opset1_obj); - *pret = ret; - return 1; - exception: - JS_FreeValue(ctx, opset1_obj); - *pret = JS_UNDEFINED; - return -1; -} - -/* return -1 if exception, 0 if no operator overloading, 1 if - overloaded operator called */ -static __exception int js_call_unary_op_fallback(JSContext *ctx, - JSValue *pret, - JSValueConst op1, - OPCodeEnum op) -{ - JSValue opset1_obj, method, ret; - JSOperatorSetData *opset1; - JSOverloadableOperatorEnum ovop; - JSObject *p; - - if (!ctx->allow_operator_overloading) - return 0; - - opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet); - if (JS_IsException(opset1_obj)) - goto exception; - if (JS_IsUndefined(opset1_obj)) - return 0; - opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET); - if (!opset1) - goto exception; - if (opset1->is_primitive) { - JS_FreeValue(ctx, opset1_obj); - return 0; - } - - ovop = get_ovop_from_opcode(op); - - p = opset1->self_ops[ovop]; - if (!p) { - JS_ThrowTypeError(ctx, "no overloaded operator %s", - js_overloadable_operator_names[ovop]); - goto exception; - } - method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); - ret = JS_CallFree(ctx, method, JS_UNDEFINED, 1, &op1); - if (JS_IsException(ret)) - goto exception; - JS_FreeValue(ctx, opset1_obj); - *pret = ret; - return 1; - exception: - JS_FreeValue(ctx, opset1_obj); - *pret = JS_UNDEFINED; - return -1; -} - -static int js_unary_arith_bigfloat(JSContext *ctx, - JSValue *pres, OPCodeEnum op, JSValue op1) -{ - bf_t a_s, *r, *a; - int ret, v; - JSValue res; - - if (op == OP_plus && !is_math_mode(ctx)) { - JS_ThrowTypeError(ctx, "bigfloat argument with unary +"); - JS_FreeValue(ctx, op1); - return -1; - } - - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) { - JS_FreeValue(ctx, op1); - return -1; - } - r = JS_GetBigFloat(res); - a = JS_ToBigFloat(ctx, &a_s, op1); - if (!a) { - JS_FreeValue(ctx, res); - JS_FreeValue(ctx, op1); - return -1; - } - ret = 0; - switch(op) { - case OP_inc: - case OP_dec: - v = 2 * (op - OP_dec) - 1; - ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case OP_plus: - ret = bf_set(r, a); - break; - case OP_neg: - ret = bf_set(r, a); - bf_neg(r); - break; - default: - abort(); - } - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, op1); - if (unlikely(ret & BF_ST_MEM_ERROR)) { - JS_FreeValue(ctx, res); - throw_bf_exception(ctx, ret); - return -1; - } - *pres = res; - return 0; -} - -static int js_unary_arith_bigdecimal(JSContext *ctx, - JSValue *pres, OPCodeEnum op, JSValue op1) -{ - bfdec_t *r, *a; - int ret, v; - JSValue res; - - if (op == OP_plus && !is_math_mode(ctx)) { - JS_ThrowTypeError(ctx, "bigdecimal argument with unary +"); - JS_FreeValue(ctx, op1); - return -1; - } - - res = JS_NewBigDecimal(ctx); - if (JS_IsException(res)) { - JS_FreeValue(ctx, op1); - return -1; - } - r = JS_GetBigDecimal(res); - a = JS_ToBigDecimal(ctx, op1); - if (!a) { - JS_FreeValue(ctx, res); - JS_FreeValue(ctx, op1); - return -1; - } - ret = 0; - switch(op) { - case OP_inc: - case OP_dec: - v = 2 * (op - OP_dec) - 1; - ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ); - break; - case OP_plus: - ret = bfdec_set(r, a); - break; - case OP_neg: - ret = bfdec_set(r, a); - bfdec_neg(r); - break; - default: - abort(); - } - JS_FreeValue(ctx, op1); - if (unlikely(ret)) { - JS_FreeValue(ctx, res); - throw_bf_exception(ctx, ret); - return -1; - } - *pres = res; - return 0; -} - -#endif /* CONFIG_BIGNUM */ - static int js_unary_arith_bigint(JSContext *ctx, JSValue *pres, OPCodeEnum op, JSValue op1) { bf_t a_s, *r, *a; int ret, v; JSValue res; - - if (op == OP_plus && !is_math_mode(ctx)) { - JS_ThrowTypeError(ctx, "bigint argument with unary +"); + + if (op == OP_plus) { + JS_ThrowTypeError(ctx, "BigInt argument with unary +"); JS_FreeValue(ctx, op1); return -1; } @@ -12855,12 +12361,7 @@ static int js_unary_arith_bigint(JSContext *ctx, return -1; } r = JS_GetBigInt(res); - a = JS_ToBigInt(ctx, &a_s, op1); - if (!a) { - JS_FreeValue(ctx, res); - JS_FreeValue(ctx, op1); - return -1; - } + a = JS_ToBigIntFree(ctx, &a_s, op1); // infallible, always a bigint ret = 0; switch(op) { case OP_inc: @@ -12883,7 +12384,6 @@ static int js_unary_arith_bigint(JSContext *ctx, abort(); } JS_FreeBigInt(ctx, a, &a_s); - JS_FreeValue(ctx, op1); if (unlikely(ret)) { JS_FreeValue(ctx, res); throw_bf_exception(ctx, ret); @@ -12906,19 +12406,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, /* fast path for float64 */ if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1))) goto handle_float64; -#ifdef CONFIG_BIGNUM - if (JS_IsObject(op1)) { - JSValue val; - int ret = js_call_unary_op_fallback(ctx, &val, op1, op); - if (ret < 0) - return -1; - if (ret) { - JS_FreeValue(ctx, op1); - sp[-1] = val; - return 0; - } - } -#endif + op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) goto exception; @@ -12938,7 +12426,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, break; case OP_neg: if (v64 == 0) { - sp[-1] = __JS_NewFloat64(ctx, -0.0); + sp[-1] = js_float64(-0.0); return 0; } else { v64 = -v64; @@ -12947,31 +12435,17 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, default: abort(); } - sp[-1] = JS_NewInt64(ctx, v64); + sp[-1] = js_int64(v64); } break; case JS_TAG_BIG_INT: - handle_bigint: - if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1)) + if (js_unary_arith_bigint(ctx, sp - 1, op, op1)) goto exception; break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1)) - goto exception; - break; - case JS_TAG_BIG_DECIMAL: - if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1)) - goto exception; - break; -#endif default: handle_float64: { - double d; - if (is_math_mode(ctx)) - goto handle_bigint; - d = JS_VALUE_GET_FLOAT64(op1); + double d = JS_VALUE_GET_FLOAT64(op1); switch(op) { case OP_inc: case OP_dec: @@ -12986,7 +12460,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx, default: abort(); } - sp[-1] = __JS_NewFloat64(ctx, d); + sp[-1] = js_float64(d); } break; } @@ -13009,39 +12483,25 @@ static __exception int js_post_inc_slow(JSContext *ctx, return -1; } sp[-1] = op1; - sp[0] = JS_DupValue(ctx, op1); + sp[0] = js_dup(op1); return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec); } static no_inline int js_not_slow(JSContext *ctx, JSValue *sp) { JSValue op1; - - op1 = sp[-1]; -#ifdef CONFIG_BIGNUM - if (JS_IsObject(op1)) { - JSValue val; - int ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not); - if (ret < 0) - return -1; - if (ret) { - JS_FreeValue(ctx, op1); - sp[-1] = val; - return 0; - } - } -#endif - op1 = JS_ToNumericFree(ctx, op1); + + op1 = JS_ToNumericFree(ctx, sp[-1]); if (JS_IsException(op1)) goto exception; - if (is_math_mode(ctx) || JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) { - if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1)) + if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) { + if (js_unary_arith_bigint(ctx, sp - 1, OP_not, op1)) goto exception; } else { int32_t v1; if (unlikely(JS_ToInt32Free(ctx, &v1, op1))) goto exception; - sp[-1] = JS_NewInt32(ctx, ~v1); + sp[-1] = js_int32(~v1); } return 0; exception: @@ -13055,17 +12515,22 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, bf_t a_s, b_s, *r, *a, *b; int ret; JSValue res; - - res = JS_NewBigInt(ctx); - if (JS_IsException(res)) - goto fail; - a = JS_ToBigInt(ctx, &a_s, op1); - if (!a) - goto fail; - b = JS_ToBigInt(ctx, &b_s, op2); + + a = JS_ToBigIntFree(ctx, &a_s, op1); + if (!a) { + JS_FreeValue(ctx, op2); + return -1; + } + b = JS_ToBigIntFree(ctx, &b_s, op2); if (!b) { JS_FreeBigInt(ctx, a, &a_s); - goto fail; + return -1; + } + res = JS_NewBigInt(ctx); + if (JS_IsException(res)) { + JS_FreeBigInt(ctx, a, &a_s); + JS_FreeBigInt(ctx, b, &b_s); + return -1; } r = JS_GetBigInt(res); ret = 0; @@ -13080,78 +12545,20 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ); break; case OP_div: - if (!is_math_mode(ctx)) { + { bf_t rem_s, *rem = &rem_s; bf_init(ctx->bf_ctx, rem); - ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ, - BF_RNDZ); + ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ); bf_delete(rem); - } else { - goto math_mode_div_pow; } break; -#ifdef CONFIG_BIGNUM - case OP_math_mod: - /* Euclidian remainder */ - ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ, - BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP; - break; -#endif case OP_mod: ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ) & BF_ST_INVALID_OP; break; case OP_pow: if (b->sign) { - if (!is_math_mode(ctx)) { - ret = BF_ST_INVALID_OP; - } else { - math_mode_div_pow: -#ifdef CONFIG_BIGNUM - JS_FreeValue(ctx, res); - ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op); - if (ret != 0) { - JS_FreeBigInt(ctx, a, &a_s); - JS_FreeBigInt(ctx, b, &b_s); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (ret < 0) { - return -1; - } else { - *pres = res; - return 0; - } - } - /* if no BigInt power operator defined, return a - bigfloat */ - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) { - JS_FreeBigInt(ctx, a, &a_s); - JS_FreeBigInt(ctx, b, &b_s); - goto fail; - } - r = JS_GetBigFloat(res); - if (op == OP_div) { - ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags) & BF_ST_MEM_ERROR; - } else { - ret = bf_pow(r, a, b, ctx->fp_env.prec, - ctx->fp_env.flags | BF_POW_JS_QUIRKS) & BF_ST_MEM_ERROR; - } - JS_FreeBigInt(ctx, a, &a_s); - JS_FreeBigInt(ctx, b, &b_s); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (unlikely(ret)) { - JS_FreeValue(ctx, res); - throw_bf_exception(ctx, ret); - return -1; - } - *pres = res; - return 0; -#else - abort(); -#endif - } + ret = BF_ST_INVALID_OP; } else { ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS); } @@ -13194,8 +12601,6 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, } JS_FreeBigInt(ctx, a, &a_s); JS_FreeBigInt(ctx, b, &b_s); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); if (unlikely(ret)) { JS_FreeValue(ctx, res); throw_bf_exception(ctx, ret); @@ -13203,174 +12608,8 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, } *pres = JS_CompactBigInt(ctx, res); return 0; - fail: - JS_FreeValue(ctx, res); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return -1; } -#ifdef CONFIG_BIGNUM -static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op, - JSValue *pres, JSValue op1, JSValue op2) -{ - bf_t a_s, b_s, *r, *a, *b; - int ret; - JSValue res; - - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) - goto fail; - r = JS_GetBigFloat(res); - a = JS_ToBigFloat(ctx, &a_s, op1); - if (!a) { - JS_FreeValue(ctx, res); - goto fail; - } - b = JS_ToBigFloat(ctx, &b_s, op2); - if (!b) { - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, res); - goto fail; - } - bf_init(ctx->bf_ctx, r); - switch(op) { - case OP_add: - ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case OP_sub: - ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case OP_mul: - ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case OP_div: - ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case OP_math_mod: - /* Euclidian remainder */ - ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags, - BF_DIVREM_EUCLIDIAN); - break; - case OP_mod: - ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags, - BF_RNDZ); - break; - case OP_pow: - ret = bf_pow(r, a, b, ctx->fp_env.prec, - ctx->fp_env.flags | BF_POW_JS_QUIRKS); - break; - default: - abort(); - } - if (a == &a_s) - bf_delete(a); - if (b == &b_s) - bf_delete(b); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (unlikely(ret & BF_ST_MEM_ERROR)) { - JS_FreeValue(ctx, res); - throw_bf_exception(ctx, ret); - return -1; - } - *pres = res; - return 0; - fail: - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return -1; -} - -/* b must be a positive integer */ -static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b) -{ - bfdec_t b1; - int32_t b2; - int ret; - - bfdec_init(b->ctx, &b1); - ret = bfdec_set(&b1, b); - if (ret) { - bfdec_delete(&b1); - return ret; - } - ret = bfdec_rint(&b1, BF_RNDZ); - if (ret) { - bfdec_delete(&b1); - return BF_ST_INVALID_OP; /* must be an integer */ - } - ret = bfdec_get_int32(&b2, &b1); - bfdec_delete(&b1); - if (ret) - return ret; /* overflow */ - if (b2 < 0) - return BF_ST_INVALID_OP; /* must be positive */ - return bfdec_pow_ui(r, a, b2); -} - -static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op, - JSValue *pres, JSValue op1, JSValue op2) -{ - bfdec_t *r, *a, *b; - int ret; - JSValue res; - - res = JS_NewBigDecimal(ctx); - if (JS_IsException(res)) - goto fail; - r = JS_GetBigDecimal(res); - - a = JS_ToBigDecimal(ctx, op1); - if (!a) - goto fail; - b = JS_ToBigDecimal(ctx, op2); - if (!b) - goto fail; - switch(op) { - case OP_add: - ret = bfdec_add(r, a, b, BF_PREC_INF, BF_RNDZ); - break; - case OP_sub: - ret = bfdec_sub(r, a, b, BF_PREC_INF, BF_RNDZ); - break; - case OP_mul: - ret = bfdec_mul(r, a, b, BF_PREC_INF, BF_RNDZ); - break; - case OP_div: - ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ); - break; - case OP_math_mod: - /* Euclidian remainder */ - ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_DIVREM_EUCLIDIAN); - break; - case OP_mod: - ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ); - break; - case OP_pow: - ret = js_bfdec_pow(r, a, b); - break; - default: - abort(); - } - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (unlikely(ret)) { - JS_FreeValue(ctx, res); - throw_bf_exception(ctx, ret); - return -1; - } - *pres = res; - return 0; - fail: - JS_FreeValue(ctx, res); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return -1; -} -#endif /* CONFIG_BIGNUM */ - static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { @@ -13389,27 +12628,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s goto handle_float64; } -#ifdef CONFIG_BIGNUM - /* try to call an overloaded operator */ - if ((tag1 == JS_TAG_OBJECT && - (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) || - (tag2 == JS_TAG_OBJECT && - (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) { - JSValue res; - int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0); - if (ret != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (ret < 0) { - goto exception; - } else { - sp[-2] = res; - return 0; - } - } - } -#endif - op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -13434,67 +12652,31 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s break; case OP_mul: v = (int64_t)v1 * (int64_t)v2; - if (is_math_mode(ctx) && - (v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER)) - goto handle_bigint; if (v == 0 && (v1 | v2) < 0) { - sp[-2] = __JS_NewFloat64(ctx, -0.0); + sp[-2] = js_float64(-0.0); return 0; } break; case OP_div: - if (is_math_mode(ctx)) - goto handle_bigint; - sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2); + sp[-2] = js_float64((double)v1 / (double)v2); return 0; -#ifdef CONFIG_BIGNUM - case OP_math_mod: - if (unlikely(v2 == 0)) { - throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO); - goto exception; - } - v = (int64_t)v1 % (int64_t)v2; - if (v < 0) { - if (v2 < 0) - v -= v2; - else - v += v2; - } - break; -#endif case OP_mod: if (v1 < 0 || v2 <= 0) { - sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2)); + sp[-2] = js_number(fmod(v1, v2)); return 0; } else { v = (int64_t)v1 % (int64_t)v2; } break; case OP_pow: - if (!is_math_mode(ctx)) { - sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2)); - return 0; - } else { - goto handle_bigint; - } - break; + sp[-2] = js_number(js_math_pow(v1, v2)); + return 0; default: abort(); } - sp[-2] = JS_NewInt64(ctx, v); - } else -#ifdef CONFIG_BIGNUM - if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) { - if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2)) - goto exception; - } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) { - if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2)) - goto exception; - } else -#endif - if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { - handle_bigint: - if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2)) + sp[-2] = js_int64(v); + } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { + if (js_binary_arith_bigint(ctx, op, sp - 2, op1, op2)) goto exception; } else { double dr; @@ -13506,8 +12688,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; handle_float64: - if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2)) - goto handle_bigint; switch(op) { case OP_sub: dr = d1 - d2; @@ -13521,22 +12701,13 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s case OP_mod: dr = fmod(d1, d2); break; -#ifdef CONFIG_BIGNUM - case OP_math_mod: - d2 = fabs(d2); - dr = fmod(d1, d2); - /* XXX: loss of accuracy if dr < 0 */ - if (dr < 0) - dr += d2; - break; -#endif case OP_pow: - dr = js_pow(d1, d2); + dr = js_math_pow(d1, d2); break; default: abort(); } - sp[-2] = __JS_NewFloat64(ctx, dr); + sp[-2] = js_float64(dr); } return 0; exception: @@ -13560,34 +12731,11 @@ 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_NewFloat64(ctx, d1 + d2); + sp[-2] = js_float64(d1 + d2); return 0; } if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) { -#ifdef CONFIG_BIGNUM - /* try to call an overloaded operator */ - if ((tag1 == JS_TAG_OBJECT && - (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED && - tag2 != JS_TAG_STRING)) || - (tag2 == JS_TAG_OBJECT && - (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED && - tag1 != JS_TAG_STRING))) { - JSValue res; - int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add, - FALSE, HINT_NONE); - if (ret != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (ret < 0) { - goto exception; - } else { - sp[-2] = res; - return 0; - } - } - } -#endif op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -13629,20 +12777,9 @@ 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_NewInt64(ctx, v); - } else -#ifdef CONFIG_BIGNUM - if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) { - if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) - goto exception; - } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) { - if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) - goto exception; - } else -#endif - if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { - handle_bigint: - if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2)) + sp[-2] = js_int64(v); + } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { + if (js_binary_arith_bigint(ctx, OP_add, sp - 2, op1, op2)) goto exception; } else { double d1, d2; @@ -13653,9 +12790,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) } if (JS_ToFloat64Free(ctx, &d2, op2)) goto exception; - if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2)) - goto handle_bigint; - sp[-2] = __JS_NewFloat64(ctx, d1 + d2); + sp[-2] = js_float64(d1 + d2); } return 0; exception: @@ -13677,27 +12812,6 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); -#ifdef CONFIG_BIGNUM - /* try to call an overloaded operator */ - if ((tag1 == JS_TAG_OBJECT && - (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) || - (tag2 == JS_TAG_OBJECT && - (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) { - JSValue res; - int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0); - if (ret != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (ret < 0) { - goto exception; - } else { - sp[-2] = res; - return 0; - } - } - } -#endif - op1 = JS_ToNumericFree(ctx, op1); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -13709,21 +12823,16 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, goto exception; } - if (is_math_mode(ctx)) - goto bigint_op; - tag1 = JS_VALUE_GET_TAG(op1); tag2 = JS_VALUE_GET_TAG(op2); if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { if (tag1 != tag2) { JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - JS_ThrowTypeError(ctx, "both operands must be bigint"); + JS_ThrowTypeError(ctx, "both operands must be BigInt"); + goto exception; + } else if (js_binary_arith_bigint(ctx, op, sp - 2, op1, op2)) { goto exception; - } else { - bigint_op: - if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2)) - goto exception; } } else { if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) { @@ -13751,7 +12860,7 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, default: abort(); } - sp[-2] = JS_NewInt32(ctx, r); + sp[-2] = js_int32(r); } return 0; exception: @@ -13760,19 +12869,18 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, return -1; } -/* Note: also used for bigint */ -static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op, - JSValue op1, JSValue op2) +static int js_compare_bigint(JSContext *ctx, OPCodeEnum op, + JSValue op1, JSValue op2) { bf_t a_s, b_s, *a, *b; int res; - - a = JS_ToBigFloat(ctx, &a_s, op1); + + a = JS_ToBigInt1(ctx, &a_s, op1); if (!a) { JS_FreeValue(ctx, op2); return -1; } - b = JS_ToBigFloat(ctx, &b_s, op2); + b = JS_ToBigInt1(ctx, &b_s, op2); if (!b) { if (a == &a_s) bf_delete(a); @@ -13807,54 +12915,6 @@ static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op, return res; } -#ifdef CONFIG_BIGNUM -static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op, - JSValue op1, JSValue op2) -{ - bfdec_t *a, *b; - int res; - - /* Note: binary floats are converted to bigdecimal with - toString(). It is not mathematically correct but is consistent - with the BigDecimal() constructor behavior */ - op1 = JS_ToBigDecimalFree(ctx, op1, TRUE); - if (JS_IsException(op1)) { - JS_FreeValue(ctx, op2); - return -1; - } - op2 = JS_ToBigDecimalFree(ctx, op2, TRUE); - if (JS_IsException(op2)) { - JS_FreeValue(ctx, op1); - return -1; - } - a = JS_ToBigDecimal(ctx, op1); /* cannot fail */ - b = JS_ToBigDecimal(ctx, op2); /* cannot fail */ - - switch(op) { - case OP_lt: - res = bfdec_cmp_lt(a, b); /* if NaN return false */ - break; - case OP_lte: - res = bfdec_cmp_le(a, b); /* if NaN return false */ - break; - case OP_gt: - res = bfdec_cmp_lt(b, a); /* if NaN return false */ - break; - case OP_gte: - res = bfdec_cmp_le(b, a); /* if NaN return false */ - break; - case OP_eq: - res = bfdec_cmp_eq(a, b); /* if NaN return false */ - break; - default: - abort(); - } - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return res; -} -#endif /* !CONFIG_BIGNUM */ - static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, OPCodeEnum op) { @@ -13866,27 +12926,7 @@ 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); -#ifdef CONFIG_BIGNUM - /* try to call an overloaded operator */ - if ((tag1 == JS_TAG_OBJECT && - (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) || - (tag2 == JS_TAG_OBJECT && - (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) { - JSValue ret; - res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op, - FALSE, HINT_NUMBER); - if (res != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (res < 0) { - goto exception; - } else { - sp[-2] = ret; - return 0; - } - } - } -#endif + op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -13904,7 +12944,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, JSString *p1, *p2; p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); - res = js_string_compare(ctx, p1, p2); + res = js_string_compare(p1, p2); switch(op) { case OP_lt: res = (res < 0); @@ -13928,8 +12968,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, goto float64_compare; } else { if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) || - (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) && - !is_math_mode(ctx)) { + (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING))) { if (tag1 == JS_TAG_STRING) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT) @@ -13961,19 +13000,8 @@ 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); -#ifdef CONFIG_BIGNUM - if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) { - res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2); - if (res < 0) - goto exception; - } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) { - res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2); - if (res < 0) - goto exception; - } else -#endif if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) { - res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2); + res = js_compare_bigint(ctx, op, op1, op2); if (res < 0) goto exception; } else { @@ -14009,7 +13037,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, } } done: - sp[-2] = JS_NewBool(ctx, res); + sp[-2] = js_bool(res); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14020,20 +13048,13 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, static BOOL tag_is_number(uint32_t tag) { return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT || - tag == JS_TAG_FLOAT64 -#ifdef CONFIG_BIGNUM - || tag == JS_TAG_BIG_FLOAT || tag == JS_TAG_BIG_DECIMAL -#endif - ); + tag == JS_TAG_FLOAT64); } static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, BOOL is_neq) { JSValue op1, op2; -#ifdef CONFIG_BIGNUM - JSValue ret; -#endif int res; uint32_t tag1, tag2; @@ -14061,42 +13082,12 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, d2 = JS_VALUE_GET_INT(op2); } res = (d1 == d2); - } else -#ifdef CONFIG_BIGNUM - if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) { - res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2); - if (res < 0) - goto exception; - } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) { - res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2); - if (res < 0) - goto exception; - } else -#endif - { - res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2); + } else { + res = js_compare_bigint(ctx, OP_eq, op1, op2); if (res < 0) goto exception; } } else if (tag1 == tag2) { -#ifdef CONFIG_BIGNUM - if (tag1 == JS_TAG_OBJECT) { - /* try the fallback operator */ - res = js_call_binary_op_fallback(ctx, &ret, op1, op2, - is_neq ? OP_neq : OP_eq, - FALSE, HINT_NONE); - if (res != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (res < 0) { - goto exception; - } else { - sp[-2] = ret; - return 0; - } - } - } -#endif 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)) { @@ -14104,8 +13095,7 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) || (tag2 == JS_TAG_STRING && tag_is_number(tag1))) { - if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) && - !is_math_mode(ctx)) { + if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT)) { if (tag1 == JS_TAG_STRING) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT) @@ -14135,31 +13125,15 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, } res = js_strict_eq(ctx, op1, op2); } else if (tag1 == JS_TAG_BOOL) { - op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1)); + op1 = js_int32(JS_VALUE_GET_INT(op1)); goto redo; } else if (tag2 == JS_TAG_BOOL) { - op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2)); + op2 = js_int32(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)) || (tag2 == JS_TAG_OBJECT && (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) { -#ifdef CONFIG_BIGNUM - /* try the fallback operator */ - res = js_call_binary_op_fallback(ctx, &ret, op1, op2, - is_neq ? OP_neq : OP_eq, - FALSE, HINT_NONE); - if (res != 0) { - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (res < 0) { - goto exception; - } else { - sp[-2] = ret; - return 0; - } - } -#endif op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -14185,7 +13159,7 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, JS_FreeValue(ctx, op2); } done: - sp[-2] = JS_NewBool(ctx, res ^ is_neq); + sp[-2] = js_bool(res ^ is_neq); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14210,11 +13184,10 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) JS_FreeValue(ctx, op1); goto exception; } - /* XXX: could forbid >>> in bignum mode */ - if (!is_math_mode(ctx) && - (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT || + + if ((JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT || JS_VALUE_GET_TAG(op2) == JS_TAG_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; @@ -14223,7 +13196,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_NewUint32(ctx, r); + sp[-2] = js_uint32(r); return 0; exception: sp[-2] = JS_UNDEFINED; @@ -14231,68 +13204,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) return -1; } -#ifdef CONFIG_BIGNUM -static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a, - int64_t exponent) -{ - bf_t r_s, *r = &r_s; - double d; - int ret; - - /* always convert to Float64 */ - bf_init(ctx->bf_ctx, r); - ret = bf_mul_pow_radix(r, a, 10, exponent, - 53, bf_set_exp_bits(11) | BF_RNDN | - BF_FLAG_SUBNORMAL); - bf_get_float64(r, &d, BF_RNDN); - bf_delete(r); - if (ret & BF_ST_MEM_ERROR) - return JS_ThrowOutOfMemory(ctx); - else - return __JS_NewFloat64(ctx, d); -} - -static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp) -{ - bf_t a_s, *a, *r; - JSValue op1, op2, res; - int64_t e; - int ret; - - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) - return -1; - r = JS_GetBigFloat(res); - op1 = sp[-2]; - op2 = sp[-1]; - a = JS_ToBigFloat(ctx, &a_s, op1); - if (!a) { - JS_FreeValue(ctx, res); - return -1; - } - if (JS_IsBigInt(ctx, op2)) { - ret = JS_ToBigInt64(ctx, &e, op2); - } else { - ret = JS_ToInt64(ctx, &e, op2); - } - if (ret) { - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, res); - return -1; - } - - bf_mul_pow_radix(r, a, 10, e, ctx->fp_env.prec, ctx->fp_env.flags); - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - sp[-2] = res; - return 0; -} -#endif - -/* XXX: Should take JSValueConst arguments */ +/* XXX: Should take JSValue arguments */ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode) { @@ -14323,7 +13235,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, } else { p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); - res = (js_string_compare(ctx, p1, p2) == 0); + res = js_string_eq(p1, p2); } } break; @@ -14391,8 +13303,8 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, res = FALSE; break; } - a = JS_ToBigFloat(ctx, &a_s, op1); /* cannot fail */ - b = JS_ToBigFloat(ctx, &b_s, op2); /* cannot fail */ + a = JS_ToBigInt1(ctx, &a_s, op1); + b = JS_ToBigInt1(ctx, &b_s, op2); res = bf_cmp_eq(a, b); if (a == &a_s) bf_delete(a); @@ -14400,47 +13312,6 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, bf_delete(b); } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p1, *p2; - const bf_t *a, *b; - if (tag1 != tag2) { - res = FALSE; - break; - } - p1 = JS_VALUE_GET_PTR(op1); - p2 = JS_VALUE_GET_PTR(op2); - a = &p1->num; - b = &p2->num; - if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) { - if (eq_mode == JS_EQ_SAME_VALUE_ZERO && - a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO) { - res = TRUE; - } else { - res = (bf_cmp_full(a, b) == 0); - } - } else { - res = bf_cmp_eq(a, b); - } - } - break; - case JS_TAG_BIG_DECIMAL: - { - JSBigDecimal *p1, *p2; - const bfdec_t *a, *b; - if (tag1 != tag2) { - res = FALSE; - break; - } - p1 = JS_VALUE_GET_PTR(op1); - p2 = JS_VALUE_GET_PTR(op2); - a = &p1->num; - b = &p2->num; - res = bfdec_cmp_eq(a, b); - } - break; -#endif default: res = FALSE; break; @@ -14456,18 +13327,14 @@ static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2) return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } -static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) +static BOOL js_same_value(JSContext *ctx, JSValue op1, JSValue op2) { - return js_strict_eq2(ctx, - JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), - JS_EQ_SAME_VALUE); + return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE); } -static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) +static BOOL js_same_value_zero(JSContext *ctx, JSValue op1, JSValue op2) { - return js_strict_eq2(ctx, - JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), - JS_EQ_SAME_VALUE_ZERO); + return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE_ZERO); } static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, @@ -14475,7 +13342,7 @@ static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, { BOOL res; res = js_strict_eq(ctx, sp[-2], sp[-1]); - sp[-2] = JS_NewBool(ctx, res ^ is_neq); + sp[-2] = js_bool(res ^ is_neq); return 0; } @@ -14501,7 +13368,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = JS_NewBool(ctx, ret); + sp[-2] = js_bool(ret); return 0; } @@ -14509,10 +13376,8 @@ 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; @@ -14542,7 +13407,7 @@ static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp) return 0; } -static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj, +static __exception int js_has_unscopable(JSContext *ctx, JSValue obj, JSAtom atom) { JSValue arr, val; @@ -14572,11 +13437,11 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) return ret; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = JS_NewBool(ctx, ret); + sp[-2] = js_bool(ret); return 0; } -static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1) +static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) { JSAtom atom; uint32_t tag; @@ -14586,14 +13451,6 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1) case JS_TAG_BIG_INT: atom = JS_ATOM_bigint; break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - atom = JS_ATOM_bigfloat; - break; - case JS_TAG_BIG_DECIMAL: - atom = JS_ATOM_bigdecimal; - break; -#endif case JS_TAG_INT: case JS_TAG_FLOAT64: atom = JS_ATOM_number; @@ -14611,7 +13468,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1) { JSObject *p; p = JS_VALUE_GET_OBJ(op1); - if (unlikely(p->is_HTMLDDA)) + if (unlikely(p->is_HTMLDDA)) atom = JS_ATOM_undefined; else if (JS_IsFunction(ctx, op1)) atom = JS_ATOM_function; @@ -14650,12 +13507,12 @@ static __exception int js_operator_delete(JSContext *ctx, JSValue *sp) return -1; JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - sp[-2] = JS_NewBool(ctx, ret); + sp[-2] = js_bool(ret); return 0; } -static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_throw_type_error(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_ThrowTypeError(ctx, "invalid property access"); } @@ -14663,40 +13520,42 @@ static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val, /* 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_function_proto_caller(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_proto_caller(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype) { + if (!b || b->is_strict_mode || !b->has_prototype) { return js_throw_type_error(ctx, this_val, 0, NULL); } return JS_UNDEFINED; } static JSValue js_function_proto_fileName(JSContext *ctx, - JSValueConst this_val) + JSValue this_val) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (b && b->has_debug) { - return JS_AtomToString(ctx, b->debug.filename); + if (b) { + return JS_AtomToString(ctx, b->filename); } return JS_UNDEFINED; } -static JSValue js_function_proto_lineNumber(JSContext *ctx, - JSValueConst this_val) +static JSValue js_function_proto_int32(JSContext *ctx, + JSValue this_val, + int magic) { JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); - if (b && b->has_debug) { - return JS_NewInt32(ctx, b->debug.line_num); + if (b) { + int *field = (int *) ((char *)b + magic); + return js_int32(*field); } return JS_UNDEFINED; } static int js_arguments_define_own_property(JSContext *ctx, - JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, int flags) + JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags) { JSObject *p; uint32_t idx; @@ -14716,7 +13575,7 @@ static const JSClassExoticMethods js_arguments_exotic_methods = { .define_own_property = js_arguments_define_own_property, }; -static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) +static JSValue js_build_arguments(JSContext *ctx, int argc, JSValue *argv) { JSValue val, *tab; JSProperty *pr; @@ -14732,7 +13591,11 @@ 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); - pr->u.value = JS_NewInt32(ctx, argc); + if (!pr) { + JS_FreeValue(ctx, val); + return JS_EXCEPTION; + } + pr->u.value = js_int32(argc); /* initialize the fast array part */ tab = NULL; @@ -14743,14 +13606,14 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) return JS_EXCEPTION; } for(i = 0; i < argc; i++) { - tab[i] = JS_DupValue(ctx, argv[i]); + tab[i] = js_dup(argv[i]); } } p->u.array.u.values = tab; p->u.array.count = argc; JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - JS_DupValue(ctx, ctx->array_proto_values), + js_dup(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, @@ -14764,7 +13627,7 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) /* legacy arguments object: add references to the function arguments */ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, - JSValueConst *argv, + JSValue *argv, JSStackFrame *sf, int arg_count) { JSValue val; @@ -14781,7 +13644,9 @@ 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); - pr->u.value = JS_NewInt32(ctx, argc); + if (!pr) + goto fail; + pr->u.value = js_int32(argc); for(i = 0; i < arg_count; i++) { JSVarRef *var_ref; @@ -14800,17 +13665,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_DupValue(ctx, argv[i]), + js_dup(argv[i]), JS_PROP_C_W_E) < 0) goto fail; } JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - JS_DupValue(ctx, ctx->array_proto_values), + js_dup(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_DupValue(ctx, ctx->rt->current_stack_frame->cur_func), + js_dup(ctx->rt->current_stack_frame->cur_func), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); return val; fail: @@ -14818,7 +13683,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, return JS_EXCEPTION; } -static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv) +static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValue *argv) { JSValue val; int i, ret; @@ -14828,7 +13693,7 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst * return val; for (i = first; i < argc; i++) { ret = JS_DefinePropertyValueUint32(ctx, val, i - first, - JS_DupValue(ctx, argv[i]), + js_dup(argv[i]), JS_PROP_C_W_E); if (ret < 0) { JS_FreeValue(ctx, val); @@ -14840,10 +13705,10 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst * static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) { - JSObject *p, *p1; + JSObject *p; JSPropertyEnum *tab_atom; int i; - JSValue enum_obj; + JSValue enum_obj, obj1; JSForInIterator *it; uint32_t tag, tab_atom_count; @@ -14866,65 +13731,14 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) it->is_array = FALSE; it->obj = obj; it->idx = 0; - 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; + p = JS_VALUE_GET_OBJ(enum_obj); + p->u.for_in_iterator = it; if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) return enum_obj; - p = JS_VALUE_GET_OBJ(obj); - if (p->fast_array) { - JSShape *sh; - JSShapeProperty *prs; - /* check that there are no enumerable normal fields */ - sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { - if (prs->flags & JS_PROP_ENUMERABLE) - goto normal_case; - } - /* for fast arrays, we only store the number of elements */ - 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_SET_ENUM)) { - JS_FreeValue(ctx, enum_obj); - return JS_EXCEPTION; - } - it->tab_atom = tab_atom; - it->atom_count = tab_atom_count; - } - return enum_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); + /* fast path: assume no enumerable properties in the prototype chain */ + obj1 = js_dup(obj); for(;;) { obj1 = JS_GetPrototypeFree(ctx, obj1); if (JS_IsNull(obj1)) @@ -14948,40 +13762,84 @@ static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx, goto fail; } } - JS_FreeValue(ctx, obj1); - return 1; + + p = JS_VALUE_GET_OBJ(obj); + + if (p->fast_array) { + JSShape *sh; + JSShapeProperty *prs; + /* check that there are no enumerable normal fields */ + sh = p->shape; + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + if (prs->flags & JS_PROP_ENUMERABLE) + goto normal_case; + } + /* for fast arrays, we only store the number of elements */ + it->is_array = TRUE; + it->array_length = 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_free_prop_enum(ctx, tab_atom, tab_atom_count); + } + return enum_obj; slow_path: - /* add the visited properties, even if they are not enumerable */ - if (it->is_array) { + /* non enumerable properties hide the enumerables ones in the + prototype chain */ + obj1 = js_dup(obj); + for(;;) { if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, - JS_VALUE_GET_OBJ(it->obj), + JS_VALUE_GET_OBJ(obj1), JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) { + JS_FreeValue(ctx, obj1); goto fail; } - it->is_array = FALSE; - it->tab_atom = tab_atom; - it->atom_count = tab_atom_count; - } - - 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) + 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_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 0; + return enum_obj; + fail: - return -1; + JS_FreeValue(ctx, enum_obj); + return JS_EXCEPTION; +} + +/* 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; } /* enum_obj -> enum_obj value done */ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) { - JSValueConst enum_obj; + JSValue enum_obj; JSObject *p; JSAtom prop; JSForInIterator *it; - JSPropertyEnum *tab_atom; - uint32_t tab_atom_count; int ret; enum_obj = sp[-1]; @@ -14994,68 +13852,34 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) it = p->u.for_in_iterator; for(;;) { - 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_free_prop_enum(ctx, it->tab_atom, it->atom_count); - it->tab_atom = tab_atom; - it->atom_count = tab_atom_count; - it->idx = 0; + if (it->is_array) { + if (it->idx >= it->array_length) + goto done; + prop = __JS_AtomFromUInt32(it->idx); + it->idx++; } else { - 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) + 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) break; } + ret = JS_HasProperty(ctx, obj, prop); + if (ret < 0) + return ret; + if (ret) + break; } /* return the property */ sp[0] = JS_AtomToValue(ctx, prop); @@ -15068,8 +13892,8 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) return 0; } -static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj, - JSValueConst method) +static JSValue JS_GetIterator2(JSContext *ctx, JSValue obj, + JSValue method) { JSValue enum_obj; @@ -15083,7 +13907,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, JSValue obj, BOOL is_async) { JSValue method, ret, sync_iter; @@ -15118,9 +13942,9 @@ static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async) } /* return *pdone = 2 if the iterator object is not parsed */ -static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj, - JSValueConst method, - int argc, JSValueConst *argv, int *pdone) +static JSValue JS_IteratorNext2(JSContext *ctx, JSValue enum_obj, + JSValue method, + int argc, JSValue *argv, int *pdone) { JSValue obj; @@ -15131,7 +13955,7 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj, if (p->class_id == JS_CLASS_C_FUNCTION && p->u.cfunc.cproto == JS_CFUNC_iterator_next) { JSCFunctionType func; - JSValueConst args[1]; + JSValue args[1]; /* in case the function expects one argument */ if (argc == 0) { @@ -15158,9 +13982,9 @@ static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj, return JS_EXCEPTION; } -static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, - JSValueConst method, - int argc, JSValueConst *argv, BOOL *pdone) +static JSValue JS_IteratorNext(JSContext *ctx, JSValue enum_obj, + JSValue method, + int argc, JSValue *argv, BOOL *pdone) { JSValue obj, value, done_val; int done; @@ -15190,7 +14014,7 @@ static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj, } /* return < 0 in case of exception */ -static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj, +static int JS_IteratorClose(JSContext *ctx, JSValue enum_obj, BOOL is_exception_pending) { JSValue method, ret, ex_obj; @@ -15198,7 +14022,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj, if (is_exception_pending) { ex_obj = ctx->rt->current_exception; - ctx->rt->current_exception = JS_NULL; + ctx->rt->current_exception = JS_UNINITIALIZED; res = -1; } else { ex_obj = JS_UNDEFINED; @@ -15274,11 +14098,11 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset) } } sp[0] = value; - sp[1] = JS_NewBool(ctx, done); + sp[1] = js_bool(done); return 0; } -static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj, +static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj, BOOL *pdone) { JSValue done_val, value; @@ -15311,7 +14135,7 @@ static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) return -1; JS_FreeValue(ctx, obj); sp[-1] = value; - sp[0] = JS_NewBool(ctx, done); + sp[0] = js_bool(done); return 0; } @@ -15330,7 +14154,7 @@ static JSValue js_create_iterator_result(JSContext *ctx, goto fail; } if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done, - JS_NewBool(ctx, done), JS_PROP_C_W_E) < 0) { + js_bool(done), JS_PROP_C_W_E) < 0) { fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -15338,14 +14162,14 @@ static JSValue js_create_iterator_result(JSContext *ctx, return obj; } -static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_array_iterator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic); -static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic); +static JSValue js_create_array_iterator(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic); -static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj) +static BOOL js_is_fast_array(JSContext *ctx, JSValue obj) { /* Try and handle fast arrays explicitly */ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { @@ -15358,7 +14182,7 @@ static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj) } /* Access an Array's internal JSValue array if available */ -static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, +static BOOL js_get_fast_array(JSContext *ctx, JSValue obj, JSValue **arrpp, uint32_t *countp) { /* Try and handle fast arrays explicitly */ @@ -15379,7 +14203,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) int is_array_iterator; JSValue *arrp; uint32_t i, count32, pos; - + if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) { JS_ThrowInternalError(ctx, "invalid index for append"); return -1; @@ -15396,8 +14220,10 @@ 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, - (JSCFunction *)js_create_array_iterator, + ft.generic, JS_ITERATOR_KIND_VALUE); JS_FreeValue(ctx, iterator); @@ -15409,9 +14235,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 }; if (is_array_iterator - && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0) - && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) { + && JS_IsCFunction(ctx, method, ft2.generic, 0) + && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) { uint32_t len; if (js_get_length32(ctx, &len, sp[-1])) goto exception; @@ -15422,7 +14250,7 @@ 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_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0) + js_dup(arrp[i]), JS_PROP_C_W_E) < 0) goto exception; } } else { @@ -15441,7 +14269,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) } } /* Note: could raise an error if too many elements */ - sp[-2] = JS_NewInt32(ctx, pos); + sp[-2] = js_int32(pos); JS_FreeValue(ctx, enumobj); JS_FreeValue(ctx, method); return 0; @@ -15454,9 +14282,9 @@ exception: } static __exception int JS_CopyDataProperties(JSContext *ctx, - JSValueConst target, - JSValueConst source, - JSValueConst excluded, + JSValue target, + JSValue source, + JSValue excluded, BOOL setprop) { JSPropertyEnum *tab_atom; @@ -15467,7 +14295,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, int ret, gpn_flags; JSPropertyDescriptor desc; BOOL is_enumerable; - + if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT) return 0; @@ -15488,7 +14316,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, gpn_flags)) return -1; - + for (i = 0; i < tab_atom_count; i++) { if (pexcl) { ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom); @@ -15529,7 +14357,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, } /* only valid inside C functions */ -static JSValueConst JS_GetActiveFunction(JSContext *ctx) +static JSValue JS_GetActiveFunction(JSContext *ctx) { return ctx->rt->current_stack_frame->cur_func; } @@ -15541,7 +14369,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, struct list_head *el; list_for_each(el, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, var_ref_link); + var_ref = list_entry(el, JSVarRef, header.link); if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) { var_ref->header.ref_count++; return var_ref; @@ -15552,29 +14380,15 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, if (!var_ref) return NULL; var_ref->header.ref_count = 1; - add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); var_ref->is_detached = FALSE; var_ref->is_arg = is_arg; var_ref->var_idx = var_idx; - 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; - } + list_add_tail(&var_ref->header.link, &sf->var_ref_list); if (is_arg) var_ref->pvalue = &sf->arg_buf[var_idx]; else var_ref->pvalue = &sf->var_buf[var_idx]; + var_ref->value = JS_UNDEFINED; return var_ref; } @@ -15630,7 +14444,7 @@ static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom set_cycle_flag(ctx, obj); set_cycle_flag(ctx, this_val); ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor, - JS_DupValue(ctx, this_val), + js_dup(this_val), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); if (ret < 0) { JS_FreeValue(ctx, obj); @@ -15718,7 +14532,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_DupValue(ctx, ctx->function_proto); + parent_class = js_dup(ctx->function_proto); } else { if (!JS_IsConstructor(ctx, parent_class)) { JS_ThrowTypeError(ctx, "parent class must be constructor"); @@ -15734,8 +14548,8 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, } } else { /* parent_class is JS_UNDEFINED in this case */ - parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]); - parent_class = JS_DupValue(ctx, ctx->function_proto); + parent_proto = js_dup(ctx->class_proto[JS_CLASS_OBJECT]); + parent_class = js_dup(ctx->function_proto); } proto = JS_NewObjectProto(ctx, parent_proto); if (JS_IsException(proto)) @@ -15755,7 +14569,7 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, JS_SetConstructorBit(ctx, ctor, TRUE); JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length, - JS_NewInt32(ctx, b->defined_arg_count), + js_int32(b->defined_arg_count), JS_PROP_CONFIGURABLE); if (is_computed_name) { @@ -15770,13 +14584,13 @@ 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_DupValue(ctx, ctor), + js_dup(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_DupValue(ctx, proto), JS_PROP_THROW) < 0) + js_dup(proto), JS_PROP_THROW) < 0) goto fail; set_cycle_flag(ctx, ctor); set_cycle_flag(ctx, proto); @@ -15805,37 +14619,33 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) int var_idx; list_for_each_safe(el, el1, &sf->var_ref_list) { - 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 = list_entry(el, JSVarRef, header.link); var_idx = var_ref->var_idx; if (var_ref->is_arg) - var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]); + var_ref->value = js_dup(sf->arg_buf[var_idx]); else - var_ref->value = JS_DupValueRT(rt, sf->var_buf[var_idx]); + var_ref->value = js_dup(sf->var_buf[var_idx]); 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); } } -static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_arg) +static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx) { struct list_head *el, *el1; JSVarRef *var_ref; - int var_idx = idx; list_for_each_safe(el, el1, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, var_ref_link); - if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) { - 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, sf->var_buf[var_idx]); + var_ref = list_entry(el, JSVarRef, header.link); + if (var_idx == var_ref->var_idx && !var_ref->is_arg) { + var_ref->value = js_dup(sf->var_buf[var_idx]); 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); } } } @@ -15843,16 +14653,16 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_ #define JS_CALL_FLAG_COPY_ARGV (1 << 1) #define JS_CALL_FLAG_GENERATOR (1 << 2) -static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags) +static JSValue js_call_c_function(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSRuntime *rt = ctx->rt; JSCFunctionType func; JSObject *p; JSStackFrame sf_s, *sf = &sf_s, *prev_sf; JSValue ret_val; - JSValueConst *arg_buf; + JSValue *arg_buf; int arg_count, i; JSCFunctionEnum cproto; @@ -15868,18 +14678,9 @@ 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 */ - -#ifdef CONFIG_BIGNUM - /* we only propagate the bignum mode as some runtime functions - test it */ - if (prev_sf) - sf->js_mode = prev_sf->js_mode & JS_MODE_MATH; - else - sf->js_mode = 0; -#else - sf->js_mode = 0; -#endif - sf->cur_func = (JSValue)func_obj; + + sf->is_strict_mode = FALSE; + sf->cur_func = func_obj; sf->arg_count = argc; arg_buf = argv; @@ -15892,7 +14693,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 = arg_buf; func = p->u.cfunc.c_function; switch(cproto) { @@ -15946,7 +14747,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ret_val = JS_EXCEPTION; break; } - ret_val = JS_NewFloat64(ctx, func.f_f(d1)); + ret_val = js_number(func.f_f(d1)); } break; case JS_CFUNC_f_f_f: @@ -15961,7 +14762,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ret_val = JS_EXCEPTION; break; } - ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2)); + ret_val = js_number(func.f_f_f(d1, d2)); } break; case JS_CFUNC_iterator_next: @@ -15982,13 +14783,13 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, return ret_val; } -static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags) +static JSValue js_call_bound_function(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSObject *p; JSBoundFunction *bf; - JSValueConst *arg_buf, new_target; + JSValue *arg_buf, new_target; int arg_count, i; p = JS_VALUE_GET_OBJ(func_obj); @@ -16026,14 +14827,28 @@ typedef enum { OP_SPECIAL_OBJECT_IMPORT_META, } OPSpecialObjectEnum; -#define FUNC_RET_AWAIT 0 -#define FUNC_RET_YIELD 1 -#define FUNC_RET_YIELD_STAR 2 -#define FUNC_RET_INITIAL_YIELD 3 +#define FUNC_RET_AWAIT 0 +#define FUNC_RET_YIELD 1 +#define FUNC_RET_YIELD_STAR 2 + +#if defined(DUMP_BYTECODE_FINAL) || \ + defined(DUMP_BYTECODE_PASS2) || \ + defined(DUMP_BYTECODE_PASS1) || \ + defined(DUMP_BYTECODE_STACK) || \ + defined(DUMP_BYTECODE_STEP) || \ + defined(DUMP_READ_OBJECT) +#define DUMP_BYTECODE +#endif + +#ifdef 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 /* 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, +static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj, + JSValue this_obj, JSValue new_target, int argc, JSValue *argv, int flags) { JSRuntime *rt = caller_ctx->rt; @@ -16041,29 +14856,33 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSObject *p; JSFunctionBytecode *b; JSStackFrame sf_s, *sf = &sf_s; - const uint8_t *pc; + 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; + JSInlineCache *ic; + +#ifdef DUMP_BYTECODE_STEP +#define DUMP_BYTECODE_OR_DONT(pc) \ + if (check_dump_flag(ctx->rt, 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) switch (opcode = *pc++) +#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) switch (opcode = *pc++) #define CASE(op) case op #define DEFAULT default #define BREAK break #else - static const void * const dispatch_table[256] = { + __extension__ 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) goto *dispatch_table[opcode = *pc++]; +#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) __extension__ ({ goto *dispatch_table[opcode = *pc++]; }); #define CASE(op) case_ ## op #define DEFAULT case_default #define BREAK SWITCH(pc) @@ -16089,6 +14908,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, pc = sf->cur_pc; sf->prev_frame = rt->current_stack_frame; rt->current_stack_frame = sf; + ic = b->ic; if (s->throw_flag) goto exception; else @@ -16106,7 +14926,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, return JS_ThrowTypeError(caller_ctx, "not a function"); } return call_func(caller_ctx, func_obj, this_obj, argc, - (JSValueConst *)argv, flags); + argv, flags); } b = p->u.func.function_bytecode; @@ -16121,10 +14941,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->js_mode = b->js_mode; + sf->is_strict_mode = b->is_strict_mode; arg_buf = argv; sf->arg_count = argc; - sf->cur_func = (JSValue)func_obj; + sf->cur_func = func_obj; init_list_head(&sf->var_ref_list); var_refs = p->u.func.var_refs; @@ -16148,10 +14968,18 @@ 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 */ - + ic = b->ic; + +#ifdef DUMP_BYTECODE_STEP + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_STEP)) + print_func_name(b); +#endif + restart: for(;;) { int call_argc; @@ -16159,14 +14987,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, SWITCH(pc) { CASE(OP_push_i32): - *sp++ = JS_NewInt32(ctx, get_u32(pc)); + *sp++ = js_int32(get_u32(pc)); pc += 4; BREAK; CASE(OP_push_const): - *sp++ = JS_DupValue(ctx, b->cpool[get_u32(pc)]); + *sp++ = js_dup(b->cpool[get_u32(pc)]); pc += 4; BREAK; -#if SHORT_OPCODES CASE(OP_push_minus1): CASE(OP_push_0): CASE(OP_push_1): @@ -16176,21 +15003,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_push_5): CASE(OP_push_6): CASE(OP_push_7): - *sp++ = JS_NewInt32(ctx, opcode - OP_push_0); + *sp++ = js_int32(opcode - OP_push_0); BREAK; CASE(OP_push_i8): - *sp++ = JS_NewInt32(ctx, get_i8(pc)); + *sp++ = js_int32(get_i8(pc)); pc += 1; BREAK; CASE(OP_push_i16): - *sp++ = JS_NewInt32(ctx, get_i16(pc)); + *sp++ = js_int32(get_i16(pc)); pc += 2; BREAK; CASE(OP_push_const8): - *sp++ = JS_DupValue(ctx, b->cpool[*pc++]); + *sp++ = js_dup(b->cpool[*pc++]); BREAK; CASE(OP_fclosure8): - *sp++ = js_closure(ctx, JS_DupValue(ctx, b->cpool[*pc++]), var_refs, sf); + *sp++ = js_closure(ctx, js_dup(b->cpool[*pc++]), var_refs, sf); if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; @@ -16201,6 +15028,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length); if (unlikely(JS_IsException(val))) goto exception; @@ -16208,7 +15036,6 @@ 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; @@ -16223,12 +15050,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->js_mode & JS_MODE_STRICT)) { + if (!b->is_strict_mode) { 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_DupValue(ctx, ctx->global_obj); + val = js_dup(ctx->global_obj); } else { val = JS_ToObject(ctx, this_obj); if (JS_IsException(val)) @@ -16236,7 +15063,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } } else { normal_this: - val = JS_DupValue(ctx, this_obj); + val = js_dup(this_obj); } *sp++ = val; } @@ -16257,21 +15084,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, (JSValueConst *)argv); + *sp++ = js_build_arguments(ctx, argc, argv); if (unlikely(JS_IsException(sp[-1]))) goto exception; break; case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS: - *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv, + *sp++ = js_build_mapped_arguments(ctx, argc, 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_DupValue(ctx, sf->cur_func); + *sp++ = js_dup(sf->cur_func); break; case OP_SPECIAL_OBJECT_NEW_TARGET: - *sp++ = JS_DupValue(ctx, new_target); + *sp++ = js_dup(new_target); break; case OP_SPECIAL_OBJECT_HOME_OBJECT: { @@ -16280,7 +15107,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (unlikely(!p1)) *sp++ = JS_UNDEFINED; else - *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); + *sp++ = js_dup(JS_MKPTR(JS_TAG_OBJECT, p1)); } break; case OP_SPECIAL_OBJECT_VAR_OBJECT: @@ -16302,7 +15129,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int first = get_u16(pc); pc += 2; - *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv); + *sp++ = js_build_rest(ctx, first, argc, argv); if (unlikely(JS_IsException(sp[-1]))) goto exception; } @@ -16324,36 +15151,36 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; BREAK; CASE(OP_dup): - sp[0] = JS_DupValue(ctx, sp[-1]); + sp[0] = js_dup(sp[-1]); sp++; BREAK; CASE(OP_dup2): /* a b -> a b a b */ - sp[0] = JS_DupValue(ctx, sp[-2]); - sp[1] = JS_DupValue(ctx, sp[-1]); + sp[0] = js_dup(sp[-2]); + sp[1] = js_dup(sp[-1]); sp += 2; BREAK; CASE(OP_dup3): /* a b c -> a b c a b c */ - sp[0] = JS_DupValue(ctx, sp[-3]); - sp[1] = JS_DupValue(ctx, sp[-2]); - sp[2] = JS_DupValue(ctx, sp[-1]); + sp[0] = js_dup(sp[-3]); + sp[1] = js_dup(sp[-2]); + sp[2] = js_dup(sp[-1]); sp += 3; BREAK; CASE(OP_dup1): /* a b -> a a b */ sp[0] = sp[-1]; - sp[-1] = JS_DupValue(ctx, sp[-2]); + sp[-1] = js_dup(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_DupValue(ctx, sp[0]); + sp[-2] = js_dup(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_DupValue(ctx, sp[0]); + sp[-3] = js_dup(sp[0]); sp++; BREAK; CASE(OP_insert4): /* this obj prop a -> a this obj prop a */ @@ -16361,7 +15188,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_DupValue(ctx, sp[0]); + sp[-4] = js_dup(sp[0]); sp++; BREAK; CASE(OP_perm3): /* obj a b -> a obj b (213) */ @@ -16452,21 +15279,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_fclosure): { - JSValue bfunc = JS_DupValue(ctx, b->cpool[get_u32(pc)]); + JSValue bfunc = js_dup(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): { @@ -16553,8 +15378,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int magic; magic = get_u16(pc); pc += 2; + sf->cur_pc = pc; - ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic); + ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic); if (unlikely(JS_IsException(ret_val))) goto exception; JS_FreeValue(ctx, sp[-3]); @@ -16586,10 +15412,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_check_ctor): if (JS_IsUndefined(new_target)) { + non_ctor_call: JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'"); goto exception; } BREAK; + CASE(OP_init_ctor): + { + JSValue super, ret; + sf->cur_pc = pc; + if (JS_IsUndefined(new_target)) + goto non_ctor_call; + super = JS_GetPrototype(ctx, func_obj); + if (JS_IsException(super)) + goto exception; + ret = JS_CallConstructor2(ctx, super, new_target, argc, argv); + JS_FreeValue(ctx, super); + if (JS_IsException(ret)) + goto exception; + *sp++ = ret; + } + BREAK; CASE(OP_check_brand): { int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]); @@ -16608,7 +15451,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_FreeValue(ctx, sp[-1]); sp -= 2; BREAK; - + CASE(OP_throw): JS_Throw(ctx, *--sp); goto exception; @@ -16646,7 +15489,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_eval): { - JSValueConst obj; + JSValue obj; int scope_idx; call_argc = get_u16(pc); scope_idx = get_u16(pc + 2) - 1; @@ -16678,10 +15521,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int scope_idx; uint32_t len; JSValue *tab; - JSValueConst obj; + JSValue obj; scope_idx = get_u16(pc) - 1; pc += 2; + sf->cur_pc = pc; tab = build_arg_list(ctx, &len, sp[-1]); if (!tab) goto exception; @@ -16694,7 +15538,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_EVAL_TYPE_DIRECT, scope_idx); } else { ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len, - (JSValueConst *)tab); + tab); } free_arg_list(ctx, tab, len); if (unlikely(JS_IsException(ret_val))) @@ -16728,6 +15572,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_import): { JSValue val; + sf->cur_pc = pc; val = js_dynamic_import(ctx, sp[-1]); if (JS_IsException(val)) goto exception; @@ -16746,7 +15591,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, ret = JS_CheckGlobalVar(ctx, atom); if (ret < 0) goto exception; - *sp++ = JS_NewBool(ctx, ret); + *sp++ = js_bool(ret); } BREAK; @@ -16757,6 +15602,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef); if (unlikely(JS_IsException(val))) @@ -16772,6 +15618,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var); sp--; @@ -16786,6 +15633,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, 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]))) { @@ -16840,7 +15688,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - sp[0] = JS_DupValue(ctx, var_buf[idx]); + sp[0] = js_dup(var_buf[idx]); sp++; } BREAK; @@ -16858,7 +15706,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_DupValue(ctx, sp[-1])); + set_value(ctx, &var_buf[idx], js_dup(sp[-1])); } BREAK; CASE(OP_get_arg): @@ -16866,7 +15714,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - sp[0] = JS_DupValue(ctx, arg_buf[idx]); + sp[0] = js_dup(arg_buf[idx]); sp++; } BREAK; @@ -16884,52 +15732,58 @@ 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_DupValue(ctx, sp[-1])); + set_value(ctx, &arg_buf[idx], js_dup(sp[-1])); } BREAK; -#if SHORT_OPCODES - CASE(OP_get_loc8): *sp++ = JS_DupValue(ctx, var_buf[*pc++]); BREAK; + CASE(OP_get_loc8): *sp++ = js_dup(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_DupValue(ctx, sp[-1])); BREAK; + CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], js_dup(sp[-1])); 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; + // 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_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_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_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_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_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_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_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_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_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_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_get_var_ref): { @@ -16938,7 +15792,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_DupValue(ctx, val); + sp[0] = js_dup(val); sp++; } BREAK; @@ -16956,7 +15810,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_DupValue(ctx, sp[-1])); + set_value(ctx, var_refs[idx]->pvalue, js_dup(sp[-1])); } BREAK; CASE(OP_get_var_ref_check): @@ -16970,7 +15824,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE); goto exception; } - sp[0] = JS_DupValue(ctx, val); + sp[0] = js_dup(val); sp++; } BREAK; @@ -17014,23 +15868,11 @@ 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(ctx, b, idx, FALSE); + JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, + FALSE); goto exception; } - 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[0] = js_dup(var_buf[idx]); sp++; } BREAK; @@ -17040,7 +15882,8 @@ 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(ctx, b, idx, FALSE); + JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, + FALSE); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); @@ -17053,7 +15896,8 @@ 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(ctx, "'this' can be initialized only once"); + JS_ThrowReferenceError(caller_ctx, + "'this' can be initialized only once"); goto exception; } set_value(ctx, &var_buf[idx], sp[-1]); @@ -17065,7 +15909,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - close_lexical_var(ctx, sf, idx, FALSE); + close_lexical_var(ctx, sf, idx); } BREAK; @@ -17118,7 +15962,6 @@ 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))) @@ -17129,7 +15972,6 @@ 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; @@ -17170,7 +16012,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } BREAK; -#if SHORT_OPCODES CASE(OP_if_true8): { int res; @@ -17211,7 +16052,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } BREAK; -#endif CASE(OP_catch): { int32_t diff; @@ -17226,7 +16066,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_NewInt32(ctx, pc + 4 - b->byte_code_buf); + sp[0] = js_int32(pc + 4 - b->byte_code_buf); sp++; pc += diff; } @@ -17250,15 +16090,18 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_for_in_start): + sf->cur_pc = pc; if (js_for_in_start(ctx, sp)) goto exception; BREAK; CASE(OP_for_in_next): + sf->cur_pc = pc; if (js_for_in_next(ctx, sp)) goto exception; sp += 2; BREAK; CASE(OP_for_of_start): + sf->cur_pc = pc; if (js_for_of_start(ctx, sp, FALSE)) goto exception; sp += 1; @@ -17268,18 +16111,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int offset = -3 - pc[0]; pc += 1; + sf->cur_pc = pc; if (js_for_of_next(ctx, sp, offset)) goto exception; sp += 2; } BREAK; CASE(OP_for_await_of_start): + sf->cur_pc = pc; if (js_for_of_start(ctx, sp, TRUE)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); BREAK; CASE(OP_iterator_get_value_done): + sf->cur_pc = pc; if (js_iterator_get_value_done(ctx, sp)) goto exception; sp += 1; @@ -17297,6 +16143,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_FreeValue(ctx, sp[-1]); /* drop the next method */ sp--; if (!JS_IsUndefined(sp[-1])) { + sf->cur_pc = pc; if (JS_IteratorClose(ctx, sp[-1], FALSE)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -17325,8 +16172,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, /* stack: iter_obj next catch_offset val */ { JSValue ret; - ret = JS_Call(ctx, sp[-3], sp[-4], - 1, (JSValueConst *)(sp - 1)); + sf->cur_pc = pc; + ret = JS_Call(ctx, sp[-3], sp[-4], 1, (sp - 1)); if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -17341,6 +16188,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BOOL ret_flag; int flags; flags = *pc++; + sf->cur_pc = pc; method = JS_GetProperty(ctx, sp[-4], (flags & 1) ? JS_ATOM_throw : JS_ATOM_return); if (JS_IsException(method)) @@ -17354,7 +16202,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, 0, NULL); } else { ret = JS_CallFree(ctx, method, sp[-4], - 1, (JSValueConst *)(sp - 1)); + 1, (sp - 1)); } if (JS_IsException(ret)) goto exception; @@ -17362,7 +16210,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-1] = ret; ret_flag = FALSE; } - sp[0] = JS_NewBool(ctx, ret_flag); + sp[0] = js_bool(ret_flag); sp += 1; } BREAK; @@ -17378,7 +16226,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } else { res = JS_ToBoolFree(ctx, op1); } - sp[-1] = JS_NewBool(ctx, !res); + sp[-1] = js_bool(!res); } BREAK; @@ -17386,12 +16234,39 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; JSAtom atom; + JSInlineCacheUpdate icu; atom = get_u32(pc); pc += 4; - - val = JS_GetProperty(ctx, sp[-1], atom); + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS}; + val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], &icu, FALSE); if (unlikely(JS_IsException(val))) goto exception; + if (icu.offset != INLINE_CACHE_MISS) { + put_u8(pc - 5, OP_get_field_ic); + put_u32(pc - 4, icu.offset); + JS_FreeAtom(ctx, atom); + } + JS_FreeValue(ctx, sp[-1]); + sp[-1] = val; + } + BREAK; + + CASE(OP_get_field_ic): + { + JSValue val; + JSAtom atom; + uint32_t ic_offset; + JSInlineCacheUpdate icu; + ic_offset = get_u32(pc); + atom = get_ic_atom(ic, ic_offset); + pc += 4; + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, ic_offset}; + val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], &icu, FALSE); + if (unlikely(JS_IsException(val))) + goto exception; + assert(icu.offset == ic_offset); JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } @@ -17401,12 +16276,38 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; JSAtom atom; + JSInlineCacheUpdate icu; atom = get_u32(pc); pc += 4; - - val = JS_GetProperty(ctx, sp[-1], atom); + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS}; + val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], &icu, FALSE); if (unlikely(JS_IsException(val))) goto exception; + if (icu.offset != INLINE_CACHE_MISS) { + put_u8(pc - 5, OP_get_field2_ic); + put_u32(pc - 4, icu.offset); + JS_FreeAtom(ctx, atom); + } + *sp++ = val; + } + BREAK; + + CASE(OP_get_field2_ic): + { + JSValue val; + JSAtom atom; + uint32_t ic_offset; + JSInlineCacheUpdate icu; + ic_offset = get_u32(pc); + atom = get_ic_atom(ic, ic_offset); + pc += 4; + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, ic_offset}; + val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], &icu, FALSE); + if (unlikely(JS_IsException(val))) + goto exception; + assert(icu.offset == ic_offset); *sp++ = val; } BREAK; @@ -17415,15 +16316,45 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int ret; JSAtom atom; + JSInlineCacheUpdate icu; atom = get_u32(pc); pc += 4; - - ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2], - JS_PROP_THROW_STRICT); + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS}; + ret = JS_SetPropertyInternal2(ctx, + sp[-2], atom, + sp[-1], sp[-2], + JS_PROP_THROW_STRICT, &icu); JS_FreeValue(ctx, sp[-2]); sp -= 2; if (unlikely(ret < 0)) goto exception; + if (icu.offset != INLINE_CACHE_MISS) { + put_u8(pc - 5, OP_put_field_ic); + put_u32(pc - 4, icu.offset); + JS_FreeAtom(ctx, atom); + } + } + BREAK; + + CASE(OP_put_field_ic): + { + int ret; + JSAtom atom; + uint32_t ic_offset; + JSInlineCacheUpdate icu; + ic_offset = get_u32(pc); + atom = get_ic_atom(ic, ic_offset); + pc += 4; + sf->cur_pc = pc; + icu = (JSInlineCacheUpdate){ic, ic_offset}; + ret = JS_SetPropertyInternalWithIC(ctx, sp[-2], atom, sp[-1], + JS_PROP_THROW_STRICT, &icu); + JS_FreeValue(ctx, sp[-2]); + sp -= 2; + if (unlikely(ret < 0)) + goto exception; + assert(icu.offset == ic_offset); } BREAK; @@ -17431,7 +16362,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSAtom atom; JSValue val; - + atom = get_u32(pc); pc += 4; val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE); @@ -17440,11 +16371,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, *sp++ = val; } BREAK; - + 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]); @@ -17458,6 +16389,7 @@ 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]); @@ -17532,7 +16464,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_define_method_computed): { JSValue getter, setter, value; - JSValueConst obj; + JSValue obj; JSAtom atom; int flags, ret, op_flags; BOOL is_computed; @@ -17593,7 +16525,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int class_flags; JSAtom atom; - + atom = get_u32(pc); class_flags = pc[4]; pc += 5; @@ -17608,6 +16540,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-2]); sp[-2] = val; @@ -17621,6 +16554,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); sp[-1] = val; if (unlikely(JS_IsException(val))) @@ -17631,6 +16565,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_ref_value): { JSValue val; + sf->cur_pc = pc; if (unlikely(JS_IsUndefined(sp[-2]))) { JSAtom atom = JS_ValueToAtom(ctx, sp[-1]); if (atom != JS_ATOM_NULL) { @@ -17640,7 +16575,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } val = JS_GetPropertyValue(ctx, sp[-2], - JS_DupValue(ctx, sp[-1])); + js_dup(sp[-1])); if (unlikely(JS_IsException(val))) goto exception; sp[0] = val; @@ -17652,10 +16587,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; JSAtom atom; + sf->cur_pc = pc; 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_GetPropertyInternal2(ctx, sp[-2], atom, sp[-3], NULL, FALSE); JS_FreeAtom(ctx, atom); if (unlikely(JS_IsException(val))) goto exception; @@ -17670,7 +16606,7 @@ 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; @@ -17682,6 +16618,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_put_ref_value): { int ret, flags; + sf->cur_pc = pc; flags = JS_PROP_THROW_STRICT; if (unlikely(JS_IsUndefined(sp[-3]))) { if (is_strict_mode(ctx)) { @@ -17692,7 +16629,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } goto exception; } else { - sp[-3] = JS_DupValue(ctx, ctx->global_obj); + sp[-3] = js_dup(ctx->global_obj); } } else { if (is_strict_mode(ctx)) @@ -17710,6 +16647,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int ret; JSAtom atom; + sf->cur_pc = pc; if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); goto exception; @@ -17717,8 +16655,10 @@ 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_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-4], - JS_PROP_THROW_STRICT); + ret = JS_SetPropertyInternal2(ctx, + sp[-3], atom, + sp[-1], sp[-4], + JS_PROP_THROW_STRICT, NULL); JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, sp[-4]); JS_FreeValue(ctx, sp[-3]); @@ -17732,7 +16672,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_DupValue(ctx, sp[-2]), sp[-1], + ret = JS_DefinePropertyValueValue(ctx, sp[-3], js_dup(sp[-2]), sp[-1], JS_PROP_C_W_E | JS_PROP_THROW); sp -= 1; if (unlikely(ret < 0)) @@ -17742,6 +16682,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_append): /* array pos enumobj -- array pos */ { + sf->cur_pc = pc; if (js_append_enumerate(ctx, sp)) goto exception; JS_FreeValue(ctx, *--sp); @@ -17757,6 +16698,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int mask; mask = *pc++; + sf->cur_pc = pc; if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)], sp[-1 - ((mask >> 2) & 7)], sp[-1 - ((mask >> 5) & 7)], 0)) @@ -17774,14 +16716,15 @@ 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_NewInt32(ctx, r); + sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + - JS_VALUE_GET_FLOAT64(op2)); + sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) + + JS_VALUE_GET_FLOAT64(op2)); sp--; } else { add_slow: + sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; sp--; @@ -17802,16 +16745,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_INT(sp[-1]); if (unlikely((int)r != r)) goto add_loc_slow; - *pv = JS_NewInt32(ctx, r); + *pv = js_int32(r); sp--; } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { JSValue op1; op1 = sp[-1]; sp--; + sf->cur_pc = pc; op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) goto exception; - op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1); + op1 = JS_ConcatString(ctx, js_dup(*pv), op1); if (JS_IsException(op1)) goto exception; set_value(ctx, pv, op1); @@ -17820,7 +16764,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ - ops[0] = JS_DupValue(ctx, *pv); + sf->cur_pc = pc; + ops[0] = js_dup(*pv); ops[1] = sp[-1]; sp--; if (js_add_slow(ctx, ops + 2)) @@ -17839,11 +16784,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_NewInt32(ctx, r); + sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) - - JS_VALUE_GET_FLOAT64(op2)); + sp[-2] = js_float64(JS_VALUE_GET_FLOAT64(op1) - + JS_VALUE_GET_FLOAT64(op2)); sp--; } else { goto binary_arith_slow; @@ -17863,11 +16808,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, v2 = JS_VALUE_GET_INT(op2); r = (int64_t)v1 * v2; if (unlikely((int)r != r)) { -#ifdef CONFIG_BIGNUM - if (unlikely(sf->js_mode & JS_MODE_MATH) && - (r < -MAX_SAFE_INTEGER || r > MAX_SAFE_INTEGER)) - goto binary_arith_slow; -#endif d = (double)r; goto mul_fp_res; } @@ -17876,16 +16816,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, d = -0.0; goto mul_fp_res; } - sp[-2] = JS_NewInt32(ctx, r); + sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { -#ifdef CONFIG_BIGNUM - if (unlikely(sf->js_mode & JS_MODE_MATH)) - goto binary_arith_slow; -#endif d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2); mul_fp_res: - sp[-2] = __JS_NewFloat64(ctx, d); + sp[-2] = js_float64(d); sp--; } else { goto binary_arith_slow; @@ -17899,11 +16835,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int v1, v2; - if (unlikely(sf->js_mode & JS_MODE_MATH)) - goto binary_arith_slow; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); - sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2); + sp[-2] = js_number((double)v1 / (double)v2); sp--; } else { goto binary_arith_slow; @@ -17911,9 +16845,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_mod): -#ifdef CONFIG_BIGNUM - CASE(OP_math_mod): -#endif { JSValue op1, op2; op1 = sp[-2]; @@ -17927,7 +16858,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_NewInt32(ctx, r); + sp[-2] = js_int32(r); sp--; } else { goto binary_arith_slow; @@ -17936,6 +16867,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_pow): binary_arith_slow: + sf->cur_pc = pc; if (js_binary_arith_slow(ctx, sp, opcode)) goto exception; sp--; @@ -17949,6 +16881,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, tag = JS_VALUE_GET_TAG(op1); if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) { } else { + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -17973,12 +16906,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, d = -(double)val; goto neg_fp_res; } - sp[-1] = JS_NewInt32(ctx, -val); + sp[-1] = js_int32(-val); } else if (JS_TAG_IS_FLOAT64(tag)) { d = -JS_VALUE_GET_FLOAT64(op1); neg_fp_res: - sp[-1] = __JS_NewFloat64(ctx, d); + sp[-1] = js_float64(d); } else { + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -17993,9 +16927,10 @@ 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_NewInt32(ctx, val + 1); + sp[-1] = js_int32(val + 1); } else { inc_slow: + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18010,9 +16945,10 @@ 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_NewInt32(ctx, val - 1); + sp[-1] = js_int32(val - 1); } else { dec_slow: + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18020,6 +16956,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_post_inc): CASE(OP_post_dec): + sf->cur_pc = pc; if (js_post_inc_slow(ctx, sp, opcode)) goto exception; sp++; @@ -18037,12 +16974,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_NewInt32(ctx, val + 1); + var_buf[idx] = js_int32(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_DupValue(ctx, op1); + op1 = js_dup(op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc)) goto exception; set_value(ctx, &var_buf[idx], op1); @@ -18062,12 +17000,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_NewInt32(ctx, val - 1); + var_buf[idx] = js_int32(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_DupValue(ctx, op1); + op1 = js_dup(op1); if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec)) goto exception; set_value(ctx, &var_buf[idx], op1); @@ -18079,8 +17018,9 @@ 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_NewInt32(ctx, ~JS_VALUE_GET_INT(op1)); + sp[-1] = js_int32(~JS_VALUE_GET_INT(op1)); } else { + sf->cur_pc = pc; if (js_not_slow(ctx, sp)) goto exception; } @@ -18095,29 +17035,11 @@ 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); -#ifdef CONFIG_BIGNUM - { - int64_t r; - if (unlikely(sf->js_mode & JS_MODE_MATH)) { - if (v2 > 0x1f) - goto shl_slow; - r = (int64_t)v1 << v2; - if ((int)r != r) - goto shl_slow; - } else { - v2 &= 0x1f; - } - } -#else - v2 &= 0x1f; -#endif - sp[-2] = JS_NewInt32(ctx, v1 << v2); + v2 = JS_VALUE_GET_INT(op2) & 0x1f; + sp[-2] = js_int32(v1 << v2); sp--; } else { -#ifdef CONFIG_BIGNUM - shl_slow: -#endif + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18132,13 +17054,11 @@ 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); - /* v1 >>> v2 retains its JS semantics if CONFIG_BIGNUM */ v2 &= 0x1f; - sp[-2] = JS_NewUint32(ctx, - (uint32_t)JS_VALUE_GET_INT(op1) >> - v2); + sp[-2] = js_uint32((uint32_t)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { + sf->cur_pc = pc; if (js_shr_slow(ctx, sp)) goto exception; sp--; @@ -18153,23 +17073,13 @@ 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); -#ifdef CONFIG_BIGNUM if (unlikely(v2 > 0x1f)) { - if (unlikely(sf->js_mode & JS_MODE_MATH)) - goto sar_slow; - else - v2 &= 0x1f; + v2 &= 0x1f; } -#else - v2 &= 0x1f; -#endif - sp[-2] = JS_NewInt32(ctx, - (int)JS_VALUE_GET_INT(op1) >> v2); + sp[-2] = js_int32((int)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { -#ifdef CONFIG_BIGNUM - sar_slow: -#endif + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18182,11 +17092,10 @@ 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_NewInt32(ctx, - JS_VALUE_GET_INT(op1) & - JS_VALUE_GET_INT(op2)); + sp[-2] = js_int32(JS_VALUE_GET_INT(op1) & JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18199,11 +17108,10 @@ 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_NewInt32(ctx, - JS_VALUE_GET_INT(op1) | - JS_VALUE_GET_INT(op2)); + sp[-2] = js_int32(JS_VALUE_GET_INT(op1) | JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18216,11 +17124,10 @@ 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_NewInt32(ctx, - JS_VALUE_GET_INT(op1) ^ - JS_VALUE_GET_INT(op2)); + sp[-2] = js_int32(JS_VALUE_GET_INT(op1) ^ JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18236,9 +17143,10 @@ 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_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ + sp[-2] = js_bool(JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ sp--; \ } else { \ + sf->cur_pc = pc; \ if (slow_call) \ goto exception; \ sp--; \ @@ -18255,14 +17163,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, OP_CMP(OP_strict_eq, ==, js_strict_eq_slow(ctx, sp, 0)); OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1)); -#ifdef CONFIG_BIGNUM - CASE(OP_mul_pow10): - if (rt->bigfloat_ops.mul_pow10(ctx, sp)) - goto exception; - sp--; - BREAK; -#endif CASE(OP_in): + sf->cur_pc = pc; if (js_operator_in(ctx, sp)) goto exception; sp--; @@ -18273,6 +17175,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; BREAK; CASE(OP_instanceof): + sf->cur_pc = pc; if (js_operator_instanceof(ctx, sp)) goto exception; sp--; @@ -18289,6 +17192,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_delete): + sf->cur_pc = pc; if (js_operator_delete(ctx, sp)) goto exception; sp--; @@ -18301,15 +17205,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0); if (unlikely(ret < 0)) goto exception; - *sp++ = JS_NewBool(ctx, ret); + *sp++ = js_bool(ret); } BREAK; CASE(OP_to_object): if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) { + sf->cur_pc = pc; ret_val = JS_ToObject(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18325,6 +17231,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, case JS_TAG_SYMBOL: break; default: + sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18346,6 +17253,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, case JS_TAG_SYMBOL: break; default: + sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18354,17 +17262,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, break; } BREAK; -#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; -#endif CASE(OP_with_get_var): CASE(OP_with_put_var): CASE(OP_with_delete_var): @@ -18380,6 +17277,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, diff = get_u32(pc + 4); is_with = pc[8]; pc += 9; + sf->cur_pc = pc; obj = sp[-1]; ret = JS_HasProperty(ctx, obj, atom); @@ -18402,7 +17300,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, break; case OP_with_put_var: /* XXX: check if strict mode */ - ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], obj, + ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-1]); sp -= 2; @@ -18414,7 +17312,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_NewBool(ctx, ret); + sp[-1] = js_bool(ret); break; case OP_with_make_ref: /* produce a pair object/propname on the stack */ @@ -18448,20 +17346,18 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_await): - ret_val = JS_NewInt32(ctx, FUNC_RET_AWAIT); + ret_val = js_int32(FUNC_RET_AWAIT); goto done_generator; CASE(OP_yield): - ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD); + ret_val = js_int32(FUNC_RET_YIELD); goto done_generator; CASE(OP_yield_star): CASE(OP_async_yield_star): - ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR); + ret_val = js_int32(FUNC_RET_YIELD_STAR); goto done_generator; CASE(OP_return_async): - ret_val = JS_UNDEFINED; - goto done_generator; CASE(OP_initial_yield): - ret_val = JS_NewInt32(ctx, FUNC_RET_INITIAL_YIELD); + ret_val = JS_UNDEFINED; goto done_generator; CASE(OP_nop): @@ -18473,7 +17369,6 @@ 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; @@ -18502,7 +17397,6 @@ 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; @@ -18523,7 +17417,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, before if the exception happens in a bytecode operation */ sf->cur_pc = pc; - build_backtrace(ctx, rt->current_exception, NULL, 0, 0); + build_backtrace(ctx, rt->current_exception, JS_UNDEFINED, NULL, 0, 0, 0); } if (!JS_IsUncatchableError(ctx, rt->current_exception)) { while (sp > stack_buf) { @@ -18538,7 +17432,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_IteratorClose(ctx, sp[-1], TRUE); } else { *sp++ = rt->current_exception; - rt->current_exception = JS_NULL; + rt->current_exception = JS_UNINITIALIZED; pc = b->byte_code_buf + pos; goto restart; } @@ -18568,29 +17462,29 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, return ret_val; } -JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, - int argc, JSValueConst *argv) +JSValue JS_Call(JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv) { return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, - argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); + argc, argv, JS_CALL_FLAG_COPY_ARGV); } -static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj, - int argc, JSValueConst *argv) +static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv) { JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED, - argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV); + argc, argv, JS_CALL_FLAG_COPY_ARGV); JS_FreeValue(ctx, func_obj); return res; } /* warning: the refcount of the context is not incremented. Return NULL in case of exception (case of revoked proxy only) */ -static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) +static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValue func_obj) { JSObject *p; JSContext *realm; - + if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) return ctx; p = JS_VALUE_GET_OBJ(func_obj); @@ -18634,14 +17528,14 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) return realm; } -static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, +static JSValue js_create_from_ctor(JSContext *ctx, JSValue ctor, int class_id) { JSValue proto, obj; JSContext *realm; - + if (JS_IsUndefined(ctor)) { - proto = JS_DupValue(ctx, ctx->class_proto[class_id]); + proto = js_dup(ctx->class_proto[class_id]); } else { proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype); if (JS_IsException(proto)) @@ -18651,7 +17545,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, realm = JS_GetFunctionRealm(ctx, ctor); if (!realm) return JS_EXCEPTION; - proto = JS_DupValue(ctx, realm->class_proto[class_id]); + proto = js_dup(realm->class_proto[class_id]); } } obj = JS_NewObjectProtoClass(ctx, proto, class_id); @@ -18661,8 +17555,8 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */ static JSValue JS_CallConstructorInternal(JSContext *ctx, - JSValueConst func_obj, - JSValueConst new_target, + JSValue func_obj, + JSValue new_target, int argc, JSValue *argv, int flags) { JSObject *p; @@ -18684,7 +17578,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx, return JS_ThrowTypeError(ctx, "not a function"); } return call_func(ctx, func_obj, new_target, argc, - (JSValueConst *)argv, flags); + argv, flags); } b = p->u.func.function_bytecode; @@ -18708,25 +17602,25 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx, } } -JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, - JSValueConst new_target, - int argc, JSValueConst *argv) +JSValue JS_CallConstructor2(JSContext *ctx, JSValue func_obj, + JSValue new_target, + int argc, JSValue *argv) { return JS_CallConstructorInternal(ctx, func_obj, new_target, - argc, (JSValue *)argv, + argc, argv, JS_CALL_FLAG_COPY_ARGV); } -JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, - int argc, JSValueConst *argv) +JSValue JS_CallConstructor(JSContext *ctx, JSValue func_obj, + int argc, JSValue *argv) { return JS_CallConstructorInternal(ctx, func_obj, func_obj, - argc, (JSValue *)argv, + argc, argv, JS_CALL_FLAG_COPY_ARGV); } -JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, - int argc, JSValueConst *argv) +JSValue JS_Invoke(JSContext *ctx, JSValue this_val, JSAtom atom, + int argc, JSValue *argv) { JSValue func_obj; func_obj = JS_GetProperty(ctx, this_val, atom); @@ -18736,7 +17630,7 @@ JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, } static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, - int argc, JSValueConst *argv) + int argc, JSValue *argv) { JSValue res = JS_Invoke(ctx, this_val, atom, argc, argv); JS_FreeValue(ctx, this_val); @@ -18744,57 +17638,69 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, } /* JSAsyncFunctionState (used by generator and async functions) */ -static JSAsyncFunctionState *async_func_init(JSContext *ctx, - JSValueConst func_obj, JSValueConst this_obj, - int argc, JSValueConst *argv) +static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, + JSValue func_obj, JSValue this_obj, + int argc, JSValue *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->js_mode = b->js_mode | JS_MODE_ASYNC; + sf->is_strict_mode = b->is_strict_mode; 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) { - js_free(ctx, s); - return NULL; - } - sf->cur_func = JS_DupValue(ctx, func_obj); - s->this_val = JS_DupValue(ctx, this_obj); + if (!sf->arg_buf) + return -1; + sf->cur_func = js_dup(func_obj); + s->this_val = js_dup(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_DupValue(ctx, argv[i]); + sf->arg_buf[i] = js_dup(argv[i]); n = arg_buf_len + b->var_count; for(i = argc; i < n; i++) sf->arg_buf[i] = JS_UNDEFINED; - s->resolving_funcs[0] = JS_UNDEFINED; - s->resolving_funcs[1] = JS_UNDEFINED; - s->is_completed = FALSE; - return s; + return 0; } -static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s) +static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, + JS_MarkFunc *mark_func) { - JSStackFrame *sf = &s->frame; + 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); + } +} + +static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) +{ + JSStackFrame *sf; + 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); @@ -18802,7 +17708,6 @@ static void async_func_free_frame(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); @@ -18810,66 +17715,17 @@ static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s) static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) { - JSRuntime *rt = ctx->rt; - JSStackFrame *sf = &s->frame; - JSValue func_obj, ret; + JSValue func_obj; - 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; + if (js_check_stack_overflow(ctx->rt, 0)) + return JS_ThrowStackOverflow(ctx); - /* close the closure variables. */ - close_var_refs(rt, sf); - - async_func_free_frame(rt, s); - } - return ret; + /* 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, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR); } -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 */ @@ -18883,17 +17739,14 @@ 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; - if (s->func_state) { - async_func_free(rt, s->func_state); - s->func_state = NULL; - } + async_func_free(rt, &s->func_state); s->state = JS_GENERATOR_STATE_COMPLETED; } @@ -18912,15 +17765,15 @@ static void free_generator_stack(JSContext *ctx, JSGeneratorData *s) free_generator_stack_rt(ctx->rt, s); } -static void js_generator_mark(JSRuntime *rt, JSValueConst val, +static void js_generator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSGeneratorData *s = p->u.generator_data; - if (!s || !s->func_state) + if (!s || s->state == JS_GENERATOR_STATE_COMPLETED) return; - mark_func(rt, &s->func_state->header); + async_func_mark(rt, &s->func_state, mark_func); } /* XXX: use enum */ @@ -18928,8 +17781,8 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val, #define GEN_MAGIC_RETURN 1 #define GEN_MAGIC_THROW 2 -static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_generator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic) { JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR); @@ -18939,7 +17792,7 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, *pdone = TRUE; if (!s) return JS_ThrowTypeError(ctx, "not a generator"); - sf = &s->func_state->frame; + sf = &s->func_state.frame; switch(s->state) { default: case JS_GENERATOR_STATE_SUSPENDED_START: @@ -18953,27 +17806,27 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR: case JS_GENERATOR_STATE_SUSPENDED_YIELD: /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */ - ret = JS_DupValue(ctx, argv[0]); + ret = js_dup(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_NewInt32(ctx, magic); + sf->cur_sp[0] = js_int32(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 (s->func_state->is_completed) { - /* finalize the execution in case of exception or normal return */ + if (JS_IsException(func_ret)) { + /* finalize the execution in case of exception */ free_generator_stack(ctx, s); return func_ret; - } else { - assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT); + } + if (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; @@ -18984,6 +17837,12 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, } else { *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: @@ -18995,10 +17854,10 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; break; case GEN_MAGIC_RETURN: - ret = JS_DupValue(ctx, argv[0]); + ret = js_dup(argv[0]); break; case GEN_MAGIC_THROW: - ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0])); + ret = JS_Throw(ctx, js_dup(argv[0])); break; } break; @@ -19009,9 +17868,9 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, +static JSValue js_generator_function_call(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSValue obj, func_ret; @@ -19021,14 +17880,13 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, if (!s) return JS_EXCEPTION; s->state = JS_GENERATOR_STATE_SUSPENDED_START; - s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv); - if (!s->func_state) { + if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { 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); @@ -19036,7 +17894,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_SetOpaque(obj, s); + JS_SetOpaqueInternal(obj, s); return obj; fail: free_generator_stack_rt(ctx->rt, s); @@ -19046,27 +17904,51 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, /* AsyncFunction */ -static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val) +static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s) { - JSObject *p = JS_VALUE_GET_OBJ(val); - JSAsyncFunctionState *s = p->u.async_function_data; - if (s) { - async_func_free(rt, s); + if (s->is_active) { + async_func_free(rt, &s->func_state); + s->is_active = FALSE; } } -static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, +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, JSValue val) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSAsyncFunctionData *s = p->u.async_function_data; + if (s) { + js_async_function_free(rt, s); + } +} + +static void js_async_function_resolve_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); - JSAsyncFunctionState *s = p->u.async_function_data; + JSAsyncFunctionData *s = p->u.async_function_data; if (s) { mark_func(rt, &s->header); } } static int js_async_function_resolve_create(JSContext *ctx, - JSAsyncFunctionState *s, + JSAsyncFunctionData *s, JSValue *resolving_funcs) { int i; @@ -19088,107 +17970,120 @@ static int js_async_function_resolve_create(JSContext *ctx, return 0; } -static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s) +static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s) { JSValue func_ret, ret2; - 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, (JSValueConst *)&error); - JS_FreeValue(ctx, error); - 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 ? */ - } + func_ret = async_func_resume(ctx, &s->func_state); + if (JS_IsException(func_ret)) { + JSValue error; + fail: + error = JS_GetException(ctx); + ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED, + 1, &error); + JS_FreeValue(ctx, error); + js_async_function_terminate(ctx->rt, s); + JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */ } else { - JSValue value, promise, resolving_funcs[2], resolving_funcs1[2]; - int i, res; + 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, &value); + JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */ + JS_FreeValue(ctx, value); + js_async_function_terminate(ctx->rt, s); + } else { + JSValue promise, resolving_funcs[2], resolving_funcs1[2]; + int i, res; - value = s->frame.cur_sp[-1]; - s->frame.cur_sp[-1] = JS_UNDEFINED; + /* await */ + JS_FreeValue(ctx, func_ret); /* not used */ + promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, &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; + } - /* 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)) { + /* 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, + resolving_funcs, + resolving_funcs1); JS_FreeValue(ctx, promise); - goto fail; + for(i = 0; i < 2; i++) + JS_FreeValue(ctx, resolving_funcs[i]); + if (res) + 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; } } static JSValue js_async_function_resolve_call(JSContext *ctx, - JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, + JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSObject *p = JS_VALUE_GET_OBJ(func_obj); - JSAsyncFunctionState *s = p->u.async_function_data; + JSAsyncFunctionData *s = p->u.async_function_data; BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE; - JSValueConst arg; + JSValue arg; if (argc > 0) arg = argv[0]; else arg = JS_UNDEFINED; - s->throw_flag = is_reject; + s->func_state.throw_flag = is_reject; if (is_reject) { - JS_Throw(ctx, JS_DupValue(ctx, arg)); + JS_Throw(ctx, js_dup(arg)); } else { /* return value of await */ - s->frame.cur_sp[-1] = JS_DupValue(ctx, arg); + s->func_state.frame.cur_sp[-1] = js_dup(arg); } js_async_function_resume(ctx, s); return JS_UNDEFINED; } -static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags) +static JSValue js_async_function_call(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSValue promise; - JSAsyncFunctionState *s; + JSAsyncFunctionData *s; - s = async_func_init(ctx, func_obj, this_obj, argc, argv); + s = js_mallocz(ctx, sizeof(*s)); 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)) { - async_func_free(ctx->rt, s); + 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); return JS_EXCEPTION; } + s->is_active = TRUE; js_async_function_resume(ctx, s); - - async_func_free(ctx->rt, s); + + js_async_function_free(ctx->rt, s); return promise; } @@ -19217,8 +18112,7 @@ typedef struct JSAsyncGeneratorRequest { typedef struct JSAsyncGeneratorData { JSObject *generator; /* back pointer to the object (const) */ JSAsyncGeneratorStateEnum state; - /* func_state is NULL is state AWAITING_RETURN and COMPLETED */ - JSAsyncFunctionState *func_state; + JSAsyncFunctionState func_state; struct list_head queue; /* list of JSAsyncGeneratorRequest.link */ } JSAsyncGeneratorData; @@ -19236,8 +18130,10 @@ static void js_async_generator_free(JSRuntime *rt, JS_FreeValueRT(rt, req->resolving_funcs[1]); js_free_rt(rt, req); } - if (s->func_state) - async_func_free(rt, s->func_state); + if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED && + s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) { + async_func_free(rt, &s->func_state); + } js_free_rt(rt, s); } @@ -19250,7 +18146,7 @@ static void js_async_generator_finalizer(JSRuntime *rt, JSValue obj) } } -static void js_async_generator_mark(JSRuntime *rt, JSValueConst val, +static void js_async_generator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSAsyncGeneratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_GENERATOR); @@ -19264,19 +18160,20 @@ 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->func_state) { - mark_func(rt, &s->func_state->header); + 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); } } } static JSValue js_async_generator_resolve_function(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, + JSValue this_obj, + int argc, JSValue *argv, int magic, JSValue *func_data); static int js_async_generator_resolve_function_create(JSContext *ctx, - JSValueConst generator, + JSValue generator, JSValue *resolving_funcs, BOOL is_resume_next) { @@ -19298,7 +18195,7 @@ static int js_async_generator_resolve_function_create(JSContext *ctx, static int js_async_generator_await(JSContext *ctx, JSAsyncGeneratorData *s, - JSValueConst value) + JSValue value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int i, res; @@ -19319,8 +18216,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, - (JSValueConst *)resolving_funcs, - (JSValueConst *)resolving_funcs1); + resolving_funcs, + resolving_funcs1); JS_FreeValue(ctx, promise); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); @@ -19333,7 +18230,7 @@ static int js_async_generator_await(JSContext *ctx, static void js_async_generator_resolve_or_reject(JSContext *ctx, JSAsyncGeneratorData *s, - JSValueConst result, + JSValue result, int is_reject) { JSAsyncGeneratorRequest *next; @@ -19353,11 +18250,11 @@ static void js_async_generator_resolve_or_reject(JSContext *ctx, static void js_async_generator_resolve(JSContext *ctx, JSAsyncGeneratorData *s, - JSValueConst value, + JSValue value, BOOL done) { JSValue result; - result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done); + result = js_create_iterator_result(ctx, js_dup(value), done); /* XXX: better exception handling ? */ js_async_generator_resolve_or_reject(ctx, s, result, 0); JS_FreeValue(ctx, result); @@ -19365,7 +18262,7 @@ static void js_async_generator_resolve(JSContext *ctx, static void js_async_generator_reject(JSContext *ctx, JSAsyncGeneratorData *s, - JSValueConst exception) + JSValue exception) { js_async_generator_resolve_or_reject(ctx, s, exception, 1); } @@ -19375,14 +18272,13 @@ 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); - s->func_state = NULL; + async_func_free(ctx->rt, &s->func_state); } } static int js_async_generator_completed_return(JSContext *ctx, JSAsyncGeneratorData *s, - JSValueConst value) + JSValue value) { JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int res; @@ -19394,7 +18290,7 @@ static int js_async_generator_completed_return(JSContext *ctx, // 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, (JSValueConst *)&err, + promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &err, /*is_reject*/1); JS_FreeValue(ctx, err); if (JS_IsException(promise)) @@ -19410,8 +18306,8 @@ static int js_async_generator_completed_return(JSContext *ctx, resolving_funcs[0] = JS_UNDEFINED; resolving_funcs[1] = JS_UNDEFINED; res = perform_promise_then(ctx, promise, - (JSValueConst *)resolving_funcs1, - (JSValueConst *)resolving_funcs); + resolving_funcs1, + resolving_funcs); JS_FreeValue(ctx, resolving_funcs1[0]); JS_FreeValue(ctx, resolving_funcs1[1]); JS_FreeValue(ctx, promise); @@ -19453,42 +18349,34 @@ 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_DupValue(ctx, next->result); + value = js_dup(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_NewInt32(ctx, 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_int32(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 (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 { + 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) { int func_ret_code, ret; - assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT); + value = s->func_state.frame.cur_sp[-1]; + s->func_state.frame.cur_sp[-1] = JS_UNDEFINED; 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: @@ -19504,13 +18392,21 @@ 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: @@ -19521,13 +18417,13 @@ 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, + JSValue this_obj, + int argc, JSValue *argv, int magic, JSValue *func_data) { BOOL is_reject = magic & 1; JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR); - JSValueConst arg = argv[0]; + JSValue arg = argv[0]; /* XXX: what if s == NULL */ @@ -19544,12 +18440,12 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx, } 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_DupValue(ctx, arg)); + JS_Throw(ctx, js_dup(arg)); } else { /* return value of await */ - s->func_state->frame.cur_sp[-1] = JS_DupValue(ctx, arg); + s->func_state.frame.cur_sp[-1] = js_dup(arg); } js_async_generator_resume_next(ctx, s); } @@ -19557,8 +18453,8 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx, } /* magic = GEN_MAGIC_x */ -static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_async_generator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSAsyncGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_GENERATOR); @@ -19573,7 +18469,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, (JSValueConst *)&err); + 1, &err); JS_FreeValue(ctx, err); JS_FreeValue(ctx, res2); JS_FreeValue(ctx, resolving_funcs[0]); @@ -19584,8 +18480,8 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, if (!req) goto fail; req->completion_type = magic; - req->result = JS_DupValue(ctx, argv[0]); - req->promise = JS_DupValue(ctx, promise); + req->result = js_dup(argv[0]); + req->promise = js_dup(promise); req->resolving_funcs[0] = resolving_funcs[0]; req->resolving_funcs[1] = resolving_funcs[1]; list_add_tail(&req->link, &s->queue); @@ -19600,9 +18496,9 @@ 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, - JSValueConst this_obj, - int argc, JSValueConst *argv, +static JSValue js_async_generator_function_call(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSValue obj, func_ret; @@ -19613,12 +18509,14 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun return JS_EXCEPTION; s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START; init_list_head(&s->queue); - s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv); - if (!s->func_state) + if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) { + s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; 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); @@ -19627,7 +18525,7 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun if (JS_IsException(obj)) goto fail; s->generator = JS_VALUE_GET_OBJ(obj); - JS_SetOpaque(obj, s); + JS_SetOpaqueInternal(obj, s); return obj; fail: js_async_generator_free(ctx->rt, s); @@ -19654,9 +18552,6 @@ enum { TOK_AND_ASSIGN, TOK_XOR_ASSIGN, TOK_OR_ASSIGN, -#ifdef CONFIG_BIGNUM - TOK_MATH_POW_ASSIGN, -#endif TOK_POW_ASSIGN, TOK_LAND_ASSIGN, TOK_LOR_ASSIGN, @@ -19676,9 +18571,6 @@ enum { TOK_STRICT_NEQ, TOK_LAND, TOK_LOR, -#ifdef CONFIG_BIGNUM - TOK_MATH_POW, -#endif TOK_POW, TOK_ARROW, TOK_ELLIPSIS, @@ -19757,7 +18649,8 @@ typedef struct BlockEnv { int drop_count; /* number of stack elements to drop */ int label_finally; /* -1 if none */ int scope_level; - int has_iterator; + uint8_t has_iterator : 1; + uint8_t is_regular_stmt : 1; // i.e. not a loop statement } BlockEnv; typedef struct JSGlobalVar { @@ -19791,10 +18684,11 @@ typedef struct LabelSlot { RelocEntry *first_reloc; } LabelSlot; -typedef struct LineNumberSlot { +typedef struct SourceLocSlot { uint32_t pc; int line_num; -} LineNumberSlot; + int col_num; +} SourceLocSlot; typedef enum JSParseFunctionEnum { JS_PARSE_FUNC_STATEMENT, @@ -19848,11 +18742,12 @@ typedef struct JSFunctionDef { BOOL in_function_body; BOOL backtrace_barrier; JSFunctionKindEnum func_kind : 8; - JSParseFunctionEnum func_type : 8; - uint8_t js_mode; /* bitmap of JS_MODE_x */ + JSParseFunctionEnum func_type : 7; + uint8_t is_strict_mode : 1; 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; @@ -19862,7 +18757,7 @@ typedef struct JSFunctionDef { int var_object_idx; /* -1 if none */ int arg_var_object_idx; /* -1 if none (var object for the argument scope) */ int arguments_var_idx; /* -1 if none */ - int arguments_arg_idx; /* argument variable definition in argument scope, + int arguments_arg_idx; /* argument variable definition in argument scope, -1 if none */ int func_var_idx; /* variable containing the current function (-1 if none, only used if is_func_expr is true) */ @@ -19872,7 +18767,7 @@ typedef struct JSFunctionDef { 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; - + int scope_level; /* index into fd->scopes if the current lexical scope */ int scope_first; /* index into vd->vars of first lexically scoped variable */ int scope_size; /* allocated size of fd->scopes array */ @@ -19887,9 +18782,8 @@ typedef struct JSFunctionDef { DynBuf byte_code; int last_opcode_pos; /* -1 if no last opcode */ - int last_opcode_line_num; BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */ - + LabelSlot *label_slots; int label_size; /* allocated size for label_slots[] */ int label_count; @@ -19909,15 +18803,17 @@ typedef struct JSFunctionDef { int jump_size; int jump_count; - LineNumberSlot *line_number_slots; - int line_number_size; - int line_number_count; + SourceLocSlot *source_loc_slots; + int source_loc_size; + int source_loc_count; int line_number_last; int line_number_last_pc; + int col_number_last; /* pc2line table */ JSAtom filename; int line_num; + int col_num; DynBuf pc2line; char *source; /* raw source, utf-8 encoded */ @@ -19925,11 +18821,13 @@ typedef struct JSFunctionDef { JSModuleDef *module; /* != NULL when parsing a module */ BOOL has_await; /* TRUE if await is used (used in module eval) */ + JSInlineCache *ic; /* inline cache for field op */ } 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; union { struct { @@ -19938,9 +18836,6 @@ typedef struct JSToken { } str; struct { JSValue val; -#ifdef CONFIG_BIGNUM - slimb_t exponent; /* may be != 0 only if val is a float */ -#endif } num; struct { JSAtom atom; @@ -19957,19 +18852,23 @@ 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 */ 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 ext_json; /* true if accepting JSON superset */ } JSParseState; typedef struct JSOpCode { @@ -19996,7 +18895,6 @@ 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 @@ -20004,9 +18902,6 @@ 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); @@ -20040,6 +18935,7 @@ 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: { @@ -20103,25 +18999,47 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const JSContext *ctx = s->ctx; va_list ap; int backtrace_flags; - + va_start(ap, fmt); JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE); 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, s->filename, s->line_num, - backtrace_flags); + build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename, + s->line_num, s->col_num, backtrace_flags); return -1; } static int js_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); + 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); } - return next_token(s); } static int js_parse_expect_semi(JSParseState *s) @@ -20144,8 +19062,10 @@ 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; @@ -20180,10 +19100,11 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p) } if (c == '\n') { s->line_num++; + s->eol = &p[-1]; + s->mark = p; } else if (c >= 0x80) { - const uint8_t *p_next; - c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); - if (c > 0x10FFFF) { + c = utf8_decode(p - 1, &p_next); + if (p_next == p) { js_parse_error(s, "invalid UTF-8 sequence"); goto fail; } @@ -20209,6 +19130,7 @@ static __exception int js_parse_string(JSParseState *s, int sep, 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; @@ -20221,11 +19143,6 @@ static __exception int js_parse_string(JSParseState *s, int sep, goto invalid_char; c = *p; if (c < 0x20) { - if (!s->cur_func) { - if (do_throw) - js_parse_error(s, "invalid character in a JSON string"); - goto fail; - } if (sep == '`') { if (c == '\r') { if (p[1] == '\n') @@ -20246,12 +19163,15 @@ static __exception int js_parse_string(JSParseState *s, int sep, } if (c == '\\') { c = *p; - /* XXX: need a specific JSON case to avoid - accepting invalid escapes */ switch(c) { case '\0': - if (p >= s->buf_end) - goto invalid_char; + if (p >= s->buf_end) { + if (sep != '`') + goto invalid_char; + if (do_throw) + js_parse_error(s, "Unexpected end of input"); + goto fail; + } p++; break; case '\'': @@ -20267,33 +19187,29 @@ static __exception int js_parse_string(JSParseState *s, int sep, case '\n': /* ignore escaped newline sequence */ p++; - if (sep != '`') + if (sep != '`') { s->line_num++; + s->eol = &p[-1]; + s->mark = p; + } continue; default: - if (c >= '0' && c <= '9') { - if (!s->cur_func) - goto invalid_escape; /* JSON case */ - 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(s, "octal escape sequences are not allowed in strict mode"); - } - goto fail; + 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"); } + goto fail; } else if (c >= 0x80) { - const uint8_t *p_next; - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next); - if (c > 0x10FFFF) { + c = utf8_decode(p, &p_next); + if (p_next == p + 1) { goto invalid_utf8; } p = p_next; @@ -20301,12 +19217,12 @@ static __exception int js_parse_string(JSParseState *s, int sep, if (c == CP_LS || c == CP_PS) continue; } else { - parse_escape: ret = lre_parse_escape(&p, TRUE); if (ret == -1) { - invalid_escape: - if (do_throw) - js_parse_error(s, "malformed escape sequence in string literal"); + if (do_throw) { + js_parse_error(s, "Invalid %s escape sequence", + c == 'u' ? "Unicode" : "hexadecimal"); + } goto fail; } else if (ret < 0) { /* ignore the '\' (could output a warning) */ @@ -20318,9 +19234,8 @@ static __exception int js_parse_string(JSParseState *s, int sep, break; } } else if (c >= 0x80) { - const uint8_t *p_next; - c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); - if (c > 0x10FFFF) + c = utf8_decode(p - 1, &p_next); + if (p_next == p) goto invalid_utf8; p = p_next; } @@ -20352,7 +19267,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { static __exception int js_parse_regexp(JSParseState *s) { - const uint8_t *p; + const uint8_t *p, *p_next; BOOL in_class; StringBuffer b_s, *b = &b_s; StringBuffer b2_s, *b2 = &b2_s; @@ -20391,9 +19306,8 @@ static __exception int js_parse_regexp(JSParseState *s) else if (c == '\0' && p >= s->buf_end) goto eof_error; else if (c >= 0x80) { - const uint8_t *p_next; - c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); - if (c > 0x10FFFF) { + c = utf8_decode(p - 1, &p_next); + if (p_next == p) { goto invalid_utf8; } p = p_next; @@ -20401,9 +19315,8 @@ static __exception int js_parse_regexp(JSParseState *s) goto eol_error; } } else if (c >= 0x80) { - const uint8_t *p_next; - c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next); - if (c > 0x10FFFF) { + c = utf8_decode(p - 1, &p_next); + if (p_next == p) { invalid_utf8: js_parse_error(s, "invalid UTF-8 sequence"); goto fail; @@ -20422,14 +19335,8 @@ static __exception int js_parse_regexp(JSParseState *s) /* flags */ for(;;) { - 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) { - goto invalid_utf8; - } - } + c = utf8_decode(p, &p_next); + /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ if (!lre_js_is_ident_next(c)) break; if (string_buffer_putc(b2, c)) @@ -20453,7 +19360,7 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, { char *buf, *new_buf; size_t size, new_size; - + buf = *pbuf; size = *psize; if (size >= (SIZE_MAX / 3) * 2) @@ -20480,7 +19387,7 @@ 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->js_mode & JS_MODE_STRICT)) || + s->cur_func->is_strict_mode) || (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 && @@ -20521,11 +19428,11 @@ static void reparse_ident_token(JSParseState *s) static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, BOOL *pident_has_escape, int c, BOOL is_private) { - const uint8_t *p, *p1; + const uint8_t *p, *p_next; char ident_buf[128], *buf; size_t ident_size, ident_pos; - JSAtom atom; - + JSAtom atom = JS_ATOM_NULL; + p = *pp; buf = ident_buf; ident_size = sizeof(ident_buf); @@ -20533,30 +19440,29 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, if (is_private) buf[ident_pos++] = '#'; for(;;) { - p1 = p; - - if (c < 128) { + if (c < 0x80) { buf[ident_pos++] = c; } else { - ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c); + ident_pos += utf8_encode((uint8_t*)buf + ident_pos, c); } - c = *p1++; - if (c == '\\' && *p1 == 'u') { - c = lre_parse_escape(&p1, TRUE); + 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 >= 128) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); + } else if (c >= 0x80) { + c = utf8_decode(p, &p_next); + /* no need to test for invalid UTF-8, 0xFFFD is not ident_next */ } if (!lre_js_is_ident_next(c)) break; - p = p1; + p = p_next; if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { - if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) { - atom = JS_ATOM_NULL; + if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) goto done; - } } } + /* buf is pure ASCII or UTF-8 encoded */ atom = JS_NewAtomLen(s->ctx, buf, ident_pos); done: if (unlikely(buf != ident_buf)) @@ -20568,22 +19474,26 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, static __exception int next_token(JSParseState *s) { - const uint8_t *p; + const uint8_t *p, *p_next; int c; BOOL ident_has_escape; JSAtom atom; - - if (js_check_stack_overflow(s->ctx->rt, 0)) { - return js_parse_error(s, "stack overflow"); + int flags, radix; + + if (js_check_stack_overflow(s->ctx->rt, 1000)) { + JS_ThrowStackOverflow(s->ctx); + return -1; } - + 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; redo: s->token.line_num = s->line_num; + s->token.col_num = s->col_num; s->token.ptr = p; c = *p; switch(c) { @@ -20612,6 +19522,8 @@ 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++; goto redo; @@ -20619,7 +19531,7 @@ static __exception int next_token(JSParseState *s) case '\v': case ' ': case '\t': - p++; + s->mark = ++p; goto redo; case '/': if (p[1] == '*') { @@ -20637,21 +19549,22 @@ static __exception int next_token(JSParseState *s) if (*p == '\n') { s->line_num++; s->got_lf = TRUE; /* considered as LF for ASI */ - p++; + s->eol = p++; + s->mark = p; } else if (*p == '\r') { s->got_lf = TRUE; /* considered as LF for ASI */ p++; } else if (*p >= 0x80) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + c = utf8_decode(p, &p); + /* ignore invalid UTF-8 in comments */ if (c == CP_LS || c == CP_PS) { 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 */ @@ -20663,17 +19576,17 @@ static __exception int next_token(JSParseState *s) if (*p == '\r' || *p == '\n') break; if (*p >= 0x80) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + c = utf8_decode(p, &p); + /* ignore invalid UTF-8 in comments */ /* 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; @@ -20703,17 +19616,18 @@ static __exception int next_token(JSParseState *s) case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': + case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': + case 'Y': case 'Z': case '_': case '$': /* identifier */ + s->mark = p; p++; ident_has_escape = FALSE; has_ident: @@ -20729,20 +19643,21 @@ static __exception int next_token(JSParseState *s) case '#': /* private name */ { - const uint8_t *p1; p++; - 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); + 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; } if (!lre_js_is_ident_first(c)) { js_parse_error(s, "invalid first character of private name"); goto fail; } - p = p1; + p = p_next; ident_has_escape = FALSE; /* not used */ atom = parse_ident(s, &p, &ident_has_escape, c, TRUE); if (atom == JS_ATOM_NULL) @@ -20758,51 +19673,56 @@ static __exception int next_token(JSParseState *s) break; } if (p[1] >= '0' && p[1] <= '9') { + flags = ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_FLOAT; + radix = 10; goto parse_number; - } else { - goto def_token; } - break; + goto def_token; case '0': - /* in strict mode, octal literals are not accepted */ - if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) { - js_parse_error(s, "octal literals are deprecated in strict mode"); + if (is_digit(p[1])) { /* handle legacy octal */ + if (s->cur_func->is_strict_mode) { + js_parse_error(s, "Octal literals are not allowed in strict mode"); + goto fail; + } + /* Legacy octal: no separators, no suffix, no floats, + base 8 unless non octal digits are detected */ + flags = 0; + radix = 8; + while (is_digit(*p)) { + if (*p >= '8' && *p <= '9') + radix = 10; + p++; + } + p = s->token.ptr; + goto parse_number; + } + if (p[1] == '_') { + js_parse_error(s, "Numeric separator can not be used after leading 0"); goto fail; } + flags = ATOD_ACCEPT_HEX_PREFIX | ATOD_ACCEPT_BIN_OCT | + ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX; + radix = 10; goto parse_number; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': - case '9': + case '9': /* number */ - parse_number: { JSValue ret; - const uint8_t *p1; - int flags, radix; - flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL | - ATOD_ACCEPT_UNDERSCORES; - flags |= ATOD_ACCEPT_SUFFIX; -#ifdef CONFIG_BIGNUM - if (s->cur_func->js_mode & JS_MODE_MATH) { - flags |= ATOD_MODE_BIGINT; - if (s->cur_func->js_mode & JS_MODE_MATH) - flags |= ATOD_TYPE_BIG_FLOAT; - } -#endif - radix = 0; -#ifdef CONFIG_BIGNUM - s->token.u.num.exponent = 0; - ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix, - flags, &s->token.u.num.exponent); -#else - ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix, - flags); -#endif + const char *p1; + + flags = ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_UNDERSCORES | ATOD_ACCEPT_SUFFIX; + radix = 10; + parse_number: + p1 = (const char *)p; + ret = js_atof(s->ctx, p1, s->buf_end - p, &p1, radix, flags); + p = (const uint8_t *)p1; if (JS_IsException(ret)) goto fail; /* reject `10instanceof Number` */ if (JS_VALUE_IS_NAN(ret) || - lre_js_is_ident_next(unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1))) { + lre_js_is_ident_next(utf8_decode(p, &p_next))) { JS_FreeValue(s->ctx, ret); js_parse_error(s, "invalid number literal"); goto fail; @@ -20851,8 +19771,8 @@ static __exception int next_token(JSParseState *s) p += 2; s->token.val = TOK_MINUS_ASSIGN; } else if (p[1] == '-') { - if (s->allow_html_comments && - p[2] == '>' && s->last_line_num != s->line_num) { + if (s->allow_html_comments && p[2] == '>' && + (s->got_lf || s->last_ptr == s->buf_start)) { /* Annex B: `-->` at beginning of line is an html comment end. It extends to the end of the line. */ @@ -20953,33 +19873,6 @@ static __exception int next_token(JSParseState *s) goto def_token; } break; -#ifdef CONFIG_BIGNUM - /* in math mode, '^' is the power operator. '^^' is always the - xor operator and '**' is always the power operator */ - case '^': - if (p[1] == '=') { - p += 2; - if (s->cur_func->js_mode & JS_MODE_MATH) - s->token.val = TOK_MATH_POW_ASSIGN; - else - s->token.val = TOK_XOR_ASSIGN; - } else if (p[1] == '^') { - if (p[2] == '=') { - p += 3; - s->token.val = TOK_XOR_ASSIGN; - } else { - p += 2; - s->token.val = '^'; - } - } else { - p++; - if (s->cur_func->js_mode & JS_MODE_MATH) - s->token.val = TOK_MATH_POW; - else - s->token.val = '^'; - } - break; -#else case '^': if (p[1] == '=') { p += 2; @@ -20988,7 +19881,6 @@ static __exception int next_token(JSParseState *s) goto def_token; } break; -#endif case '|': if (p[1] == '=') { p += 2; @@ -21022,17 +19914,20 @@ static __exception int next_token(JSParseState *s) } break; default: - if (c >= 128) { - /* unicode value */ - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if (c >= 0x80) { /* non-ASCII code-point */ + c = utf8_decode(p, &p_next); + if (p_next == p + 1) + goto invalid_utf8; + p = p_next; switch(c) { case CP_PS: case CP_LS: /* XXX: should avoid incrementing line_number, but needed to handle HTML comments */ - goto line_terminator; + 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; @@ -21048,16 +19943,150 @@ 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; } +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 */ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) { @@ -21065,7 +20094,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) char ident_buf[128], *buf; size_t ident_size, ident_pos; JSAtom atom; - + p = *pp; buf = ident_buf; ident_size = sizeof(ident_buf); @@ -21084,6 +20113,7 @@ 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)) @@ -21094,20 +20124,23 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) static __exception int json_next_token(JSParseState *s) { - const uint8_t *p; + const uint8_t *p, *p_next; int c; JSAtom atom; - - if (js_check_stack_overflow(s->ctx->rt, 0)) { - return js_parse_error(s, "stack overflow"); + + if (js_check_stack_overflow(s->ctx->rt, 1000)) { + JS_ThrowStackOverflow(s->ctx); + return -1; } - + 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) { @@ -21119,13 +20152,11 @@ static __exception int json_next_token(JSParseState *s) } break; case '\'': - if (!s->ext_json) { - /* JSON does not accept single quoted strings */ - goto def_token; - } - /* fall through */ + /* JSON does not accept single quoted strings */ + goto def_token; case '\"': - if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p)) + p++; + if (json_parse_string(s, &p)) goto fail; break; case '\r': /* accept DOS and MAC newline sequences */ @@ -21134,91 +20165,36 @@ static __exception int json_next_token(JSParseState *s) } /* fall thru */ case '\n': - p++; s->line_num++; + s->eol = p++; + s->mark = p; goto redo; case '\f': case '\v': - if (!s->ext_json) { - /* JSONWhitespace does not match , nor */ - goto def_token; - } - /* fall through */ + /* JSONWhitespace does not match , nor */ + goto def_token; case ' ': case '\t': p++; + s->mark = p; goto redo; case '/': - 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 == '\n') { - s->line_num++; - p++; - } else if (*p == '\r') { - p++; - } else 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; + /* JSON does not accept comments */ + goto def_token; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': + case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': + case 'Y': case 'Z': case '_': case '$': /* identifier : only pure ascii characters are accepted */ @@ -21231,44 +20207,37 @@ static __exception int json_next_token(JSParseState *s) s->token.u.ident.is_reserved = FALSE; s->token.val = TOK_IDENT; break; - case '+': - if (!s->ext_json || !is_digit(p[1])) - goto def_token; + case '-': + if (!is_digit(p[1])) { + json_parse_error(s, p, "No number after minus sign"); + goto fail; + } goto parse_number; case '0': - if (is_digit(p[1])) - goto def_token; - goto parse_number; - case '-': - if (!is_digit(p[1])) - goto def_token; + 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': + case '9': /* number */ parse_number: - { - JSValue ret; - int flags, radix; - if (!s->ext_json) { - flags = 0; - radix = 10; - } else { - flags = ATOD_ACCEPT_BIN_OCT; - radix = 0; - } - ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix, - flags); - if (JS_IsException(ret)) - goto fail; - s->token.val = TOK_NUMBER; - s->token.u.num.val = ret; - } + if (json_parse_number(s, &p)) + goto fail; break; default: - if (c >= 128) { - js_parse_error(s, "unexpected character"); + 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); + } goto fail; } def_token: @@ -21276,6 +20245,7 @@ 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); @@ -21293,7 +20263,7 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) { const uint8_t *p; uint32_t c; - + /* skip spaces and comments */ p = *pp; for (;;) { @@ -21356,6 +20326,9 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) 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; } @@ -21382,12 +20355,10 @@ static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end) if (*p == '\n' || *p == '\r') { break; } else if (*p >= 0x80) { - c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); - if (c == CP_LS || c == CP_PS) { + c = utf8_decode(p, &p); + /* purposely ignore UTF-8 encoding errors in this comment line */ + if (c == CP_LS || c == CP_PS) break; - } else if (c == -1) { - p++; /* skip invalid UTF-8 */ - } } else { p++; } @@ -21396,29 +20367,6 @@ 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) return OP_invalid; @@ -21436,10 +20384,8 @@ 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; default: @@ -21462,19 +20408,21 @@ 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) +{ + 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); +} + static void emit_op(JSParseState *s, uint8_t val) { JSFunctionDef *fd = s->cur_func; DynBuf *bc = &fd->byte_code; - /* Use the line number of the last token used, not the next token, - nor the current offset in the source file. - */ - if (unlikely(fd->last_opcode_line_num != s->last_line_num)) { - dbuf_putc(bc, OP_line_num); - dbuf_put_u32(bc, s->last_line_num); - fd->last_opcode_line_num = s->last_line_num; - } fd->last_opcode_pos = bc->size; dbuf_putc(bc, val); } @@ -21484,6 +20432,36 @@ static void emit_atom(JSParseState *s, JSAtom name) emit_u32(s, JS_DupAtom(s->ctx, name)); } +static force_inline uint32_t get_index_hash(JSAtom atom, int hash_bits) +{ + return (atom * 0x9e370001) >> (32 - hash_bits); +} + +static void emit_ic(JSParseState *s, JSAtom atom) +{ + uint32_t h; + JSContext *ctx; + JSInlineCache *ic; + JSInlineCacheHashSlot *ch; + + ic = s->cur_func->ic; + ctx = s->ctx; + if (ic->count + 1 >= ic->capacity && resize_ic_hash(ctx, ic)) + return; + h = get_index_hash(atom, ic->hash_bits); + for (ch = ic->hash[h]; ch != NULL; ch = ch->next) + if (ch->atom == atom) + return; + ch = js_malloc(ctx, sizeof(*ch)); + if (unlikely(!ch)) + return; + ch->atom = JS_DupAtom(ctx, atom); + ch->index = 0; + ch->next = ic->hash[h]; + ic->hash[h] = ch; + ic->count += 1; +} + static int update_label(JSFunctionDef *s, int label, int delta) { LabelSlot *ls; @@ -21559,7 +20537,7 @@ static int emit_goto(JSParseState *s, int opcode, int label) static int cpool_add(JSParseState *s, JSValue val) { JSFunctionDef *fd = s->cur_func; - + if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]), &fd->cpool_size, fd->cpool_count + 1)) return -1; @@ -21567,7 +20545,7 @@ static int cpool_add(JSParseState *s, JSValue val) return fd->cpool_count - 1; } -static __exception int emit_push_const(JSParseState *s, JSValueConst val, +static __exception int emit_push_const(JSParseState *s, JSValue val, BOOL as_atom) { int idx; @@ -21592,6 +20570,86 @@ static __exception int emit_push_const(JSParseState *s, JSValueConst 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) @@ -21606,11 +20664,24 @@ static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) { + JSVarDef *vd; int i; - for(i = fd->var_count; i-- > 0;) { - if (fd->vars[i].var_name == name && fd->vars[i].scope_level == 0) + + 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; + } +not_found: return find_arg(ctx, fd, name); } @@ -21773,7 +20844,9 @@ 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) { - JS_ThrowInternalError(ctx, "too many local variables"); + // 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); return -1; } if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]), @@ -21783,6 +20856,8 @@ 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; } @@ -21807,7 +20882,7 @@ 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->js_mode & JS_MODE_STRICT) + if (fd->is_strict_mode) fd->vars[idx].is_const = TRUE; } return idx; @@ -21853,7 +20928,9 @@ 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) { - JS_ThrowInternalError(ctx, "too many arguments"); + // 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); return -1; } if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]), @@ -21918,7 +20995,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, 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->js_mode & JS_MODE_STRICT) && + if (!(!fd->is_strict_mode && var_def_type == JS_VAR_DEF_FUNCTION_DECL && fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) { goto redef_lex_error; @@ -21945,7 +21022,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) { return js_parse_error(s, "invalid redefinition of a variable"); } - + if (fd->is_global_var) { JSGlobalVar *hf; hf = find_global_var(fd, name); @@ -21954,7 +21031,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, return js_parse_error(s, "invalid redefinition of global identifier"); } } - + if (fd->is_eval && (fd->eval_type == JS_EVAL_TYPE_GLOBAL || fd->eval_type == JS_EVAL_TYPE_MODULE) && @@ -22047,7 +21124,7 @@ 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_line, int start_col); static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s); static __exception int js_parse_function_decl2(JSParseState *s, JSParseFunctionEnum func_type, @@ -22055,6 +21132,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, 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); @@ -22070,7 +21148,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, JSValueConst obj) +static int seal_template_obj(JSContext *ctx, JSValue obj) { JSObject *p; JSShapeProperty *prs; @@ -22121,7 +21199,7 @@ 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_DupValue(ctx, s->token.u.str.str), + js_dup(s->token.u.str.str), JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) { return -1; } @@ -22156,6 +21234,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) goto done1; emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_concat); + emit_ic(s, JS_ATOM_concat); } depth++; } else { @@ -22178,6 +21257,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) * 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; if (js_parse_template_part(s, s->buf_ptr)) return -1; } @@ -22226,7 +21306,7 @@ static int __exception js_parse_property_name(JSParseState *s, 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) @@ -22236,7 +21316,8 @@ static int __exception js_parse_property_name(JSParseState *s, 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 == '(' || + s->token.val == '=' || s->token.val == ';') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -22252,7 +21333,8 @@ static int __exception js_parse_property_name(JSParseState *s, 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 == '(' || + s->token.val == '=' || s->token.val == ';') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -22292,21 +21374,7 @@ static int __exception js_parse_property_name(JSParseState *s, } else if (s->token.val == TOK_NUMBER) { JSValue val; val = s->token.u.num.val; -#ifdef CONFIG_BIGNUM - if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - val = s->ctx->rt->bigfloat_ops. - mul_pow10_to_float64(s->ctx, &p->num, - s->token.u.num.exponent); - if (JS_IsException(val)) - goto fail; - name = JS_ValueToAtom(s->ctx, val); - JS_FreeValue(s->ctx, val); - } else -#endif - { - name = JS_ValueToAtom(s->ctx, val); - } + name = JS_ValueToAtom(s->ctx, val); if (name == JS_ATOM_NULL) goto fail; if (next_token(s)) @@ -22345,16 +21413,24 @@ 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; 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; } @@ -22362,8 +21438,12 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp) 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); } @@ -22437,6 +21517,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ * 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; if (js_parse_template_part(s, s->buf_ptr)) goto done; goto handle_template; @@ -22452,7 +21533,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ if (level >= sizeof(state)) goto done; state[level++] = '`'; - } + } break; case TOK_EOF: goto done; @@ -22469,7 +21550,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ case '=': bits |= SKIP_HAS_ASSIGNMENT; break; - + case TOK_DIV_ASSIGN: tok_len = 2; goto parse_regexp; @@ -22568,7 +21649,7 @@ static __exception int js_parse_object_literal(JSParseState *s) { JSAtom name = JS_ATOM_NULL; const uint8_t *start_ptr; - int start_line, prop_type; + int start_line, start_col, prop_type; BOOL has_proto; if (next_token(s)) @@ -22580,6 +21661,7 @@ static __exception int js_parse_object_literal(JSParseState *s) /* 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)) @@ -22625,7 +21707,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_ptr, start_line, start_col)) goto fail; if (name == JS_ATOM_NULL) { emit_op(s, OP_define_method_computed); @@ -22679,15 +21761,13 @@ static __exception int js_parse_object_literal(JSParseState *s) } /* allow the 'in' binary operator */ -#define PF_IN_ACCEPTED (1 << 0) +#define PF_IN_ACCEPTED (1 << 0) /* allow function calls parsing in js_parse_postfix_expr() */ -#define PF_POSTFIX_CALL (1 << 1) -/* allow arrow functions parsing in js_parse_postfix_expr() */ -#define PF_ARROW_FUNC (1 << 2) +#define PF_POSTFIX_CALL (1 << 1) /* allow the exponentiation operator in js_parse_unary() */ -#define PF_POW_ALLOWED (1 << 3) +#define PF_POW_ALLOWED (1 << 2) /* forbid the exponentiation operator in js_parse_unary() */ -#define PF_POW_FORBIDDEN (1 << 4) +#define PF_POW_FORBIDDEN (1 << 3) static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags); @@ -22696,41 +21776,6 @@ static __exception int js_parse_left_hand_side_expr(JSParseState *s) return js_parse_postfix_expr(s, PF_POSTFIX_CALL); } -/* XXX: could generate specific bytecode */ -static __exception int js_parse_class_default_ctor(JSParseState *s, - BOOL has_super, - JSFunctionDef **pfd) -{ - JSParsePos pos; - const char *str; - int ret, line_num; - JSParseFunctionEnum func_type; - const uint8_t *saved_buf_end; - - js_parse_get_pos(s, &pos); - if (has_super) { - /* spec change: no argument evaluation */ - str = "(){super(...arguments);}"; - func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR; - } else { - str = "(){}"; - func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; - } - line_num = s->token.line_num; - saved_buf_end = s->buf_end; - s->buf_ptr = (uint8_t *)str; - s->buf_end = (uint8_t *)(str + strlen(str)); - ret = next_token(s); - if (!ret) { - ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL, - JS_ATOM_NULL, (uint8_t *)str, - line_num, JS_PARSE_EXPORT_NONE, pfd); - } - s->buf_end = saved_buf_end; - ret |= js_parse_seek_token(s, &pos); - return ret; -} - /* find field in the current scope */ static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, JSAtom name, int scope_level) @@ -22753,7 +21798,7 @@ static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, static void emit_class_field_init(JSParseState *s) { int label_next; - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_class_fields_init); emit_u16(s, s->cur_func->scope_level); @@ -22761,13 +21806,13 @@ static void emit_class_field_init(JSParseState *s) /* no need to call the class field initializer if not defined */ emit_op(s, OP_dup); label_next = emit_goto(s, OP_if_false, -1); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); - + emit_op(s, OP_swap); - + emit_op(s, OP_call_method); emit_u16(s, 0); @@ -22793,13 +21838,13 @@ static __exception int emit_class_init_start(JSParseState *s, ClassFieldsDef *cf) { int label_add_brand; - + cf->fields_init_fd = js_parse_function_class_fields_init(s); if (!cf->fields_init_fd) return -1; s->cur_func = cf->fields_init_fd; - + if (!cf->is_static) { /* add the brand to the newly created instance */ /* XXX: would be better to add the code only if needed, maybe in a @@ -22807,17 +21852,17 @@ static __exception int emit_class_init_start(JSParseState *s, emit_op(s, OP_push_false); /* will be patched later */ cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos; label_add_brand = emit_goto(s, OP_if_false, -1); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_home_object); emit_u16(s, 0); - + emit_op(s, OP_add_brand); - + emit_label(s, label_add_brand); } s->cur_func = s->cur_func->parent; @@ -22831,7 +21876,7 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf) s->cur_func = cf->fields_init_fd; emit_op(s, OP_return_undef); s->cur_func = s->cur_func->parent; - + cpool_idx = cpool_add(s, JS_NULL); cf->fields_init_fd->parent_cpool_idx = cpool_idx; emit_op(s, OP_fclosure); @@ -22839,6 +21884,72 @@ 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, JSParseExportEnum export_flag) @@ -22848,16 +21959,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 saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset; + int class_name_var_idx, prop_type, ctor_cpool_offset; int class_flags = 0, i, define_class_offset; - BOOL is_static, is_private; + BOOL is_static, is_private, is_strict_mode; 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 */ - saved_js_mode = fd->js_mode; - fd->js_mode |= JS_MODE_STRICT; + is_strict_mode = fd->is_strict_mode; + fd->is_strict_mode = TRUE; if (next_token(s)) goto fail; if (s->token.val == TOK_IDENT) { @@ -22917,7 +22028,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else { class_name1 = class_name; } - + emit_op(s, OP_define_class); emit_atom(s, class_name1); emit_u8(s, class_flags); @@ -22930,7 +22041,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, cf->need_brand = FALSE; cf->is_static = i; } - + ctor_fd = NULL; while (s->token.val != '}') { if (s->token.val == ';') { @@ -22938,26 +22049,29 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, goto fail; continue; } - is_static = (s->token.val == TOK_STATIC); + is_static = FALSE; + if (s->token.val == TOK_STATIC) { + int next = peek_token(s, TRUE); + if (!(next == ';' || next == '}' || next == '(' || next == '=')) + is_static = TRUE; + } prop_type = -1; if (is_static) { if (next_token(s)) goto fail; if (s->token.val == '{') { ClassFieldsDef *cf = &class_fields[is_static]; - JSFunctionDef *init; - if (!cf->fields_init_fd) { + 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.ptr, + s->token.line_num, + s->token.col_num, JS_PARSE_EXPORT_NONE, &init) < 0) { goto fail; } @@ -22967,6 +22081,13 @@ 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); @@ -22995,7 +22116,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } is_private = prop_type & PROP_TYPE_PRIVATE; prop_type &= ~PROP_TYPE_PRIVATE; - + if ((name == JS_ATOM_constructor && !is_static && prop_type != PROP_TYPE_IDENT) || (name == JS_ATOM_prototype && is_static) || @@ -23032,7 +22153,9 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set, JS_FUNC_NORMAL, JS_ATOM_NULL, - start_ptr, s->token.line_num, + start_ptr, + s->token.line_num, + s->token.col_num, JS_PARSE_EXPORT_NONE, &method_fd)) goto fail; if (is_private) { @@ -23043,7 +22166,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (is_set) { JSAtom setter_name; int ret; - + setter_name = get_private_setter_name(ctx, name); if (setter_name == JS_ATOM_NULL) goto fail; @@ -23069,7 +22192,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') { ClassFieldsDef *cf = &class_fields[is_static]; JSAtom field_var_name = JS_ATOM_NULL; - + /* class field */ /* XXX: spec: not consistent with method name checks */ @@ -23077,7 +22200,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, js_parse_error(s, "invalid field name"); goto fail; } - + if (is_private) { if (find_private_class_field(ctx, fd, name, fd->scope_level) >= 0) { @@ -23116,6 +22239,14 @@ 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); @@ -23127,7 +22258,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_atom(s, name); emit_u16(s, s->cur_func->scope_level); } - + if (s->token.val == '=') { if (next_token(s)) goto fail; @@ -23154,7 +22285,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else { JSParseFunctionEnum func_type; JSFunctionKindEnum func_kind; - + func_type = JS_PARSE_FUNC_METHOD; func_kind = JS_FUNC_NORMAL; if (prop_type == PROP_TYPE_STAR) { @@ -23176,7 +22307,11 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (is_private) { 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, JS_PARSE_EXPORT_NONE, &method_fd)) + 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)) goto fail; if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR || func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { @@ -23227,14 +22362,11 @@ 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. */ - if (!(fd->js_mode & JS_MODE_STRIP)) { - 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; - } + 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)) @@ -23250,7 +22382,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_op(s, OP_null); emit_op(s, OP_swap); emit_op(s, OP_add_brand); - + /* define the brand field in 'this' of the initializer */ if (!cf->fields_init_fd) { if (emit_class_init_start(s, cf)) @@ -23260,7 +22392,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, OP_add_brand_instance code */ cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true; } - + /* store the function to initialize the fields to that it can be referenced by the constructor */ var_idx = define_var(s, fd, JS_ATOM_class_fields_init, @@ -23287,16 +22419,6 @@ 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]; @@ -23306,7 +22428,16 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_u16(s, 0); 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); @@ -23337,13 +22468,13 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_var_name); - fd->js_mode = saved_js_mode; + fd->is_strict_mode = is_strict_mode; return 0; fail: JS_FreeAtom(ctx, name); JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_var_name); - fd->js_mode = saved_js_mode; + fd->is_strict_mode = is_strict_mode; return -1; } @@ -23402,6 +22533,7 @@ static __exception int js_parse_array_literal(JSParseState *s) emit_u32(s, idx); emit_op(s, OP_put_field); emit_atom(s, JS_ATOM_length); + emit_ic(s, JS_ATOM_length); } goto done; } @@ -23417,33 +22549,7 @@ 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; if (s->token.val != ',') { @@ -23466,6 +22572,7 @@ static __exception int js_parse_array_literal(JSParseState *s) emit_op(s, OP_dup1); /* array length - array array length */ emit_op(s, OP_put_field); emit_atom(s, JS_ATOM_length); + emit_ic(s, JS_ATOM_length); } else { emit_op(s, OP_drop); /* array length - array */ } @@ -23512,7 +22619,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->js_mode & JS_MODE_STRICT)) { + fd->is_strict_mode) { return js_parse_error(s, "invalid lvalue in strict mode"); } if (name == JS_ATOM_this || name == JS_ATOM_new_target) @@ -23566,6 +22673,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, case OP_get_field: emit_op(s, OP_get_field2); emit_atom(s, name); + emit_ic(s, name); break; case OP_scope_get_private_field: emit_op(s, OP_scope_get_private_field2); @@ -23701,7 +22809,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, default: break; } - + switch(opcode) { case OP_scope_get_var: /* val -- */ assert(special == PUT_LVALUE_NOKEEP || @@ -23713,6 +22821,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, case OP_get_field: emit_op(s, OP_put_field); emit_u32(s, name); /* name has refcount */ + emit_ic(s, name); break; case OP_scope_get_private_field: emit_op(s, OP_scope_put_private_field); @@ -23755,17 +22864,25 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) { JSFunctionDef *fd = s->cur_func; JSVarDefEnum var_def_type; - + if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) { return js_parse_error(s, "yield is a reserved identifier"); } if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) - && (fd->js_mode & JS_MODE_STRICT)) { + && fd->is_strict_mode) { return js_parse_error(s, "invalid variable name in strict mode"); } - if ((name == JS_ATOM_let || name == JS_ATOM_undefined) - && (tok == TOK_LET || tok == TOK_CONST)) { - return js_parse_error(s, "invalid lexical variable name"); + 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"); + } } switch(tok) { case TOK_LET: @@ -23830,7 +22947,7 @@ static int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name) return 0; duplicate: - return js_parse_error(s, "duplicate parameter names not allowed in this context"); + return js_parse_error(s, "Duplicate parameter name not allowed in this context"); } static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg) @@ -23838,7 +22955,7 @@ 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->js_mode & JS_MODE_STRICT) && + || (s->cur_func->is_strict_mode && (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; @@ -23866,7 +22983,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, JSAtom prop_name, var_name; int opcode, scope, tok1, skip_bits; BOOL has_initializer; - + + label_lvalue = -1; + if (has_ellipsis < 0) { /* pre-parse destructuration target for spread detection */ js_parse_skip_parens_token(s, &skip_bits, FALSE); @@ -23974,6 +23093,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, /* get the named property from the source object */ emit_op(s, OP_get_field2); emit_u32(s, prop_name); + emit_ic(s, prop_name); } if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE) < 0) return -1; @@ -24063,12 +23183,13 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, /* source -- val */ emit_op(s, OP_get_field); emit_u32(s, prop_name); + emit_ic(s, prop_name); } } else { /* 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->js_mode & JS_MODE_STRICT) && + if (s->cur_func->is_strict_mode && (prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) { js_parse_error(s, "invalid destructuring target"); goto prop_error; @@ -24094,6 +23215,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, /* source -- source val */ emit_op(s, OP_get_field2); emit_u32(s, prop_name); + emit_ic(s, prop_name); } set_val: if (tok) { @@ -24299,13 +23421,13 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label, emit_label(s, label_next); } -/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */ +/* allowed parse_flags: PF_POSTFIX_CALL */ 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; - + call_type = FUNC_CALL_NORMAL; switch(s->token.val) { case TOK_NUMBER: @@ -24316,34 +23438,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) { emit_op(s, OP_push_i32); emit_u32(s, JS_VALUE_GET_INT(val)); - } else -#ifdef CONFIG_BIGNUM - if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) { - slimb_t e; - int ret; - - /* need a runtime conversion */ - /* XXX: could add a cache and/or do it once at - the start of the function */ - if (emit_push_const(s, val, 0) < 0) - return -1; - e = s->token.u.num.exponent; - if (e == (int32_t)e) { - emit_op(s, OP_push_i32); - emit_u32(s, e); - } else { - val = JS_NewBigInt64_1(s->ctx, e); - if (JS_IsException(val)) - return -1; - ret = emit_push_const(s, val, 0); - JS_FreeValue(s->ctx, val); - if (ret < 0) - return -1; - } - emit_op(s, OP_mul_pow10); - } else -#endif - { + } else { if (emit_push_const(s, val, 0) < 0) return -1; } @@ -24361,7 +23456,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (next_token(s)) return -1; break; - + case TOK_DIV_ASSIGN: s->buf_ptr -= 2; goto parse_regexp; @@ -24384,8 +23479,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) 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, - s->filename, s->token.line_num, + build_backtrace(s->ctx, s->ctx->rt->current_exception, JS_UNDEFINED, + s->filename, + s->token.line_num, + s->token.col_num, backtrace_flags); return -1; } @@ -24402,21 +23499,15 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) } break; case '(': - if ((parse_flags & PF_ARROW_FUNC) && - js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) { - if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, - JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, s->token.line_num)) - return -1; - } else { - if (js_parse_expr_paren(s)) - return -1; - } + if (js_parse_expr_paren(s)) + return -1; break; 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.ptr, + s->token.line_num, + s->token.col_num)) return -1; break; case TOK_CLASS: @@ -24451,34 +23542,23 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (s->token.u.ident.is_reserved) { return js_parse_error_reserved_identifier(s); } - if ((parse_flags & PF_ARROW_FUNC) && - peek_token(s, TRUE) == TOK_ARROW) { - if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, - JS_FUNC_NORMAL, JS_ATOM_NULL, - s->token.ptr, s->token.line_num)) - return -1; - } else if (token_is_pseudo_keyword(s, JS_ATOM_async) && - peek_token(s, TRUE) != '\n') { + 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; 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)) - return -1; - } else if ((parse_flags & PF_ARROW_FUNC) && - ((s->token.val == '(' && - 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))) { - if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW, - JS_FUNC_ASYNC, JS_ATOM_NULL, - source_ptr, source_line_num)) + source_ptr, + source_line_num, + source_col_num)) return -1; } else { name = JS_DupAtom(s->ctx, JS_ATOM_async); @@ -24491,7 +23571,7 @@ 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)) { /* update line number before emitting code */ JS_FreeAtom(s->ctx, name); return -1; } @@ -24536,6 +23616,7 @@ 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; @@ -24605,7 +23686,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) for(;;) { JSFunctionDef *fd = s->cur_func; BOOL has_optional_chain = FALSE; - + if (s->token.val == TOK_QUESTION_MARK_DOT) { /* optional chaining */ if (next_token(s)) @@ -24635,6 +23716,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) 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 */ @@ -24756,7 +23838,8 @@ 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 call arguments"); + return js_parse_error(s, "Too many arguments in function call (only %d allowed)", + 65535 - 1); } if (s->token.val == TOK_ELLIPSIS) break; @@ -24782,34 +23865,8 @@ 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; @@ -24944,6 +24001,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) } emit_op(s, OP_get_field); emit_atom(s, s->token.u.ident.atom); + emit_ic(s, s->token.u.ident.atom); } } if (next_token(s)) @@ -25059,7 +24117,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->js_mode & JS_MODE_STRICT) { + if (fd->is_strict_mode) { 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; @@ -25083,7 +24141,7 @@ static __exception int js_parse_delete(JSParseState *s) return 0; } -/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */ +/* allowed parse_flags: PF_POW_ALLOWED, PF_POW_FORBIDDEN */ static __exception int js_parse_unary(JSParseState *s, int parse_flags) { int op; @@ -25174,8 +24232,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) parse_flags = 0; break; default: - if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) | - PF_POSTFIX_CALL)) + if (js_parse_postfix_expr(s, PF_POSTFIX_CALL)) return -1; if (!s->got_lf && (s->token.val == TOK_DEC || s->token.val == TOK_INC)) { @@ -25188,64 +24245,41 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND, FALSE); if (next_token(s)) - return -1; + return -1; } break; } if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) { -#ifdef CONFIG_BIGNUM - if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) { - /* Extended exponentiation syntax rules: we extend the ES7 - grammar in order to have more intuitive semantics: - -2**2 evaluates to -4. */ - if (!(s->cur_func->js_mode & JS_MODE_MATH)) { - if (parse_flags & PF_POW_FORBIDDEN) { - JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'"); - return -1; - } - } - if (next_token(s)) - return -1; - if (js_parse_unary(s, PF_POW_ALLOWED)) - return -1; - emit_op(s, OP_pow); - } -#else if (s->token.val == TOK_POW) { /* Strict ES7 exponentiation syntax rules: To solve conficting semantics between different implementations 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) { - JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'"); - return -1; - } + if (parse_flags & PF_POW_FORBIDDEN) + return js_parse_error(s, "unparenthesized unary expression can't appear on the left-hand side of '**'"); if (next_token(s)) return -1; if (js_parse_unary(s, PF_POW_ALLOWED)) return -1; emit_op(s, OP_pow); } -#endif } return 0; } -/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */ +/* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_expr_binary(JSParseState *s, int level, int parse_flags) { int op, opcode; if (level == 0) { - return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) | - PF_POW_ALLOWED); + 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) { JSAtom atom; - atom = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) goto fail_private_in; @@ -25253,7 +24287,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, goto fail_private_in; if (next_token(s)) goto fail_private_in; - if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC)) { + if (js_parse_expr_binary(s, level - 1, parse_flags)) { fail_private_in: JS_FreeAtom(s->ctx, atom); return -1; @@ -25279,12 +24313,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, opcode = OP_div; break; case '%': -#ifdef CONFIG_BIGNUM - if (s->cur_func->js_mode & JS_MODE_MATH) - opcode = OP_math_mod; - else -#endif - opcode = OP_mod; + opcode = OP_mod; break; default: return 0; @@ -25395,14 +24424,15 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level, } if (next_token(s)) return -1; - if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC)) + emit_source_loc(s); + if (js_parse_expr_binary(s, level - 1, parse_flags)) return -1; emit_op(s, opcode); } return 0; } -/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */ +/* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_logical_and_or(JSParseState *s, int op, int parse_flags) { @@ -25426,11 +24456,10 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op, emit_op(s, OP_drop); if (op == TOK_LAND) { - if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC)) + if (js_parse_expr_binary(s, 8, parse_flags)) return -1; } else { - if (js_parse_logical_and_or(s, TOK_LAND, - parse_flags & ~PF_ARROW_FUNC)) + if (js_parse_logical_and_or(s, TOK_LAND, parse_flags)) return -1; } if (s->token.val != op) { @@ -25448,7 +24477,7 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op, static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags) { int label1; - + if (js_parse_logical_and_or(s, TOK_LOR, parse_flags)) return -1; if (s->token.val == TOK_DOUBLE_QUESTION_MARK) { @@ -25456,13 +24485,13 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags) for(;;) { if (next_token(s)) return -1; - + emit_op(s, OP_dup); emit_op(s, OP_is_undefined_or_null); emit_goto(s, OP_if_false, label1); emit_op(s, OP_drop); - - if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC)) + + if (js_parse_expr_binary(s, 8, parse_flags)) return -1; if (s->token.val != TOK_DOUBLE_QUESTION_MARK) break; @@ -25472,7 +24501,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags) return 0; } -/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */ +/* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags) { int label1, label2; @@ -25501,8 +24530,6 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags) return 0; } -static void emit_return(JSParseState *s, BOOL hasval); - /* allowed parse_flags: PF_IN_ACCEPTED */ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) { @@ -25512,7 +24539,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) if (s->token.val == TOK_YIELD) { BOOL is_star = FALSE, is_async; - + if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR)) return js_parse_error(s, "unexpected 'yield' keyword"); if (!s->cur_func->in_function_body) @@ -25550,9 +24577,9 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) undefined) */ emit_op(s, OP_drop); emit_op(s, OP_undefined); - + emit_op(s, OP_undefined); /* initial value */ - + emit_label(s, label_loop); emit_op(s, OP_iterator_next); if (is_async) @@ -25560,12 +24587,14 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_iterator_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); + emit_ic(s, JS_ATOM_done); label_next = emit_goto(s, OP_if_true, -1); /* end of loop */ emit_label(s, label_yield); if (is_async) { /* OP_async_yield_star takes the value as parameter */ emit_op(s, OP_get_field); emit_atom(s, JS_ATOM_value); + emit_ic(s, JS_ATOM_value); emit_op(s, OP_async_yield_star); } else { /* OP_yield_star takes (value, done) as parameter */ @@ -25575,13 +24604,13 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label_return = emit_goto(s, OP_if_true, -1); emit_op(s, OP_drop); emit_goto(s, OP_goto, label_loop); - + emit_label(s, label_return); emit_op(s, OP_push_i32); emit_u32(s, 2); emit_op(s, OP_strict_eq); label_throw = emit_goto(s, OP_if_true, -1); - + /* return handling */ if (is_async) emit_op(s, OP_await); @@ -25593,17 +24622,19 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_iterator_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); + emit_ic(s, JS_ATOM_done); emit_goto(s, OP_if_false, label_yield); emit_op(s, OP_get_field); emit_atom(s, JS_ATOM_value); - + emit_ic(s, JS_ATOM_value); + emit_label(s, label_return1); emit_op(s, OP_nip); emit_op(s, OP_nip); emit_op(s, OP_nip); emit_return(s, TRUE); - + /* throw handling */ emit_label(s, label_throw); emit_op(s, OP_iterator_call); @@ -25614,6 +24645,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_iterator_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); + emit_ic(s, JS_ATOM_done); emit_goto(s, OP_if_false, label_yield); emit_goto(s, OP_goto, label_next); /* close the iterator and throw a type error exception */ @@ -25628,17 +24660,18 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_throw_error); emit_atom(s, JS_ATOM_NULL); emit_u8(s, JS_THROW_ERROR_ITERATOR_THROW); - + emit_label(s, label_next); emit_op(s, OP_get_field); emit_atom(s, JS_ATOM_value); + emit_ic(s, JS_ATOM_value); emit_op(s, OP_nip); /* keep the value associated with done = true */ emit_op(s, OP_nip); emit_op(s, OP_nip); } else { int label_next; - + if (is_async) emit_op(s, OP_await); emit_op(s, OP_yield); @@ -25647,12 +24680,54 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_label(s, label_next); } return 0; + } else if (s->token.val == '(' && + 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); + } else if (token_is_pseudo_keyword(s, JS_ATOM_async)) { + const uint8_t *source_ptr; + int tok, source_line_num, source_col_num; + JSParsePos pos; + + /* fast test */ + 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) || + (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved && + 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); + } 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) { + 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); } + next: if (s->token.val == TOK_IDENT) { /* name0 is used to check for OP_set_name pattern, not duplicated */ name0 = s->token.u.ident.atom; } - if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC)) + if (js_parse_cond_expr(s, parse_flags)) return -1; op = s->token.val; @@ -25663,37 +24738,51 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) 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 { - 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, -#ifdef CONFIG_BIGNUM - OP_pow, -#endif - OP_pow, - }; - op = assign_opcodes[op - TOK_MUL_ASSIGN]; -#ifdef CONFIG_BIGNUM - if (s->cur_func->js_mode & JS_MODE_MATH) { - if (op == OP_mod) - op = OP_math_mod; - } -#endif - emit_op(s, op); + emit_op(s, op - TOK_MUL_ASSIGN + OP_mul); } 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, @@ -25706,7 +24795,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false, -1); emit_op(s, OP_drop); - + if (js_parse_assign_expr2(s, parse_flags)) { JS_FreeAtom(s->ctx, name); return -1; @@ -25715,7 +24804,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) if (opcode == OP_get_ref_value && name == name0) { set_object_name(s, name); } - + switch(depth_lvalue) { case 1: emit_op(s, OP_insert2); @@ -25735,7 +24824,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH, FALSE); label2 = emit_goto(s, OP_goto, -1); - + emit_label(s, label1); /* remove the lvalue stack entries */ @@ -25798,6 +24887,7 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be, be->label_finally = -1; be->scope_level = fd->scope_level; be->has_iterator = FALSE; + be->is_regular_stmt = FALSE; } static void pop_break_entry(JSFunctionDef *fd) @@ -25824,11 +24914,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 && - (name == JS_ATOM_NULL || top->label_name == name)) { - emit_goto(s, OP_goto, top->label_break); - 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; + } } i = 0; if (top->has_iterator) { @@ -25871,7 +24962,7 @@ static void emit_return(JSParseState *s, BOOL hasval) emit_op(s, OP_await); } } - + top = s->cur_func->top_break; while (top != NULL) { if (top->has_iterator || top->label_finally != -1) { @@ -25892,6 +24983,7 @@ static void emit_return(JSParseState *s, BOOL hasval) emit_op(s, OP_swap); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_return); + emit_ic(s, JS_ATOM_return); /* stack: iter_obj return_func */ emit_op(s, OP_dup); emit_op(s, OP_is_undefined_or_null); @@ -25930,9 +25022,9 @@ static void emit_return(JSParseState *s, BOOL hasval) label_return = -1; } - /* The error should be raised in the caller context, so we use - a specific opcode */ - emit_op(s, OP_scope_get_var_checkthis); + /* XXX: if this is not initialized, should throw the + ReferenceError in the caller realm */ + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); @@ -26085,7 +25177,6 @@ static int is_let(JSParseState *s, int decl_mask) int res = FALSE; if (token_is_pseudo_keyword(s, JS_ATOM_let)) { -#if 1 JSParsePos pos; js_parse_get_pos(s, &pos); for (;;) { @@ -26118,12 +25209,6 @@ static int is_let(JSParseState *s, int decl_mask) if (js_parse_seek_token(s, &pos)) { res = -1; } -#else - int tok = peek_token(s, TRUE); - if (tok == '{' || tok == TOK_IDENT || peek_token(s, FALSE) == '[') { - res = TRUE; - } -#endif } return res; } @@ -26205,8 +25290,7 @@ 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; @@ -26249,7 +25333,8 @@ 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)) { - break_entry.has_iterator = is_for_of = TRUE; + is_for_of = TRUE; + break_entry.has_iterator = TRUE; break_entry.drop_count += 2; if (has_initializer) goto initializer_error; @@ -26257,8 +25342,7 @@ 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->js_mode & JS_MODE_STRICT) || - has_destructuring)) { + (tok != TOK_VAR || fd->is_strict_mode || 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"); @@ -26293,7 +25377,7 @@ 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; @@ -26394,13 +25478,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(s->cur_func, &break_entry, - label_name, label_break, -1, 0); - if (!(s->cur_func->js_mode & JS_MODE_STRICT) && + push_break_entry(fd, &break_entry, label_name, label_break, -1, 0); + fd->top_break->is_regular_stmt = 1; + if (!fd->is_strict_mode && (decl_mask & DECL_MASK_FUNC_WITH_LABEL)) { mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL; } else { @@ -26409,7 +25494,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(s->cur_func); + pop_break_entry(fd); goto done; } } @@ -26480,7 +25565,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->js_mode & JS_MODE_STRICT) + if (s->cur_func->is_strict_mode) mask = 0; else mask = DECL_MASK_FUNC; /* Annex B.3.4 */ @@ -26690,7 +25775,7 @@ 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 (OPTIMIZE && label_test != label_body && label_cont != label_test) { + if (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; @@ -26956,7 +26041,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_label(s, label_finally); if (s->token.val == TOK_FINALLY) { int saved_eval_ret_idx = 0; /* avoid warning */ - + if (next_token(s)) goto fail; /* on the stack: ret_value gosub_ret_value */ @@ -26976,7 +26061,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_u16(s, saved_eval_ret_idx); set_eval_ret_undefined(s); } - + if (js_parse_block(s)) goto fail; @@ -26998,7 +26083,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, goto fail; break; case TOK_WITH: - if (s->cur_func->js_mode & JS_MODE_STRICT) { + if (s->cur_func->is_strict_mode) { js_parse_error(s, "invalid keyword: with"); goto fail; } else { @@ -27059,7 +26144,9 @@ 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.ptr, + s->token.line_num, + s->token.col_num)) goto fail; break; } @@ -27081,7 +26168,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_expect_semi(s)) goto fail; break; - + case TOK_ENUM: case TOK_EXPORT: case TOK_EXTENDS: @@ -27090,6 +26177,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, default: hasexpr: + emit_source_loc(s); if (js_parse_expr(s)) goto fail; if (s->cur_func->eval_ret_idx >= 0) { @@ -27221,7 +26309,7 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, return i; } -static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m, +static JSExportEntry *find_export_entry(JSContext *ctx, const JSModuleDef *m, JSAtom export_name) { JSExportEntry *me; @@ -27289,6 +26377,7 @@ static int add_star_export_entry(JSContext *ctx, JSModuleDef *m, } /* 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) { @@ -27302,6 +26391,7 @@ 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; @@ -27318,6 +26408,7 @@ 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) { @@ -27353,6 +26444,7 @@ static char *js_default_module_normalize_name(JSContext *ctx, { char *filename, *p; const char *r; + int cap; int len; if (name[0] != '.') { @@ -27366,7 +26458,8 @@ static char *js_default_module_normalize_name(JSContext *ctx, else len = 0; - filename = js_malloc(ctx, len + strlen(name) + 1 + 1); + cap = len + strlen(name) + 1 + 1; + filename = js_malloc(ctx, cap); if (!filename) return NULL; memcpy(filename, base_name, len); @@ -27398,8 +26491,8 @@ static char *js_default_module_normalize_name(JSContext *ctx, } } if (filename[0] != '\0') - strcat(filename, "/"); - strcat(filename, r); + js__pstrcat(filename, cap, "/"); + js__pstrcat(filename, cap, r); // printf("normalize: %s %s -> %s\n", base_name, name, filename); return filename; } @@ -27408,7 +26501,7 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) { struct list_head *el; JSModuleDef *m; - + /* first look at the loaded modules */ list_for_each(el, &ctx->loaded_modules) { m = list_entry(el, JSModuleDef, link); @@ -27419,6 +26512,7 @@ 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) @@ -27456,6 +26550,7 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, /* load the module */ if (!rt->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); @@ -27473,7 +26568,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, { const char *base_cname, *cname; JSModuleDef *m; - + base_cname = JS_AtomToCString(ctx, base_module_name); if (!base_cname) return NULL; @@ -27749,7 +26844,7 @@ static __exception int get_exported_names(JSContext *ctx, } /* Unfortunately, the spec gives a different behavior from GetOwnProperty ! */ -static int js_module_ns_has(JSContext *ctx, JSValueConst obj, JSAtom atom) +static int js_module_ns_has(JSContext *ctx, JSValue obj, JSAtom atom) { return (find_own_property1(JS_VALUE_GET_OBJ(obj), atom) != NULL); } @@ -27773,7 +26868,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(ctx, JS_VALUE_GET_STRING(str1), + ret = js_string_compare(JS_VALUE_GET_STRING(str1), JS_VALUE_GET_STRING(str2)); } JS_FreeValue(ctx, str1); @@ -27781,13 +26876,11 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque) return ret; } -static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m); - static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { JSModuleDef *m = opaque; - return js_get_module_ns(ctx, m); + return JS_GetModuleNamespace(ctx, m); } static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) @@ -27857,6 +26950,11 @@ 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); @@ -27893,7 +26991,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; } -static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m) +JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m) { if (JS_IsUndefined(m->module_ns)) { JSValue val; @@ -27902,9 +27000,19 @@ static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; m->module_ns = val; } - return JS_DupValue(ctx, m->module_ns); + return js_dup(m->module_ns); } +#ifdef DUMP_MODULE_RESOLVE +#define module_trace(ctx, ...) \ + do { \ + if (check_dump_flag(ctx->rt, 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) { @@ -27914,7 +27022,7 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) if (m->resolved) return 0; #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, DUMP_MODULE_RESOLVE)) { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("resolving module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } @@ -27990,9 +27098,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; -#ifdef DUMP_MODULE_RESOLVE - printf("local %d: %p\n", i, var_ref); -#endif + + module_trace(ctx, "local %d: %p\n", i, var_ref); + var_refs[i] = var_ref; } } @@ -28011,7 +27119,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) BOOL is_c_module; int i; JSVarRef *var_ref; - + if (m->func_created) return 0; @@ -28035,7 +27143,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) m->func_created = TRUE; /* do it on the dependencies */ - + for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; if (js_create_module_function(ctx, rme->module) < 0) @@ -28043,9 +27151,9 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) } return 0; -} +} + - /* Prepare a module to be executed by resolving all the imported variables. */ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, @@ -28058,14 +27166,14 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, JSObject *p; BOOL is_c_module; JSValue ret_val; - + if (js_check_stack_overflow(ctx->rt, 0)) { JS_ThrowStackOverflow(ctx); return -1; } - + #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, 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)); } @@ -28103,7 +27211,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, DUMP_MODULE_RESOLVE)) { char buf1[ATOM_GET_STR_BUF_SIZE]; printf("instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); } @@ -28126,7 +27234,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, DUMP_MODULE_RESOLVE)) { printf("exported bindings:\n"); for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; @@ -28146,21 +27254,23 @@ 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 DUMP_MODULE_RESOLVE - printf("import var_idx=%d name=", mi->var_idx); - print_atom(ctx, mi->import_name); - printf(": "); + if (check_dump_flag(ctx->rt, 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_) { JSValue val; /* name space import */ - val = js_get_module_ns(ctx, m1); + val = JS_GetModuleNamespace(ctx, m1); if (JS_IsException(val)) goto fail; set_value(ctx, &var_refs[mi->var_idx]->value, val); -#ifdef DUMP_MODULE_RESOLVE - printf("namespace\n"); -#endif + + module_trace(ctx, "namespace\n"); + } else { JSResolveResultEnum ret; JSExportEntry *res_me; @@ -28178,7 +27288,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, JSModuleDef *m2; /* name space import from */ m2 = res_m->req_module_entries[res_me->u.req_module_idx].module; - val = js_get_module_ns(ctx, m2); + val = JS_GetModuleNamespace(ctx, m2); if (JS_IsException(val)) goto fail; var_ref = js_create_module_var(ctx, TRUE); @@ -28188,9 +27298,9 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } set_value(ctx, &var_ref->value, val); var_refs[mi->var_idx] = var_ref; -#ifdef DUMP_MODULE_RESOLVE - printf("namespace from\n"); -#endif + + module_trace(ctx, "namespace from\n"); + } else { var_ref = res_me->u.local.var_ref; if (!var_ref) { @@ -28199,9 +27309,8 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } var_ref->header.ref_count++; var_refs[mi->var_idx] = var_ref; -#ifdef DUMP_MODULE_RESOLVE - printf("local export (var_ref=%p)\n", var_ref); -#endif + + module_trace(ctx, "local export (var_ref=%p)\n", var_ref); } } } @@ -28238,7 +27347,9 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, } #ifdef DUMP_MODULE_RESOLVE - printf("js_inner_module_linking done\n"); + if (check_dump_flag(ctx->rt, DUMP_MODULE_RESOLVE)) { + printf("js_inner_module_linking done\n"); + } #endif return index; fail: @@ -28252,7 +27363,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m) JSModuleDef *stack_top, *m1; #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, 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)); } @@ -28286,8 +27397,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 from the debug info. May need to add a ScriptOrModule - info in JSFunctionBytecode. */ + function. It does not work for eval(). Need to add a + ScriptOrModule info in JSFunctionBytecode */ sf = ctx->rt->current_stack_frame; if (!sf) return JS_ATOM_NULL; @@ -28296,23 +27407,13 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels) if (!sf) return JS_ATOM_NULL; } - 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; - } - } + 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); } JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m) @@ -28331,14 +27432,14 @@ JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; m->meta_obj = obj; } - return JS_DupValue(ctx, obj); + return js_dup(obj); } static JSValue js_import_meta(JSContext *ctx) { JSAtom filename; JSModuleDef *m; - + filename = JS_GetScriptOrModuleName(ctx, 0); if (filename == JS_ATOM_NULL) goto fail; @@ -28366,7 +27467,7 @@ static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val, JSValueConst *resolving_funcs = (JSValueConst *)func_data; JSValueConst error; JSValue ret; - + /* XXX: check if the test is necessary */ if (argc >= 1) error = argv[0]; @@ -28384,9 +27485,9 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val, JSValueConst *resolving_funcs = (JSValueConst *)func_data; JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]); JSValue ret, ns; - + /* return the module namespace */ - ns = js_get_module_ns(ctx, m); + ns = JS_GetModuleNamespace(ctx, m); if (JS_IsException(ns)) { JSValue err = JS_GetException(ctx); js_load_module_rejected(ctx, JS_UNDEFINED, 1, (JSValueConst *)&err, 0, func_data); @@ -28407,11 +27508,11 @@ static void JS_LoadModuleInternal(JSContext *ctx, const char *basename, JSModuleDef *m; JSValue ret, err, func_obj, evaluate_resolving_funcs[2]; JSValueConst func_data[3]; - + m = js_host_resolve_imported_module(ctx, basename, filename); if (!m) goto fail; - + if (js_resolve_module(ctx, m) < 0) { js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED); goto fail; @@ -28450,7 +27551,7 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename, const char *filename) { JSValue promise, resolving_funcs[2]; - + promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; @@ -28462,11 +27563,11 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename, } static JSValue js_dynamic_import_job(JSContext *ctx, - int argc, JSValueConst *argv) + int argc, JSValue *argv) { - JSValueConst *resolving_funcs = argv; - JSValueConst basename_val = argv[2]; - JSValueConst specifier = argv[3]; + JSValue *resolving_funcs = argv; + JSValue basename_val = argv[2]; + JSValue specifier = argv[3]; const char *basename = NULL, *filename; JSValue ret, err; @@ -28481,7 +27582,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, filename = JS_ToCString(ctx, specifier); if (!filename) goto exception; - + JS_LoadModuleInternal(ctx, basename, filename, resolving_funcs); JS_FreeCString(ctx, filename); @@ -28490,18 +27591,18 @@ static JSValue js_dynamic_import_job(JSContext *ctx, exception: err = JS_GetException(ctx); ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, - 1, (JSValueConst *)&err); + 1, &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, JSValue specifier) { JSAtom basename; JSValue promise, resolving_funcs[2], basename_val; - JSValueConst args[4]; + JSValue args[4]; basename = JS_GetScriptOrModuleName(ctx, 0); if (basename == JS_ATOM_NULL) @@ -28511,7 +27612,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) JS_FreeAtom(ctx, basename); if (JS_IsException(basename_val)) return basename_val; - + promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) { JS_FreeValue(ctx, basename_val); @@ -28522,7 +27623,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) args[1] = resolving_funcs[1]; args[2] = basename_val; args[3] = specifier; - + /* cannot run JS_LoadModuleInternal synchronously because it would cause an unexpected recursion in js_evaluate_module() */ JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args); @@ -28614,7 +27715,7 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]); JSValueConst error = argv[0]; int i; - + if (js_check_stack_overflow(ctx->rt, 0)) return JS_ThrowStackOverflow(ctx); @@ -28655,7 +27756,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]); ExecModuleList exec_list_s, *exec_list = &exec_list_s; int i; - + if (module->status == JS_MODULE_STATUS_EVALUATED) { assert(module->eval_has_exception); return JS_UNDEFINED; @@ -28678,7 +27779,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst /* sort by increasing async_evaluation timestamp */ rqsort(exec_list->tab, exec_list->count, sizeof(exec_list->tab[0]), exec_module_list_cmp, NULL); - + for(i = 0; i < exec_list->count; i++) { JSModuleDef *m = exec_list->tab[i]; if (m->status == JS_MODULE_STATUS_EVALUATED) { @@ -28770,9 +27871,9 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m, *pvalue = JS_GetException(ctx); return -1; } - + #ifdef DUMP_MODULE_RESOLVE - { + if (check_dump_flag(ctx->rt, 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)); } @@ -28802,12 +27903,12 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m, /* push 'm' on stack */ m->stack_prev = *pstack_top; *pstack_top = m; - + for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; m1 = rme->module; index = js_inner_module_evaluation(ctx, m1, index, pstack_top, pvalue); - if (index < 0) + if (index < 0) return -1; assert(m1->status == JS_MODULE_STATUS_EVALUATING || m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC || @@ -28969,7 +28070,9 @@ static __exception int js_parse_export(JSParseState *s) 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.ptr, + s->token.line_num, + s->token.col_num, JS_PARSE_EXPORT_NAMED, NULL); } @@ -29079,7 +28182,9 @@ static __exception int js_parse_export(JSParseState *s) 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.ptr, + s->token.line_num, + s->token.col_num, JS_PARSE_EXPORT_DEFAULT, NULL); } else { if (js_parse_assign_expr(s)) @@ -29138,7 +28243,7 @@ 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, m->import_entries_count, - local_name, TRUE, TRUE, FALSE); + local_name, TRUE, TRUE, JS_VAR_NORMAL); if (var_idx < 0) return -1; if (js_resize_array(ctx, (void **)&m->import_entries, @@ -29271,13 +28376,15 @@ static __exception int js_parse_source_element(JSParseState *s) { JSFunctionDef *fd = s->cur_func; int tok; - + if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && 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.ptr, + s->token.line_num, + s->token.col_num)) return -1; } else if (s->token.val == TOK_EXPORT && fd->module) { if (js_parse_export(s)) @@ -29295,11 +28402,14 @@ 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, - const char *filename, int line_num) + const char *filename, + int line_num, + int col_num) { JSFunctionDef *fd; @@ -29315,7 +28425,7 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, fd->parent_cpool_idx = -1; if (parent) { list_add_tail(&fd->link, &parent->child_list); - fd->js_mode = parent->js_mode; + fd->is_strict_mode = parent->is_strict_mode; fd->parent_scope_level = parent->scope_level; } @@ -29347,12 +28457,13 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, fd->filename = JS_NewAtom(ctx, filename); fd->line_num = line_num; + fd->col_num = col_num; js_dbuf_init(ctx, &fd->pc2line); //fd->pc2line_last_line_num = line_num; //fd->pc2line_last_pc = 0; - fd->last_opcode_line_num = line_num; + fd->ic = init_ic(ctx); return fd; } @@ -29363,7 +28474,7 @@ static void free_bytecode_atoms(JSRuntime *rt, int pos, len, op; JSAtom atom; const JSOpCode *oi; - + pos = 0; while (pos < bc_len) { op = bc_buf[pos]; @@ -29371,7 +28482,7 @@ static void free_bytecode_atoms(JSRuntime *rt, oi = &short_opcode_info(op); else oi = &opcode_info[op]; - + len = oi->size; switch(oi->fmt) { case OP_FMT_atom: @@ -29406,7 +28517,11 @@ 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->line_number_slots); + js_free(ctx, fd->source_loc_slots); + + /* free ic */ + if (fd->ic) + free_ic(ctx->rt, fd->ic); for(i = 0; i < fd->cpool_count; i++) { JS_FreeValue(ctx, fd->cpool[i]); @@ -29419,6 +28534,7 @@ 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); } @@ -29452,7 +28568,7 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) #ifdef DUMP_BYTECODE static const char *skip_lines(const char *p, int n) { - while (n-- > 0 && *p) { + while (p && n-- > 0 && *p) { while (*p && *p++ != '\n') continue; } @@ -29462,7 +28578,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) { + if (p && *p) { while (line++ < line1) { p = skip_lines(s = p, 1); printf(";; %.*s", (int)(p - s), s); @@ -29482,13 +28598,17 @@ static void dump_byte_code(JSContext *ctx, int pass, 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) + const LabelSlot *label_slots, JSFunctionBytecode *b, + int start_pos) { const JSOpCode *oi; int pos, pos_next, op, size, idx, addr, line, line1, in_source; uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits)); BOOL use_short_opcodes = (b != NULL); + if (start_pos != 0 || bits == NULL) + goto no_labels; + /* scan for jump targets */ for (pos = 0; pos < len; pos = pos_next) { op = tab[pos]; @@ -29499,7 +28619,6 @@ 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]; @@ -29508,7 +28627,6 @@ 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; @@ -29531,6 +28649,7 @@ static void dump_byte_code(JSContext *ctx, int pass, } } } + no_labels: in_source = 0; if (source) { /* Always print first line: needed if single line */ @@ -29543,8 +28662,9 @@ static void dump_byte_code(JSContext *ctx, int pass, op = tab[pos]; if (source) { if (b) { - line1 = find_line_num(ctx, b, pos) - line_num + 1; - } else if (op == OP_line_num) { + int col1; + line1 = find_line_num(ctx, b, pos, &col1) - line_num + 1; + } else if (op == OP_source_loc) { line1 = get_u32(tab + pos + 1) - line_num + 1; } if (line1 > line) { @@ -29573,8 +28693,8 @@ static void dump_byte_code(JSContext *ctx, int pass, printf("truncated opcode (0x%02x)\n", op); break; } -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 16) - { +#ifdef DUMP_BYTECODE_HEX + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_HEX)) { int i, x, x0; x = x0 = printf("%5d ", pos); for (i = 0; i < size; i++) { @@ -29586,12 +28706,12 @@ static void dump_byte_code(JSContext *ctx, int pass, printf("%*s", x0 + 20 - x, ""); } #endif - if (bits[pos]) { + if (bits && bits[pos]) { printf("%5d: ", pos); } else { printf(" "); } - printf("%s", oi->name); + printf("%-15s", oi->name); /* align opcode arguments */ pos++; switch(oi->fmt) { case OP_FMT_none_int: @@ -29622,47 +28742,42 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_u32: printf(" %u", get_u32(tab + pos)); break; -#if SHORT_OPCODES + case OP_FMT_u32x2: + printf(" %u:%u", get_u32(tab + pos), get_u32(tab + pos + 4)); + break; 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: - addr = get_u32(tab + pos); - goto has_addr1; - has_addr1: - 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); - break; case OP_FMT_label_u16: addr = get_u32(tab + pos); + has_addr1: if (pass == 1) - printf(" %u:%u", addr, label_slots[addr].pos); + printf(" %d:%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)); + 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)); 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(" %u: ", idx); + printf(" %-4u ; ", idx); if (idx < cpool_count) { - JS_DumpValue(ctx, cpool[idx]); + JS_DumpValue(ctx->rt, cpool[idx]); } break; case OP_FMT_atom: @@ -29696,15 +28811,24 @@ static void dump_byte_code(JSContext *ctx, int pass, printf(",%u", get_u16(tab + pos + 8)); break; case OP_FMT_none_loc: - idx = (op - OP_get_loc0) % 4; - goto has_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; case OP_FMT_loc8: idx = get_u8(tab + pos); goto has_loc; case OP_FMT_loc: idx = get_u16(tab + pos); has_loc: - printf(" %d: ", idx); + printf(" %-4d ; ", idx); if (idx < var_count) { print_atom(ctx, vars[idx].var_name); } @@ -29715,7 +28839,7 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_arg: idx = get_u16(tab + pos); has_arg: - printf(" %d: ", idx); + printf(" %-4d ; ", idx); if (idx < arg_count) { print_atom(ctx, args[idx].var_name); } @@ -29726,7 +28850,7 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_var_ref: idx = get_u16(tab + pos); has_var_ref: - printf(" %d: ", idx); + printf(" %-4d ; ", idx); if (idx < closure_var_count) { print_atom(ctx, closure_var[idx].var_name); } @@ -29745,8 +28869,35 @@ static void dump_byte_code(JSContext *ctx, int pass, js_free(ctx, bits); } -static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len, - int line_num) +// 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) +{ + 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; @@ -29755,7 +28906,7 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int if (len <= 0) return; - printf("%5s %5s\n", "PC", "LINE"); + printf("%5s %5s %5s\n", "PC", "LINE", "COLUMN"); p = buf; p_end = buf + len; @@ -29763,21 +28914,18 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int while (p < p_end) { op = *p++; if (op == 0) { - v = unicode_from_utf8(p, p_end - p, &p_next); + v = utf8_decode_len(p, p_end - p, &p_next); if (v < 0) goto fail; pc += v; p = p_next; - v = unicode_from_utf8(p, p_end - p, &p_next); - if (v < 0) { - fail: - printf("invalid pc2line encode pos=%d\n", (int)(p - buf)); - return; - } - if (!(v & 1)) { - v = v >> 1; - } else { + v = utf8_decode_len(p, p_end - p, &p_next); + if (v < 0) + goto fail; + if (v & 1) { v = -(v >> 1) - 1; + } else { + v = v >> 1; } line_num += v; p = p_next; @@ -29786,8 +28934,21 @@ static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int pc += (op / PC2LINE_RANGE); line_num += (op % PC2LINE_RANGE) + PC2LINE_BASE; } - printf("%5d %5d\n", pc, line_num); + v = utf8_decode_len(p, p_end - p, &p_next); + if (v < 0) + goto fail; + if (v & 1) { + v = -(v >> 1) - 1; + } else { + v = v >> 1; + } + 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)); } static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b) @@ -29796,23 +28957,14 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB char atom_buf[ATOM_GET_STR_BUF_SIZE]; const char *str; - if (b->has_debug && b->debug.filename != JS_ATOM_NULL) { - str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->debug.filename); - printf("%s:%d: ", str, b->debug.line_num); + 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); } str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name); printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str); - if (b->js_mode) { - printf(" mode:"); - if (b->js_mode & JS_MODE_STRICT) - printf(" strict"); -#ifdef CONFIG_BIGNUM - if (b->js_mode & JS_MODE_MATH) - printf(" math"); -#endif - printf("\n"); - } + printf(" mode: %s\n", b->is_strict_mode ? "strict" : "sloppy"); if (b->arg_count && b->vardefs) { printf(" args:"); for(i = 0; i < b->arg_count; i++) { @@ -29856,11 +29008,10 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB b->vardefs ? b->vardefs + b->arg_count : NULL, b->var_count, b->closure_var, b->closure_var_count, b->cpool, b->cpool_count, - b->has_debug ? b->debug.source : NULL, - b->has_debug ? b->debug.line_num : -1, NULL, b); -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 32) - if (b->has_debug) - dump_pc2line(ctx, b->debug.pc2line_buf, b->debug.pc2line_len, b->debug.line_num); + b->source, b->line_num, NULL, b, 0); +#ifdef DUMP_BYTECODE_PC2LINE + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_PC2LINE)) + dump_pc2line(ctx, b->pc2line_buf, b->pc2line_len, b->line_num, b->col_num); #endif printf("\n"); } @@ -29876,7 +29027,9 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s, /* the closure variable indexes are currently stored on 16 bits */ if (s->closure_var_count >= JS_MAX_LOCAL_VARS) { - JS_ThrowInternalError(ctx, "too many closure variables"); + // 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); return -1; } @@ -30025,12 +29178,11 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, JSAtom var_name) { int label_pos, end_pos, pos, op; - BOOL is_strict; - is_strict = ((s->js_mode & JS_MODE_STRICT) != 0); + BOOL is_strict_mode = s->is_strict_mode; /* replace the reference get/put with normal variable accesses */ - if (is_strict) { + 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 */ @@ -30052,7 +29204,7 @@ 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) { + if (is_strict_mode) { if (op != OP_nop) { switch(op) { case OP_insert3: @@ -30073,7 +29225,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, if (op == OP_insert3) bc_buf[pos++] = OP_dup; } - if (is_strict) { + if (is_strict_mode) { bc_buf[pos] = OP_put_var_strict; /* XXX: need 1 extra OP_drop if destructuring an array */ } else { @@ -30154,7 +29306,7 @@ static void var_object_test(JSContext *ctx, JSFunctionDef *s, update_label(s, *plabel_done, 1); s->jump_size++; } - + /* return the position of the next opcode */ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, JSAtom var_name, int scope_level, int op, @@ -30277,7 +29429,6 @@ 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: @@ -30303,12 +29454,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, } } else { if (s->vars[var_idx].is_lexical) { - 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); - } + dbuf_putc(bc, OP_get_loc_check); } else { dbuf_putc(bc, OP_get_loc); } @@ -30366,7 +29512,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, is_arg_scope = (idx == ARG_SCOPE_END); if (var_idx >= 0) break; - + if (!is_arg_scope) { var_idx = find_var(ctx, fd, var_name); if (var_idx >= 0) @@ -30410,7 +29556,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, dbuf_put_u16(bc, idx); var_object_test(ctx, s, var_name, op, bc, &label_done, 0); } - + if (fd->is_eval) break; /* it it necessarily the top level function */ } @@ -30613,7 +29759,7 @@ 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 */ - if (is_ref) + if (is_ref) dbuf_putc(bc, OP_get_var_ref); else dbuf_putc(bc, OP_get_loc); @@ -30628,7 +29774,7 @@ static int resolve_scope_private_field1(JSContext *ctx, int idx, var_kind; JSFunctionDef *fd; BOOL is_ref; - + fd = s; is_ref = FALSE; for(;;) { @@ -30667,6 +29813,7 @@ 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; @@ -30815,7 +29962,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) /* in non strict mode, variables are created in the caller's environment object */ - if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) { + if (!s->is_eval && !s->is_strict_mode) { s->var_object_idx = add_var(ctx, s, JS_ATOM__var_); if (s->has_parameter_expressions) { /* an additional variable object is needed for the @@ -30842,7 +29989,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->js_mode & JS_MODE_STRICT)) + if (s->has_parameter_expressions && !s->is_strict_mode) add_arguments_arg(ctx, s); } if (s->is_func_expr && s->func_name != JS_ATOM_NULL) @@ -30960,7 +30107,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, int i, count; JSVarDef *vd; BOOL is_arg_scope; - + count = b->arg_count + b->var_count + b->closure_var_count; s->closure_var = NULL; s->closure_var_count = 0; @@ -31029,7 +30176,8 @@ 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_line_num parameter or -1 */ + int line_num; /* last visited OP_source_loc parameter or -1 */ + int col_num; /* last visited OP_source_loc parameter or -1 */ int op; int idx; int label; @@ -31037,18 +30185,19 @@ typedef struct CodeContext { JSAtom atom; } CodeContext; -#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)) +#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)) static BOOL code_match(CodeContext *s, int pos, ...) { const uint8_t *tab = s->bc_buf; - int op, len, op1, line_num, pos_next; + int op, len, op1, line_num, col_num, pos_next; va_list ap; BOOL ret = FALSE; line_num = -1; + col_num = -1; va_start(ap, pos); for(;;) { @@ -31056,6 +30205,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; break; } @@ -31067,8 +30217,9 @@ static BOOL code_match(CodeContext *s, int pos, ...) pos_next = pos + len; if (pos_next > s->bc_len) goto done; - if (op == OP_line_num) { + if (op == OP_source_loc) { line_num = get_u32(tab + pos + 1); + col_num = get_u32(tab + pos + 5); pos = pos_next; } else { break; @@ -31194,7 +30345,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy visible if there are cyclic module references */ if (s->module) { label_next = new_label_fd(s, -1); - + /* if 'this' is true, initialize the global variables and return */ dbuf_putc(bc, OP_push_this); dbuf_putc(bc, OP_if_false); @@ -31202,7 +30353,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy update_label(s, label_next, 1); s->jump_size++; } - + /* add the global variables (only happens if s->is_global_var is true) */ for(i = 0; i < s->global_var_count; i++) { @@ -31231,7 +30382,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy } if (!has_closure) { int flags; - + flags = 0; if (s->eval_type != JS_EVAL_TYPE_GLOBAL) flags |= JS_PROP_CONFIGURABLE; @@ -31239,11 +30390,11 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy /* global function definitions need a specific handling */ dbuf_putc(bc, OP_fclosure); dbuf_put_u32(bc, hf->cpool_idx); - + dbuf_putc(bc, OP_define_func); dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name)); dbuf_putc(bc, flags); - + goto done_global_var; } else { if (hf->is_lexical) { @@ -31287,7 +30438,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy if (s->module) { dbuf_putc(bc, OP_return_undef); - + dbuf_putc(bc, OP_label); dbuf_put_u32(bc, label_next); s->label_slots[label_next].pos2 = bc->size; @@ -31300,26 +30451,20 @@ 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 pos, int *linep, int *colp) { int op, len, label; for (; pos < bc_len; pos += len) { op = bc_buf[pos]; len = opcode_info[op].size; - if (op == OP_line_num) { + if (op == OP_source_loc) { *linep = get_u32(bc_buf + pos + 1); - } else - if (op == OP_label) { + *colp = get_u32(bc_buf + pos + 5); + } 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? */ @@ -31356,7 +30501,9 @@ static int get_label_pos(JSFunctionDef *s, int label) pos = s->label_slots[label].pos; for (;;) { switch (s->byte_code.buf[pos]) { - case OP_line_num: + case OP_source_loc: + pos += 9; + continue; case OP_label: pos += 5; continue; @@ -31376,7 +30523,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; + int pos, pos_next, bc_len, op, len, i, idx, line_num, col_num; uint8_t *bc_buf; JSAtom var_name; DynBuf bc_out; @@ -31392,7 +30539,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) for(i = 0; i < s->global_var_count; i++) { JSGlobalVar *hf = &s->global_vars[i]; int flags; - + /* check if global variable (XXX: simplify) */ for(idx = 0; idx < s->closure_var_count; idx++) { JSClosureVar *cv = &s->closure_var[idx]; @@ -31414,7 +30561,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) cv->var_name == JS_ATOM__arg_var_) goto next; } - + dbuf_putc(&bc_out, OP_check_define_var); dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name)); flags = 0; @@ -31427,14 +30574,16 @@ 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_line_num: + case OP_source_loc: line_num = get_u32(bc_buf + pos + 1); - s->line_number_size++; + col_num = get_u32(bc_buf + pos + 5); + s->source_loc_size++; goto no_change; case OP_eval: /* convert scope index to adjusted variable index */ @@ -31453,7 +30602,6 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) dbuf_putc(&bc_out, op); dbuf_put_u16(&bc_out, s->scopes[scope].first + 1); break; - case OP_scope_get_var_checkthis: case OP_scope_get_var_undef: case OP_scope_get_var: case OP_scope_put_var: @@ -31496,7 +30644,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; @@ -31510,43 +30658,22 @@ 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: - 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); - } + /* 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) 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; @@ -31560,17 +30687,23 @@ 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); + pos = skip_dead_code(s, bc_buf, bc_len, pos + len, + &line, &col); pos_next = pos; - if (pos < bc_len && line >= 0 && line_num != line) { + if (line < 0 || pos >= bc_len) + break; + if (line_num != line || col_num != col) { line_num = line; - s->line_number_size++; - dbuf_putc(&bc_out, OP_line_num); + col_num = col; + 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; } @@ -31657,34 +30790,37 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) goto no_change; case OP_dup: - 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); - } + /* 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) 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; @@ -31706,7 +30842,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) case OP_get_array_el_opt_chain: /* equivalent to OP_get_array_el */ dbuf_putc(&bc_out, OP_get_array_el); break; - + default: no_change: dbuf_put(&bc_out, bc_buf + pos, len); @@ -31737,39 +30873,52 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) } /* the pc2line table gives a line number for each PC value */ -static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, int line_num) +static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, + int line_num, int col_num) { - if (s->line_number_slots != NULL - && s->line_number_count < s->line_number_size - && pc >= s->line_number_last_pc - && line_num != s->line_number_last) { - s->line_number_slots[s->line_number_count].pc = pc; - s->line_number_slots[s->line_number_count].line_num = line_num; - s->line_number_count++; - s->line_number_last_pc = pc; - s->line_number_last = line_num; - } + 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; } static void compute_pc2line_info(JSFunctionDef *s) { - if (!(s->js_mode & JS_MODE_STRIP) && s->line_number_slots) { + if (s->source_loc_slots) { int last_line_num = s->line_num; + int last_col_num = s->col_num; uint32_t last_pc = 0; int i; js_dbuf_init(s->ctx, &s->pc2line); - for (i = 0; i < s->line_number_count; i++) { - uint32_t pc = s->line_number_slots[i].pc; - int line_num = s->line_number_slots[i].line_num; - int diff_pc, diff_line; + 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; + int diff_pc, diff_line, diff_col; if (line_num < 0) continue; diff_pc = pc - last_pc; + if (diff_pc < 0) + continue; + diff_line = line_num - last_line_num; - if (diff_line == 0 || diff_pc < 0) + diff_col = col_num - last_col_num; + if (diff_line == 0 && diff_col == 0) continue; if (diff_line >= PC2LINE_BASE && @@ -31783,8 +30932,11 @@ static void compute_pc2line_info(JSFunctionDef *s) dbuf_put_leb128(&s->pc2line, diff_pc); 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; } } } @@ -31806,8 +30958,8 @@ 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_line_num) { - pos += 5; + if (op == OP_source_loc) { + pos += 9; continue; } if (op == OP_label) { @@ -31830,7 +30982,7 @@ static BOOL code_has_label(CodeContext *s, int pos, int label) /* 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, int *pline) +static int find_jump_target(JSFunctionDef *s, int label, int *pop) { int i, pos, op; @@ -31840,10 +30992,7 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline) pos = s->label_slots[label].pos2; for (;;) { switch(op = s->byte_code.buf[pos]) { - case OP_line_num: - if (pline) - *pline = get_u32(s->byte_code.buf + pos + 1); - /* fall thru */ + case OP_source_loc: case OP_label: pos += opcode_info[op].size; continue; @@ -31872,7 +31021,6 @@ static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline) 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; @@ -31887,14 +31035,12 @@ 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: @@ -31945,7 +31091,6 @@ 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); } @@ -31953,38 +31098,36 @@ 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; + int pos, pos_next, bc_len, op, op1, len, i, line_num, col_num, patch_offsets; 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; cc.bc_buf = bc_buf = s->byte_code.buf; cc.bc_len = bc_len = s->byte_code.size; js_dbuf_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; } -#endif - /* XXX: Should skip this phase if not generating SHORT_OPCODES */ - if (s->line_number_size && !(s->js_mode & JS_MODE_STRIP)) { - s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size); - if (s->line_number_slots == NULL) + + 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) return -1; s->line_number_last = s->line_num; + s->col_number_last = s->col_num; s->line_number_last_pc = 0; } @@ -32019,7 +31162,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } /* initialize the 'arguments' variable if needed */ if (s->arguments_var_idx >= 0) { - if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) { + if (s->is_strict_mode || !s->has_simple_parameter_list) { dbuf_putc(&bc_out, OP_special_object); dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS); } else { @@ -32054,11 +31197,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) len = opcode_info[op].size; pos_next = pos + len; switch(op) { - case OP_line_num: + case OP_source_loc: /* 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: @@ -32099,12 +31243,14 @@ 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; - add_pc2line_info(s, bc_out.size, line_num); + if (cc.col_num >= 0) col_num = cc.col_num; + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op + 1, argc); - pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, &line_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, + &line_num, &col_num); break; } - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op, argc); break; } @@ -32115,16 +31261,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); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, + &line_num, &col_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, &line1); + label = find_jump_target(s, label, &op1); if (code_has_label(&cc, pos_next, label)) { /* jump to next instruction: remove jump */ update_label(s, label, -1); @@ -32133,11 +31279,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 >= 0) line_num = line1; update_label(s, label, -1); - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); dbuf_putc(&bc_out, op1); - pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, + &line_num, &col_num); break; } /* XXX: should duplicate single instructions followed by goto or return */ @@ -32151,14 +31297,6 @@ 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: @@ -32168,35 +31306,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); - 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)) { + 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; 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; - if (code_has_label(&cc, pos1, label)) { - if (line1 >= 0) line_num = line1; - pos_next = pos1; - update_label(s, label, -1); - label = cc.label; - op ^= OP_if_true ^ OP_if_false; - } + label = cc.label; + op ^= OP_if_true ^ OP_if_false; } } has_label: - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); if (op == OP_goto) { - pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num); + pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, + &line_num, &col_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; @@ -32240,7 +31378,6 @@ 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) { @@ -32262,19 +31399,15 @@ 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]; - if (OPTIMIZE) { - label = find_jump_target(s, label, &op1, NULL); - } + label = find_jump_target(s, label, &op1); assert(label >= 0 && label < s->label_count); ls = &label_slots[label]; - add_pc2line_info(s, bc_out.size, line_num); -#if SHORT_OPCODES + add_pc2line_info(s, bc_out.size, line_num, col_num); 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); @@ -32288,106 +31421,101 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) break; case OP_drop: - 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; - } + /* 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; } goto no_change; case OP_null: -#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; - } + /* 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; } -#endif /* fall thru */ case OP_push_false: case OP_push_true: - 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; - } + 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; } } goto no_change; case OP_push_i32: - 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)) { + /* 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 (cc.line_num >= 0) line_num = cc.line_num; - 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; + 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); } - /* 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); + pos_next = cc.pos; break; } - goto no_change; + /* 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; + } + /* 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; -#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); + add_pc2line_info(s, bc_out.size, line_num, col_num); dbuf_putc(&bc_out, OP_push_const8 + op - OP_push_const); dbuf_putc(&bc_out, idx); break; @@ -32396,122 +31524,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); + add_pc2line_info(s, bc_out.size, line_num, col_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); + add_pc2line_info(s, bc_out.size, line_num, col_num); dbuf_putc(&bc_out, OP_push_empty_string); break; } -#endif } goto no_change; case OP_to_propkey: case OP_to_propkey2: - if (OPTIMIZE) { - /* 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; - } + /* 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; } goto no_change; case OP_undefined: - 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 + /* 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; } goto no_change; case OP_insert2: - if (OPTIMIZE) { - /* 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; - add_pc2line_info(s, bc_out.size, line_num); - dbuf_putc(&bc_out, cc.op); - dbuf_put_u32(&bc_out, cc.atom); - pos_next = cc.pos; - break; - } + /* 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; } 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)) { @@ -32520,7 +31646,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) pos_next = cc.pos; } } - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op1, cc.idx); if (line2 >= 0) line_num = line2; break; @@ -32528,8 +31654,18 @@ 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) @@ -32543,7 +31679,8 @@ 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; - add_pc2line_info(s, bc_out.size, 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 == OP_inc || cc.op == OP_post_inc) ? OP_inc_loc : OP_dec_loc); dbuf_putc(&bc_out, idx); pos_next = cc.pos; @@ -32554,14 +31691,12 @@ 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; - add_pc2line_info(s, bc_out.size, line_num); -#if SHORT_OPCODES + if (cc.col_num >= 0) col_num = cc.col_num; + add_pc2line_info(s, bc_out.size, line_num, col_num); if (cc.atom == JS_ATOM_empty_string) { JS_FreeAtom(ctx, cc.atom); dbuf_putc(&bc_out, OP_push_empty_string); - } else -#endif - { + } else { dbuf_putc(&bc_out, OP_push_atom_value); dbuf_put_u32(&bc_out, cc.atom); } @@ -32575,7 +31710,8 @@ 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; - add_pc2line_info(s, bc_out.size, line_num); + if (cc.col_num >= 0) col_num = cc.col_num; + add_pc2line_info(s, bc_out.size, line_num, col_num); push_short_int(&bc_out, cc.label); dbuf_putc(&bc_out, OP_add_loc); dbuf_putc(&bc_out, idx); @@ -32589,53 +31725,59 @@ 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; - add_pc2line_info(s, bc_out.size, line_num); + if (cc.col_num >= 0) col_num = cc.col_num; + add_pc2line_info(s, bc_out.size, line_num, col_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; } - add_pc2line_info(s, bc_out.size, line_num); + /* 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); put_short_code(&bc_out, op, idx); - break; } - goto no_change; -#if SHORT_OPCODES + break; 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); + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op, idx); - break; } - goto no_change; -#endif + break; 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; - add_pc2line_info(s, bc_out.size, line_num); + if (cc.col_num >= 0) col_num = cc.col_num; + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op + 1, idx); pos_next = cc.pos; break; } - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); put_short_code(&bc_out, op, idx); - break; } - goto no_change; + break; 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 @@ -32645,22 +31787,25 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) 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); + add_pc2line_info(s, bc_out.size, line_num, col_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 (cc.line_num >= 0) line_num = cc.line_num; - add_pc2line_info(s, bc_out.size, 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_dec + (op - OP_post_dec)); dbuf_putc(&bc_out, cc.op); dbuf_put_u32(&bc_out, cc.atom); @@ -32669,7 +31814,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } 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; - add_pc2line_info(s, bc_out.size, 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_dec + (op - OP_post_dec)); dbuf_putc(&bc_out, OP_put_array_el); pos_next = cc.pos; @@ -32678,51 +31824,49 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } goto no_change; -#if SHORT_OPCODES case OP_typeof: - 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; + /* 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; break; } - 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; - } + 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; } } } goto no_change; -#endif default: no_change: - add_pc2line_info(s, bc_out.size, line_num); + add_pc2line_info(s, bc_out.size, line_num, col_num); dbuf_put(&bc_out, bc_buf + pos, len); break; } @@ -32732,91 +31876,90 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) for(i = 0; i < s->label_count; i++) { assert(label_slots[i].first_reloc == NULL); } -#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; + /* 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; + } + continue; + } + 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->line_number_slots); - s->line_number_slots = NULL; + js_free(ctx, s->source_loc_slots); + s->source_loc_slots = NULL; /* set the new byte code */ dbuf_free(&s->byte_code); s->byte_code = bc_out; @@ -32877,7 +32020,7 @@ static __exception int ss_check(JSContext *ctx, StackSizeState *s, /* mark as explored and store the stack size */ s->stack_level_tab[pos] = stack_len; s->catch_pos_tab[pos] = catch_pos; - + /* queue the new PC to explore */ if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]), &s->pc_stack_size, s->pc_stack_len + 1)) @@ -32905,8 +32048,7 @@ 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; @@ -32928,8 +32070,9 @@ static __exception int compute_stack_size(JSContext *ctx, goto fail; } oi = &short_opcode_info(op); -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64) - printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos); +#ifdef DUMP_BYTECODE_STACK + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_STACK)) + 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) { @@ -32940,12 +32083,8 @@ 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 SHORT_OPCODES - if (oi->fmt == OP_FMT_npopx) { - n_pop += op - OP_call0; - } -#endif + } else if (oi->fmt == OP_FMT_npopx) { + n_pop += op - OP_call0; } if (stack_len < n_pop) { @@ -32974,7 +32113,6 @@ 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; @@ -32989,7 +32127,6 @@ 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); @@ -33102,7 +32239,7 @@ 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, FALSE) < 0) + hf->is_lexical, JS_VAR_NORMAL) < 0) return -1; } @@ -33112,6 +32249,7 @@ 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; @@ -33188,14 +32326,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) fd->cpool[cpool_idx] = func_obj; } -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4) - if (!(fd->js_mode & JS_MODE_STRIP)) { +#ifdef DUMP_BYTECODE_PASS1 + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_PASS1)) { 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); + fd->label_slots, NULL, 0); printf("\n"); } #endif @@ -33203,14 +32341,14 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) if (resolve_variables(ctx, fd)) goto fail; -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2) - if (!(fd->js_mode & JS_MODE_STRIP)) { +#ifdef DUMP_BYTECODE_PASS2 + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_PASS2)) { 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); + fd->label_slots, NULL, 0); printf("\n"); } #endif @@ -33221,17 +32359,11 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) if (compute_stack_size(ctx, fd, &stack_size) < 0) goto fail; - if (fd->js_mode & JS_MODE_STRIP) { - function_size = offsetof(JSFunctionBytecode, debug); - } else { - function_size = sizeof(*b); - } + function_size = sizeof(*b); cpool_offset = function_size; function_size += fd->cpool_count * sizeof(*fd->cpool); vardefs_offset = function_size; - if (!(fd->js_mode & JS_MODE_STRIP) || fd->has_eval_call) { - function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs); - } + 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; @@ -33250,29 +32382,17 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->func_name = fd->func_name; if (fd->arg_count + fd->var_count > 0) { - if ((fd->js_mode & JS_MODE_STRIP) && !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); + 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])); - } 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) { @@ -33284,27 +32404,20 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->stack_size = stack_size; - if (fd->js_mode & JS_MODE_STRIP) { - 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; - b->debug.line_num = fd->line_num; + /* 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; - //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); @@ -33318,7 +32431,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->js_mode = fd->js_mode; + b->is_strict_mode = fd->is_strict_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 || @@ -33328,16 +32441,20 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) 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); + b->ic = fd->ic; + fd->ic = NULL; + rebuild_ic(ctx, b->ic); + if (b->ic->count == 0) { + free_ic(ctx->rt, b->ic); + b->ic = NULL; + } add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); - -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1) - if (!(fd->js_mode & JS_MODE_STRIP)) { + +#ifdef DUMP_BYTECODE_FINAL + if (check_dump_flag(ctx->rt, DUMP_BYTECODE_FINAL)) js_dump_function_bytecode(ctx, b); - } #endif if (fd->parent) { @@ -33356,15 +32473,11 @@ 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 free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE); + if (b->ic) + free_ic(rt, b->ic); + if (b->vardefs) { for(i = 0; i < b->arg_count + b->var_count; i++) { JS_FreeAtomRT(rt, b->vardefs[i].var_name); @@ -33381,11 +32494,9 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) JS_FreeContext(b->realm); JS_FreeAtomRT(rt, b->func_name); - 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); - } + JS_FreeAtomRT(rt, b->filename); + js_free_rt(rt, b->pc2line_buf); + js_free_rt(rt, b->source); remove_gc_object(&b->header); if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) { @@ -33475,45 +32586,53 @@ static __exception int js_parse_directives(JSParseState *s) break; if (!strcmp(str, "use strict")) { s->cur_func->has_use_strict = TRUE; - s->cur_func->js_mode |= JS_MODE_STRICT; + s->cur_func->is_strict_mode = TRUE; } -#if !defined(DUMP_BYTECODE) || !(DUMP_BYTECODE & 8) - else if (!strcmp(str, "use strip")) { - s->cur_func->js_mode |= JS_MODE_STRIP; - } -#endif -#ifdef CONFIG_BIGNUM - else if (s->ctx->bignum_ext && !strcmp(str, "use math")) { - s->cur_func->js_mode |= JS_MODE_MATH; - } -#endif } 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; + } +} + static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, JSAtom func_name) { JSAtom name; int i, idx; - if (fd->js_mode & JS_MODE_STRICT) { + if (fd->is_strict_mode) { 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 (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) { + if (js_invalid_strict_name(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 (name == JS_ATOM_eval || name == JS_ATOM_arguments) { + if (js_invalid_strict_name(name)) { return js_parse_error(s, "invalid argument name in strict code"); } } } /* check async_generator case */ - if ((fd->js_mode & JS_MODE_STRICT) + if (fd->is_strict_mode || !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 @@ -33538,22 +32657,22 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, return 0; duplicate: - return js_parse_error(s, "duplicate argument names not allowed in this context"); + return js_parse_error(s, "Duplicate parameter name not allowed in this context"); } /* create a function to initialize class fields */ 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); + s->filename, 0, 0); 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; @@ -33561,7 +32680,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) fd->super_call_allowed = FALSE; fd->super_allowed = fd->has_home_object; fd->arguments_allowed = FALSE; - + fd->func_kind = JS_FUNC_NORMAL; fd->func_type = JS_PARSE_FUNC_METHOD; return fd; @@ -33575,6 +32694,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, JSAtom func_name, const uint8_t *ptr, int function_line_num, + int function_col_num, JSParseExportEnum export_flag, JSFunctionDef **pfd) { @@ -33619,7 +32739,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } if (s->token.val == TOK_IDENT || - (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) || + (((s->token.val == TOK_YIELD && !fd->is_strict_mode) || (s->token.val == TOK_AWAIT && !s->is_module)) && func_type == JS_PARSE_FUNC_EXPR)) { func_name = JS_DupAtom(ctx, s->token.u.ident.atom); @@ -33650,7 +32770,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } if (func_type == JS_PARSE_FUNC_VAR) { - if (!(fd->js_mode & JS_MODE_STRICT) + if (!fd->is_strict_mode && func_kind == JS_FUNC_NORMAL && 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)) @@ -33688,8 +32808,8 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } - fd = js_new_function_def(ctx, fd, FALSE, is_expr, - s->filename, function_line_num); + fd = js_new_function_def(ctx, fd, FALSE, is_expr, s->filename, + function_line_num, function_col_num); if (!fd) { JS_FreeAtom(ctx, func_name); return -1; @@ -33744,7 +32864,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { emit_class_field_init(s); } - + /* parse arguments */ fd->has_simple_parameter_list = TRUE; fd->has_parameter_expressions = FALSE; @@ -33779,7 +32899,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (push_scope(s) < 0) return -1; } - + while (s->token.val != ')') { JSAtom name; BOOL rest = FALSE; @@ -33820,6 +32940,8 @@ static __exception int js_parse_function_decl2(JSParseState *s, goto fail; } if (fd->has_parameter_expressions) { + if (js_parse_check_duplicate_parameter(s, name)) + goto fail; if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0) goto fail; } @@ -33844,7 +32966,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, has_opt_arg = TRUE; } else if (s->token.val == '=') { int label; - + fd->has_simple_parameter_list = FALSE; has_opt_arg = TRUE; @@ -33927,7 +33049,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } idx = vd->scope_next; } - + /* the argument scope has no parent, hence we don't use pop_scope(s) */ emit_op(s, OP_leave_scope); emit_u16(s, fd->scope_level); @@ -33936,7 +33058,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, fd->scope_level = 0; fd->scope_first = fd->scopes[fd->scope_level].first; } - + if (next_token(s)) goto fail; @@ -33967,23 +33089,22 @@ static __exception int js_parse_function_decl2(JSParseState *s, else emit_op(s, OP_return); - if (!(fd->js_mode & JS_MODE_STRIP)) { - /* 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; - } + /* 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; } } - if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) { + // js_parse_class() already consumed the '{' + if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) if (js_parse_expect(s, '{')) goto fail; - } if (js_parse_directives(s)) goto fail; @@ -33996,13 +33117,12 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (js_parse_source_element(s)) goto fail; } - if (!(fd->js_mode & JS_MODE_STRIP)) { - /* 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; - } + + /* 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 '}' */ @@ -34013,7 +33133,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (js_is_live_code(s)) { emit_return(s, FALSE); } - done: +done: s->cur_func = fd->parent; /* Reparse identifiers after the function is terminated so that @@ -34021,7 +33141,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, by just using next_token() here for normal functions, but it is necessary for arrow functions with an expression body. */ reparse_ident_token(s); - + /* create the function object */ { int idx; @@ -34058,8 +33178,8 @@ static __exception int js_parse_function_decl2(JSParseState *s, /* it is considered as defined at the top level (needed for annex B.3.3.4 and B.3.3.5 checks) */ - hf->scope_level = 0; - hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0); + hf->scope_level = 0; + hf->force_init = s->cur_func->is_strict_mode; /* store directly into global var, bypass lexical scope */ emit_op(s, OP_dup); emit_op(s, OP_scope_put_var); @@ -34137,11 +33257,12 @@ static __exception int js_parse_function_decl(JSParseState *s, JSFunctionKindEnum func_kind, JSAtom func_name, const uint8_t *ptr, - int function_line_num) + int start_line, + int start_col) { return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr, - function_line_num, JS_PARSE_EXPORT_NONE, - NULL); + start_line, start_col, + JS_PARSE_EXPORT_NONE, NULL); } static __exception int js_parse_program(JSParseState *s) @@ -34157,7 +33278,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->js_mode & JS_MODE_STRICT); + !fd->is_strict_mode; if (!s->is_module) { /* hidden variable for the return value */ @@ -34173,9 +33294,21 @@ static __exception int js_parse_program(JSParseState *s) if (!s->is_module) { /* return the value of the hidden variable eval_ret_idx */ - emit_op(s, OP_get_loc); - emit_u16(s, fd->eval_ret_idx); + if (fd->func_kind == JS_FUNC_ASYNC) { + /* wrap the return value in an object so that promises can + be safely returned */ + emit_op(s, OP_object); + emit_op(s, OP_dup); + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + + emit_op(s, OP_put_field); + emit_atom(s, JS_ATOM_value); + } else { + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + } emit_return(s, TRUE); } else { emit_return(s, FALSE); @@ -34192,14 +33325,18 @@ static void js_parse_init(JSContext *ctx, JSParseState *s, s->ctx = ctx; s->filename = filename; s->line_num = 1; - s->buf_ptr = (const uint8_t *)input; + 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; } static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj, - JSValueConst this_obj, + JSValue this_obj, JSVarRef **var_refs, JSStackFrame *sf) { JSValue ret_val; @@ -34236,18 +33373,20 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj) } /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ -static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, +/* `export_name` and `input` may be pure ASCII or UTF-8 encoded */ +static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx) { JSParseState s1, *s = &s1; - int err, js_mode, eval_type; + int err, 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); skip_shebang(&s->buf_ptr, s->buf_end); @@ -34263,16 +33402,12 @@ 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; - js_mode = b->js_mode; + is_strict_mode = b->is_strict_mode; } else { sf = NULL; b = NULL; var_refs = NULL; - js_mode = 0; - if (flags & JS_EVAL_FLAG_STRICT) - js_mode |= JS_MODE_STRICT; - if (flags & JS_EVAL_FLAG_STRIP) - js_mode |= JS_MODE_STRIP; + is_strict_mode = (flags & JS_EVAL_FLAG_STRICT) != 0; if (eval_type == JS_EVAL_TYPE_MODULE) { JSAtom module_name = JS_NewAtom(ctx, filename); if (module_name == JS_ATOM_NULL) @@ -34280,10 +33415,10 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, m = js_new_module_def(ctx, module_name); if (!m) return JS_EXCEPTION; - js_mode |= JS_MODE_STRICT; + is_strict_mode = TRUE; } } - fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1); + fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1, 1); if (!fd) goto fail1; s->cur_func = fd; @@ -34301,7 +33436,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, fd->super_allowed = FALSE; fd->arguments_allowed = TRUE; } - fd->js_mode = js_mode; + fd->is_strict_mode = is_strict_mode; fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_); if (b) { if (add_closure_variables(ctx, fd, b, scope_idx)) @@ -34317,7 +33452,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, push_scope(s); /* body scope */ fd->body_scope = fd->scope_level; - + err = js_parse_program(s); if (err) { fail: @@ -34354,7 +33489,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, } /* the indirection is needed to make 'eval' optional */ -static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, +static JSValue JS_EvalInternal(JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx) { @@ -34365,15 +33500,15 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, flags, scope_idx); } -static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, - JSValueConst val, int flags, int scope_idx) +static JSValue JS_EvalObject(JSContext *ctx, JSValue this_obj, + JSValue val, int flags, int scope_idx) { JSValue ret; const char *str; size_t len; if (!JS_IsString(val)) - return JS_DupValue(ctx, val); + return js_dup(val); str = JS_ToCStringLen(ctx, &len, val); if (!str) return JS_EXCEPTION; @@ -34383,15 +33518,14 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, } -JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj, +JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj, const char *input, size_t input_len, const char *filename, int eval_flags) { - int eval_type = eval_flags & JS_EVAL_TYPE_MASK; JSValue ret; - assert(eval_type == JS_EVAL_TYPE_GLOBAL || - eval_type == JS_EVAL_TYPE_MODULE); + 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, eval_flags, -1); return ret; @@ -34404,7 +33538,7 @@ JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, eval_flags); } -int JS_ResolveModule(JSContext *ctx, JSValueConst obj) +int JS_ResolveModule(JSContext *ctx, JSValue obj) { if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { JSModuleDef *m = JS_VALUE_GET_PTR(obj); @@ -34455,13 +33589,13 @@ static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s, js_free(ctx, s->hash_table); s->hash_table = new_hash_table; s->hash_size = new_hash_size; - + for(i = 0; i < s->hash_size; i++) { s->hash_table[i] = -1; } for(i = 0; i < s->object_count; i++) { e = &s->object_tab[i]; - h = js_object_list_get_hash(e->obj, s->hash_size); + h = js_object_list_get_hash(e->obj, s->hash_size); e->hash_next = s->hash_table[h]; s->hash_table[h] = i; } @@ -34474,7 +33608,7 @@ static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj) { JSObjectListEntry *e; uint32_t h, new_hash_size; - + if (js_resize_array(ctx, (void *)&s->object_tab, sizeof(s->object_tab[0]), &s->object_size, s->object_count + 1)) @@ -34487,7 +33621,7 @@ static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj) return -1; } e = &s->object_tab[s->object_count++]; - h = js_object_list_get_hash(obj, s->hash_size); + h = js_object_list_get_hash(obj, s->hash_size); e->obj = obj; e->hash_next = s->hash_table[h]; s->hash_table[h] = s->object_count - 1; @@ -34503,7 +33637,7 @@ static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj) /* must test empty size because there is no hash table */ if (s->object_count == 0) return -1; - h = js_object_list_get_hash(obj, s->hash_size); + h = js_object_list_get_hash(obj, s->hash_size); p = s->hash_table[h]; while (p != -1) { e = &s->object_tab[p]; @@ -34534,38 +33668,31 @@ typedef enum BCTagEnum { BC_TAG_OBJECT, BC_TAG_ARRAY, BC_TAG_BIG_INT, - BC_TAG_BIG_FLOAT, - BC_TAG_BIG_DECIMAL, BC_TAG_TEMPLATE_OBJECT, BC_TAG_FUNCTION_BYTECODE, BC_TAG_MODULE, 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; -#ifdef CONFIG_BIGNUM -#define BC_BASE_VERSION 2 -#else -#define BC_BASE_VERSION 1 -#endif -#define BC_BE_VERSION 0x40 -#ifdef WORDS_BIGENDIAN -#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION) -#else -#define BC_VERSION BC_BASE_VERSION -#endif +#define BC_VERSION 19 typedef struct BCWriterState { JSContext *ctx; DynBuf dbuf; - BOOL byte_swap : 8; BOOL allow_bytecode : 8; BOOL allow_sab : 8; BOOL allow_reference : 8; + BOOL allow_source : 1; + BOOL allow_debug : 1; uint32_t first_atom; uint32_t *atom_to_idx; int atom_to_idx_size; @@ -34591,18 +33718,20 @@ static const char * const bc_tag_str[] = { "string", "object", "array", - "bigint", - "bigfloat", - "bigdecimal", + "BigInt", "template", "function", "module", "TypedArray", "ArrayBuffer", "SharedArrayBuffer", + "RegExp", "Date", "ObjectValue", "ObjectReference", + "Map", + "Set", + "Symbol", }; #endif @@ -34613,21 +33742,21 @@ static void bc_put_u8(BCWriterState *s, uint8_t v) static void bc_put_u16(BCWriterState *s, uint16_t v) { - if (s->byte_swap) + if (is_be()) v = bswap16(v); dbuf_put_u16(&s->dbuf, v); } static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v) { - if (s->byte_swap) + if (is_be()) v = bswap32(v); dbuf_put_u32(&s->dbuf, v); } static void bc_put_u64(BCWriterState *s, uint64_t v) { - if (s->byte_swap) + if (is_be()) v = bswap64(v); dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v)); } @@ -34763,18 +33892,24 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len) } } -static int JS_WriteFunctionBytecode(BCWriterState *s, - const uint8_t *bc_buf1, int bc_len) +static BOOL is_ic_op(uint8_t op) { - int pos, len, op; + return op >= OP_get_field_ic && op <= OP_put_field_ic; +} + +static int JS_WriteFunctionBytecode(BCWriterState *s, + const JSFunctionBytecode *b) +{ + int pos, len, bc_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, bc_buf1, bc_len); + memcpy(bc_buf, b->byte_code_buf, bc_len); pos = 0; while (pos < bc_len) { @@ -34792,12 +33927,22 @@ static int JS_WriteFunctionBytecode(BCWriterState *s, put_u32(bc_buf + pos + 1, val); break; default: + // IC (inline cache) opcodes should not end up in the serialized + // bytecode; translate them to their non-IC counterparts here + if (is_ic_op(op)) { + val = get_u32(bc_buf + pos + 1); + atom = get_ic_atom(b->ic, val); + if (bc_atom_to_idx(s, &val, atom)) + goto fail; + put_u32(bc_buf + pos + 1, val); + bc_buf[pos] -= (OP_get_field_ic - OP_get_field); + } break; } pos += len; } - if (s->byte_swap) + if (is_be()) bc_byte_swap(bc_buf, bc_len); dbuf_put(&s->dbuf, bc_buf, bc_len); @@ -34821,11 +33966,11 @@ static void JS_WriteString(BCWriterState *s, JSString *p) } } -static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) +static int JS_WriteBigInt(BCWriterState *s, JSValue obj) { uint32_t tag, tag1; int64_t e; - JSBigFloat *bf = JS_VALUE_GET_PTR(obj); + JSBigInt *bf = JS_VALUE_GET_PTR(obj); bf_t *a = &bf->num; size_t len, i, n1, j; limb_t v; @@ -34835,14 +33980,6 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) case JS_TAG_BIG_INT: tag1 = BC_TAG_BIG_INT; break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - tag1 = BC_TAG_BIG_FLOAT; - break; - case JS_TAG_BIG_DECIMAL: - tag1 = BC_TAG_BIG_DECIMAL; - break; -#endif default: abort(); } @@ -34859,113 +33996,56 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) e = a->expn + 3; else e = a->expn; - e = (e << 1) | a->sign; + e = (e * 2) | a->sign; if (e < INT32_MIN || e > INT32_MAX) { - JS_ThrowInternalError(s->ctx, "bignum exponent is too large"); + JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded"); return -1; } bc_put_sleb128(s, e); /* mantissa */ if (a->len != 0) { - if (tag != JS_TAG_BIG_DECIMAL) { - i = 0; - while (i < a->len && a->tab[i] == 0) - i++; - assert(i < a->len); - v = a->tab[i]; - n1 = sizeof(limb_t); - while ((v & 0xff) == 0) { - n1--; - v >>= 8; - } + i = 0; + while (i < a->len && a->tab[i] == 0) i++; - len = (a->len - i) * sizeof(limb_t) + n1; - if (len > INT32_MAX) { - JS_ThrowInternalError(s->ctx, "bignum is too large"); - return -1; - } - bc_put_leb128(s, len); - /* always saved in byte based little endian representation */ - for(j = 0; j < n1; j++) { - dbuf_putc(&s->dbuf, v >> (j * 8)); - } - for(; i < a->len; i++) { - limb_t v = a->tab[i]; + assert(i < a->len); + v = a->tab[i]; + n1 = sizeof(limb_t); + while ((v & 0xff) == 0) { + n1--; + v >>= 8; + } + i++; + len = (a->len - i) * sizeof(limb_t) + n1; + if (len > INT32_MAX) { + JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded"); + return -1; + } + bc_put_leb128(s, len); + /* always saved in byte based little endian representation */ + for(j = 0; j < n1; j++) { + bc_put_u8(s, v >> (j * 8)); + } + for(; i < a->len; i++) { + limb_t v = a->tab[i]; #if LIMB_BITS == 32 -#ifdef WORDS_BIGENDIAN - v = bswap32(v); -#endif - dbuf_put_u32(&s->dbuf, v); + bc_put_u32(s, v); #else -#ifdef WORDS_BIGENDIAN - v = bswap64(v); + bc_put_u64(s, v); #endif - dbuf_put_u64(&s->dbuf, v); -#endif - } - } else { - int bpos, d; - uint8_t v8; - size_t i0; - - /* little endian BCD */ - i = 0; - while (i < a->len && a->tab[i] == 0) - i++; - assert(i < a->len); - len = a->len * LIMB_DIGITS; - v = a->tab[i]; - j = 0; - while ((v % 10) == 0) { - j++; - v /= 10; - } - len -= j; - assert(len > 0); - if (len > INT32_MAX) { - JS_ThrowInternalError(s->ctx, "bignum is too large"); - return -1; - } - bc_put_leb128(s, len); - - bpos = 0; - v8 = 0; - i0 = i; - for(; i < a->len; i++) { - if (i != i0) { - v = a->tab[i]; - j = 0; - } - for(; j < LIMB_DIGITS; j++) { - d = v % 10; - v /= 10; - if (bpos == 0) { - v8 = d; - bpos = 1; - } else { - dbuf_putc(&s->dbuf, v8 | (d << 4)); - bpos = 0; - } - } - } - /* flush the last digit */ - if (bpos) { - dbuf_putc(&s->dbuf, v8); - } } } return 0; } -static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj); +static int JS_WriteObjectRec(BCWriterState *s, JSValue obj); -static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) +static int JS_WriteFunctionTag(BCWriterState *s, JSValue obj) { JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj); uint32_t flags; int idx, i; - + bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE); flags = idx = 0; bc_set_flags(&flags, &idx, b->has_prototype, 1); @@ -34977,14 +34057,13 @@ 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->has_debug, 1); bc_set_flags(&flags, &idx, b->backtrace_barrier, 1); - bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1); + bc_set_flags(&flags, &idx, s->allow_debug, 1); assert(idx <= 16); bc_put_u16(s, flags); - bc_put_u8(s, b->js_mode); + bc_put_u8(s, b->is_strict_mode); bc_put_atom(s, b->func_name); - + bc_put_leb128(s, b->arg_count); bc_put_leb128(s, b->var_count); bc_put_leb128(s, b->defined_arg_count); @@ -35011,7 +34090,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) } else { bc_put_leb128(s, 0); } - + for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; bc_put_atom(s, cv->var_name); @@ -35025,40 +34104,49 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) assert(idx <= 8); bc_put_u8(s, flags); } - - if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len)) - goto fail; - - if (b->has_debug) { - bc_put_atom(s, b->debug.filename); - bc_put_leb128(s, b->debug.line_num); - bc_put_leb128(s, b->debug.pc2line_len); - dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len); - } - + + // 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)) + 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); + } else { + bc_put_leb128(s, 0); + } + } return 0; fail: return -1; } -static int JS_WriteModule(BCWriterState *s, JSValueConst obj) +static int JS_WriteModule(BCWriterState *s, JSValue obj) { JSModuleDef *m = JS_VALUE_GET_PTR(obj); int i; - + bc_put_u8(s, BC_TAG_MODULE); bc_put_atom(s, m->module_name); - + bc_put_leb128(s, m->req_module_entries_count); for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; bc_put_atom(s, rme->module_name); } - + bc_put_leb128(s, m->export_entries_count); for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; @@ -35071,13 +34159,13 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) } bc_put_atom(s, me->export_name); } - + bc_put_leb128(s, m->star_export_entries_count); for(i = 0; i < m->star_export_entries_count; i++) { JSStarExportEntry *se = &m->star_export_entries[i]; bc_put_leb128(s, se->req_module_idx); } - + bc_put_leb128(s, m->import_entries_count); for(i = 0; i < m->import_entries_count; i++) { JSImportEntry *mi = &m->import_entries[i]; @@ -35087,7 +34175,7 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) } bc_put_u8(s, m->has_tla); - + if (JS_WriteObjectRec(s, m->func_obj)) goto fail; return 0; @@ -35095,14 +34183,14 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) return -1; } -static int JS_WriteArray(BCWriterState *s, JSValueConst obj) +static int JS_WriteArray(BCWriterState *s, JSValue obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); uint32_t i, len; JSValue val; int ret; BOOL is_template; - + if (s->allow_bytecode && !p->extensible) { /* not extensible array: we consider it is a template when we are saving bytecode */ @@ -35138,7 +34226,7 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj) return -1; } -static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) +static int JS_WriteObjectTag(BCWriterState *s, JSValue obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); uint32_t i, prop_count; @@ -35155,9 +34243,7 @@ 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 && - JS_AtomIsString(s->ctx, atom) && - (pr->flags & JS_PROP_ENUMERABLE)) { + if (atom != JS_ATOM_NULL && (pr->flags & JS_PROP_ENUMERABLE)) { if (pr->flags & JS_PROP_TMASK) { JS_ThrowTypeError(s->ctx, "only value properties are supported"); goto fail; @@ -35177,7 +34263,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) return -1; } -static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj) +static int JS_WriteTypedArray(BCWriterState *s, JSValue obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); JSTypedArray *ta = p->u.typed_array; @@ -35191,7 +34277,7 @@ static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj) return 0; } -static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj) +static int JS_WriteArrayBuffer(BCWriterState *s, JSValue obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); JSArrayBuffer *abuf = p->u.array_buffer; @@ -35201,17 +34287,19 @@ static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj) } bc_put_u8(s, BC_TAG_ARRAY_BUFFER); bc_put_leb128(s, abuf->byte_length); + bc_put_leb128(s, abuf->max_byte_length); dbuf_put(&s->dbuf, abuf->data, abuf->byte_length); return 0; } -static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj) +static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValue obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); JSArrayBuffer *abuf = p->u.array_buffer; assert(!abuf->detached); /* SharedArrayBuffer are never detached */ bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER); bc_put_leb128(s, abuf->byte_length); + bc_put_leb128(s, abuf->max_byte_length); bc_put_u64(s, (uintptr_t)abuf->data); if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]), &s->sab_tab_size, s->sab_tab_len + 1)) @@ -35221,7 +34309,28 @@ static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj) return 0; } -static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) +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(bc->u.str8, bc->len, /*is_byte_swapped*/FALSE); + + JS_WriteString(s, bc); + + if (is_be()) + lre_byte_swap(bc->u.str8, 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, JSValue obj) { uint32_t tag; @@ -35276,7 +34385,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); int ret, idx; - + if (s->allow_reference) { idx = js_object_list_find(s->ctx, &s->object_list, p); if (idx >= 0) { @@ -35309,6 +34418,10 @@ 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); @@ -35317,13 +34430,17 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) case JS_CLASS_STRING: case JS_CLASS_BOOLEAN: case JS_CLASS_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_CLASS_BIG_FLOAT: - case JS_CLASS_BIG_DECIMAL: -#endif 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 (p->class_id >= JS_CLASS_UINT8C_ARRAY && p->class_id <= JS_CLASS_FLOAT64_ARRAY) { @@ -35340,13 +34457,21 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) } break; case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - case JS_TAG_BIG_DECIMAL: -#endif - if (JS_WriteBigNum(s, 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); @@ -35364,20 +34489,26 @@ static int JS_WriteObjectAtoms(BCWriterState *s) JSRuntime *rt = s->ctx->rt; DynBuf dbuf1; int i, atoms_size; - uint8_t version; dbuf1 = s->dbuf; js_dbuf_init(s->ctx, &s->dbuf); - - version = BC_VERSION; - if (s->byte_swap) - version ^= BC_BE_VERSION; - bc_put_u8(s, version); + bc_put_u8(s, BC_VERSION); bc_put_leb128(s, s->idx_to_atom_count); for(i = 0; i < s->idx_to_atom_count; i++) { - JSAtomStruct *p = rt->atom_array[s->idx_to_atom[i]]; - JS_WriteString(s, p); + 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); + } } /* XXX: should check for OOM in above phase */ @@ -35398,18 +34529,18 @@ static int JS_WriteObjectAtoms(BCWriterState *s) return -1; } -uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, - int flags, uint8_t ***psab_tab, size_t *psab_tab_len) +uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValue obj, + int flags, JSSABTab *psab_tab) { BCWriterState ss, *s = &ss; memset(s, 0, sizeof(*s)); s->ctx = ctx; - /* XXX: byte swapped output is untested */ - s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0); 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; @@ -35417,7 +34548,7 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, s->first_atom = 1; js_dbuf_init(ctx, &s->dbuf); js_object_list_init(&s->object_list); - + if (JS_WriteObjectRec(s, obj)) goto fail; if (JS_WriteObjectAtoms(s)) @@ -35426,10 +34557,12 @@ 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 = s->sab_tab; - if (psab_tab_len) - *psab_tab_len = s->sab_tab_len; + if (psab_tab) { + psab_tab->tab = s->sab_tab; + psab_tab->len = s->sab_tab_len; + } else { + js_free(ctx, s->sab_tab); + } return s->dbuf.buf; fail: js_object_list_end(ctx, &s->object_list); @@ -35437,17 +34570,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 = NULL; - if (psab_tab_len) - *psab_tab_len = 0; + if (psab_tab) { + psab_tab->tab = NULL; + psab_tab->len = 0; + } return NULL; } -uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, +uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValue obj, int flags) { - return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL); + return JS_WriteObject2(ctx, psize, obj, flags, NULL); } typedef struct BCReaderState { @@ -35459,17 +34592,18 @@ typedef struct BCReaderState { int error_state; 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; - -#ifdef DUMP_READ_OBJECT + /* SAB references */ + uint8_t **sab_tab; + int sab_tab_len; + int sab_tab_size; + /* used for DUMP_READ_OBJECT */ const uint8_t *ptr_last; int level; -#endif } BCReaderState; #ifdef DUMP_READ_OBJECT @@ -35477,6 +34611,9 @@ static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s va_list ap; int i, n, n0; + if (!check_dump_flag(s->ctx->rt, DUMP_READ_OBJECT)) + return; + if (!s->ptr_last) s->ptr_last = s->buf_start; @@ -35527,33 +34664,45 @@ static int bc_get_u8(BCReaderState *s, uint8_t *pval) static int bc_get_u16(BCReaderState *s, uint16_t *pval) { + uint16_t v; if (unlikely(s->buf_end - s->ptr < 2)) { *pval = 0; /* avoid warning */ return bc_read_error_end(s); } - *pval = get_u16(s->ptr); + v = get_u16(s->ptr); + if (is_be()) + v = bswap16(v); + *pval = v; s->ptr += 2; return 0; } static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval) { + uint32_t v; if (unlikely(s->buf_end - s->ptr < 4)) { *pval = 0; /* avoid warning */ return bc_read_error_end(s); } - *pval = get_u32(s->ptr); + v = get_u32(s->ptr); + if (is_be()) + v = bswap32(v); + *pval = v; s->ptr += 4; return 0; } static int bc_get_u64(BCReaderState *s, uint64_t *pval) { + uint64_t v; if (unlikely(s->buf_end - s->ptr < 8)) { *pval = 0; /* avoid warning */ return bc_read_error_end(s); } - *pval = get_u64(s->ptr); + v = get_u64(s->ptr); + if (is_be()) + v = bswap64(v); + *pval = v; s->ptr += 8; return 0; } @@ -35595,7 +34744,7 @@ static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval) return 0; } -static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len) +static int bc_get_buf(BCReaderState *s, void *buf, uint32_t buf_len) { if (buf_len != 0) { if (unlikely(!buf || s->buf_end - s->ptr < buf_len)) @@ -35665,11 +34814,21 @@ static JSString *JS_ReadString(BCReaderState *s) } memcpy(p->u.str8, s->ptr, size); s->ptr += size; - if (!is_wide_char) { + if (is_wide_char) { + if (is_be()) { + uint32_t i; + for (i = 0; i < len; i++) + p->u.str16[i] = bswap16(p->u.str16[i]); + } + } else { 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"); + if (check_dump_flag(s->ctx->rt, DUMP_READ_OBJECT)) { + bc_read_trace(s, "%s", ""); // hex dump and indentation + JS_DumpString(s->ctx->rt, p); + printf("\n"); + } #endif return p; } @@ -35691,19 +34850,14 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, JSAtom atom; uint32_t idx; - 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; - } + bc_buf = (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()) + bc_byte_swap(bc_buf, bc_len); + pos = 0; while (pos < bc_len) { op = bc_buf[pos]; @@ -35715,65 +34869,53 @@ 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 (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 + 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); break; default: + assert(!is_ic_op(op)); // should not end up in serialized bytecode break; } +#ifdef DUMP_READ_OBJECT + if (check_dump_flag(s->ctx->rt, 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; } -static JSValue JS_ReadBigNum(BCReaderState *s, int tag) +static JSValue JS_ReadBigInt(BCReaderState *s) { - JSValue obj = JS_UNDEFINED; + JSValue obj; uint8_t v8; int32_t e; uint32_t len; - limb_t l, i, n, j; - JSBigFloat *p; + limb_t l, i, n; limb_t v; bf_t *a; - int bpos, d; - - p = js_new_bf(s->ctx); - if (!p) + + obj = JS_NewBigInt(s->ctx); + if (JS_IsException(obj)) goto fail; - switch(tag) { - case BC_TAG_BIG_INT: - obj = JS_MKPTR(JS_TAG_BIG_INT, p); - break; -#ifdef CONFIG_BIGNUM - case BC_TAG_BIG_FLOAT: - obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p); - break; - case BC_TAG_BIG_DECIMAL: - obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p); - break; -#endif - default: - abort(); - } /* sign + exponent */ if (bc_get_sleb128(s, &e)) goto fail; - a = &p->num; + a = JS_GetBigInt(obj); a->sign = e & 1; e >>= 1; if (e == 0) @@ -35795,77 +34937,38 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) goto fail; bc_read_trace(s, "len=%" PRId64 "\n", (int64_t)len); if (len == 0) { - JS_ThrowInternalError(s->ctx, "invalid bignum length"); + JS_ThrowRangeError(s->ctx, "maximum BigInt size exceeded"); goto fail; } - if (tag != BC_TAG_BIG_DECIMAL) - l = (len + sizeof(limb_t) - 1) / sizeof(limb_t); - else - l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS; + l = (len + sizeof(limb_t) - 1) / sizeof(limb_t); if (bf_resize(a, l)) { JS_ThrowOutOfMemory(s->ctx); goto fail; } - if (tag != BC_TAG_BIG_DECIMAL) { - n = len & (sizeof(limb_t) - 1); - if (n != 0) { - v = 0; - for(i = 0; i < n; i++) { - if (bc_get_u8(s, &v8)) - goto fail; - v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8); - } - a->tab[0] = v; - i = 1; - } else { - i = 0; - } - for(; i < l; i++) { -#if LIMB_BITS == 32 - if (bc_get_u32(s, &v)) + n = len & (sizeof(limb_t) - 1); + if (n != 0) { + v = 0; + for(i = 0; i < n; i++) { + if (bc_get_u8(s, &v8)) goto fail; -#ifdef WORDS_BIGENDIAN - v = bswap32(v); -#endif -#else - if (bc_get_u64(s, &v)) - goto fail; -#ifdef WORDS_BIGENDIAN - v = bswap64(v); -#endif -#endif - a->tab[i] = v; + v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8); } + a->tab[0] = v; + i = 1; } else { - bpos = 0; - for(i = 0; i < l; i++) { - if (i == 0 && (n = len % LIMB_DIGITS) != 0) { - j = LIMB_DIGITS - n; - } else { - j = 0; - } - v = 0; - for(; j < LIMB_DIGITS; j++) { - if (bpos == 0) { - if (bc_get_u8(s, &v8)) - goto fail; - d = v8 & 0xf; - bpos = 1; - } else { - d = v8 >> 4; - bpos = 0; - } - if (d >= 10) { - JS_ThrowInternalError(s->ctx, "invalid digit"); - goto fail; - } - v += mp_pow_dec[j] * d; - } - a->tab[i] = v; - } + i = 0; + } + for(; i < l; i++) { +#if LIMB_BITS == 32 + if (bc_get_u32(s, &v)) + goto fail; +#else + if (bc_get_u64(s, &v)) + goto fail; +#endif + a->tab[i] = v; } } - bc_read_trace(s, "}\n"); return obj; fail: JS_FreeValue(s->ctx, obj); @@ -35886,7 +34989,7 @@ static int BC_add_object_ref1(BCReaderState *s, JSObject *p) return 0; } -static int BC_add_object_ref(BCReaderState *s, JSValueConst obj) +static int BC_add_object_ref(BCReaderState *s, JSValue obj) { return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj)); } @@ -35898,7 +35001,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) JSValue obj = JS_UNDEFINED; uint16_t v16; uint8_t v8; - int idx, i, local_count; + int idx, i, local_count, has_debug_info; int function_size, cpool_offset, byte_code_offset; int closure_var_offset, vardefs_offset; @@ -35918,14 +35021,12 @@ 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.has_debug = bc_get_flags(v16, &idx, 1); bc.backtrace_barrier = 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; + has_debug_info = bc_get_flags(v16, &idx, 1); if (bc_get_u8(s, &v8)) goto fail; - bc.js_mode = v8; - if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure + bc.is_strict_mode = (v8 > 0); + if (bc_get_atom(s, &bc.func_name)) goto fail; if (bc_get_leb128_u16(s, &bc.arg_count)) goto fail; @@ -35944,11 +35045,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) if (bc_get_leb128_int(s, &local_count)) goto fail; - if (bc.has_debug) { - function_size = sizeof(*b); - } else { - function_size = offsetof(JSFunctionBytecode, debug); - } + function_size = sizeof(*b); cpool_offset = function_size; function_size += bc.cpool_count * sizeof(*bc.cpool); vardefs_offset = function_size; @@ -35956,15 +35053,14 @@ 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; - if (!bc.read_only_bytecode) { - function_size += bc.byte_code_len; - } + function_size += bc.byte_code_len; b = js_mallocz(ctx, function_size); if (!b) - return JS_EXCEPTION; - - memcpy(b, &bc, offsetof(JSFunctionBytecode, debug)); + goto fail; + + memcpy(b, &bc, sizeof(*b)); + bc.func_name = JS_ATOM_NULL; b->header.ref_count = 1; if (local_count != 0) { b->vardefs = (void *)((uint8_t*)b + vardefs_offset); @@ -35975,13 +35071,19 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) if (b->cpool_count != 0) { b->cpool = (void *)((uint8_t*)b + cpool_offset); } - + add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); - + obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b); #ifdef DUMP_READ_OBJECT - bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n"); + if (check_dump_flag(s->ctx->rt, DUMP_READ_OBJECT)) { + if (b->func_name) { + 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, @@ -35991,6 +35093,7 @@ 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)) @@ -36008,13 +35111,23 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) vd->is_lexical = bc_get_flags(v8, &idx, 1); vd->is_captured = bc_get_flags(v8, &idx, 1); #ifdef DUMP_READ_OBJECT - bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n"); + if (check_dump_flag(s->ctx->rt, 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"); + } #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; @@ -36032,38 +35145,21 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) cv->is_lexical = bc_get_flags(v8, &idx, 1); cv->var_kind = bc_get_flags(v8, &idx, 4); #ifdef DUMP_READ_OBJECT - bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); + if (check_dump_flag(s->ctx->rt, 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"); + } #endif } 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 (b->has_debug) { - /* read optional debug information */ - bc_read_trace(s, "debug {\n"); - if (bc_get_atom(s, &b->debug.filename)) - goto fail; - if (bc_get_leb128_int(s, &b->debug.line_num)) - goto fail; - if (bc_get_leb128_int(s, &b->debug.pc2line_len)) - goto fail; - 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; - } -#ifdef DUMP_READ_OBJECT - bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); 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++) { @@ -36075,9 +35171,61 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) } 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 DUMP_READ_OBJECT + if (check_dump_flag(s->ctx->rt, 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); + } +#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) + goto fail; + if (bc_get_buf(s, b->pc2line_buf, b->pc2line_len)) + goto fail; + } + 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; + } + 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; } @@ -36090,18 +35238,23 @@ static JSValue JS_ReadModule(BCReaderState *s) JSAtom module_name; int i; uint8_t v8; - + if (bc_get_atom(s, &module_name)) goto fail; #ifdef DUMP_READ_OBJECT - bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n"); + if (check_dump_flag(s->ctx->rt, 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_NewModuleValue(ctx, m); + obj = js_dup(JS_MKPTR(JS_TAG_MODULE, 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); @@ -36195,7 +35348,7 @@ static JSValue JS_ReadObjectTag(BCReaderState *s) JSAtom atom; JSValue val; int ret; - + obj = JS_NewObject(ctx); if (BC_add_object_ref(s, obj)) goto fail; @@ -36205,7 +35358,11 @@ static JSValue JS_ReadObjectTag(BCReaderState *s) if (bc_get_atom(s, &atom)) goto fail; #ifdef DUMP_READ_OBJECT - bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n"); + if (check_dump_flag(s->ctx->rt, DUMP_READ_OBJECT)) { + bc_read_trace(s, "propname: "); + print_atom(s->ctx, atom); + printf("\n"); + } #endif val = JS_ReadObjectRec(s); if (JS_IsException(val)) { @@ -36273,9 +35430,9 @@ static JSValue JS_ReadTypedArray(BCReaderState *s) JSContext *ctx = s->ctx; JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED; uint8_t array_tag; - JSValueConst args[3]; + JSValue args[3]; uint32_t offset, len, idx; - + if (bc_get_u8(s, &array_tag)) return JS_EXCEPTION; if (array_tag >= JS_TYPED_ARRAY_COUNT) @@ -36297,8 +35454,8 @@ static JSValue JS_ReadTypedArray(BCReaderState *s) return JS_EXCEPTION; } args[0] = array_buffer; - args[1] = JS_NewInt64(ctx, offset); - args[2] = JS_NewInt64(ctx, len); + args[1] = js_int64(offset); + args[2] = js_int64(len); obj = js_typed_array_constructor(ctx, JS_UNDEFINED, 3, args, JS_CLASS_UINT8C_ARRAY + array_tag); @@ -36318,16 +35475,31 @@ static JSValue JS_ReadTypedArray(BCReaderState *s) static JSValue JS_ReadArrayBuffer(BCReaderState *s) { JSContext *ctx = s->ctx; - uint32_t byte_length; + uint32_t byte_length, max_byte_length; + uint64_t max_byte_length_u64, *pmax_byte_length = NULL; JSValue obj; - + if (bc_get_leb128(s, &byte_length)) return JS_EXCEPTION; + if (bc_get_leb128(s, &max_byte_length)) + return JS_EXCEPTION; + if (max_byte_length < byte_length) + return JS_ThrowTypeError(ctx, "invalid array buffer"); + if (max_byte_length != UINT32_MAX) { + max_byte_length_u64 = max_byte_length; + pmax_byte_length = &max_byte_length_u64; + } if (unlikely(s->buf_end - s->ptr < byte_length)) { bc_read_error_end(s); return JS_EXCEPTION; } - obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length); + // makes a copy of the input + obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, + byte_length, pmax_byte_length, + JS_CLASS_ARRAY_BUFFER, + (uint8_t*)s->ptr, + js_array_buffer_free, NULL, + /*alloc_flag*/TRUE); if (JS_IsException(obj)) goto fail; if (BC_add_object_ref(s, obj)) @@ -36342,18 +35514,33 @@ static JSValue JS_ReadArrayBuffer(BCReaderState *s) static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) { JSContext *ctx = s->ctx; - uint32_t byte_length; + uint32_t byte_length, max_byte_length; + uint64_t max_byte_length_u64, *pmax_byte_length = NULL; uint8_t *data_ptr; JSValue obj; uint64_t u64; - + if (bc_get_leb128(s, &byte_length)) return JS_EXCEPTION; + if (bc_get_leb128(s, &max_byte_length)) + return JS_EXCEPTION; + if (max_byte_length < byte_length) + return JS_ThrowTypeError(ctx, "invalid array buffer"); + if (max_byte_length != UINT32_MAX) { + max_byte_length_u64 = max_byte_length; + pmax_byte_length = &max_byte_length_u64; + } 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, + obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, + byte_length, pmax_byte_length, JS_CLASS_SHARED_ARRAY_BUFFER, data_ptr, NULL, NULL, FALSE); @@ -36367,6 +35554,36 @@ 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(bc->u.str8, 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; @@ -36414,6 +35631,9 @@ 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; @@ -36437,7 +35657,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) break; case BC_TAG_BOOL_FALSE: case BC_TAG_BOOL_TRUE: - obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE); + obj = js_bool(tag - BC_TAG_BOOL_FALSE); break; case BC_TAG_INT32: { @@ -36445,7 +35665,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_NewInt32(ctx, val); + obj = js_int32(val); } break; case BC_TAG_FLOAT64: @@ -36454,7 +35674,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_NewFloat64(ctx, u.d); + obj = js_float64(u.d); } break; case BC_TAG_STRING: @@ -36468,12 +35688,14 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) break; case BC_TAG_FUNCTION_BYTECODE: if (!s->allow_bytecode) - goto invalid_tag; + goto no_allow_bytecode; obj = JS_ReadFunctionTag(s); break; case BC_TAG_MODULE: - if (!s->allow_bytecode) - goto invalid_tag; + if (!s->allow_bytecode) { + no_allow_bytecode: + return JS_ThrowSyntaxError(ctx, "no bytecode allowed"); + } obj = JS_ReadModule(s); break; case BC_TAG_OBJECT: @@ -36494,6 +35716,9 @@ 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; @@ -36501,11 +35726,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) obj = JS_ReadObjectValue(s); break; case BC_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case BC_TAG_BIG_FLOAT: - case BC_TAG_BIG_DECIMAL: -#endif - obj = JS_ReadBigNum(s, tag); + obj = JS_ReadBigInt(s); break; case BC_TAG_OBJECT_REFERENCE: { @@ -36519,7 +35740,26 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)", val, s->objects_count); } - obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val])); + 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); + } } break; default: @@ -36533,14 +35773,13 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) static int JS_ReadObjectAtoms(BCReaderState *s) { - uint8_t v8; + uint8_t v8, type; JSString *p; int i; JSAtom atom; if (bc_get_u8(s, &v8)) return -1; - /* XXX: could support byte swapped input */ if (v8 != BC_VERSION) { JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)", v8, BC_VERSION); @@ -36548,8 +35787,13 @@ 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, "%d atom indexes {\n", s->idx_to_atom_count); + bc_read_trace(s, "%u 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 * @@ -36558,15 +35802,29 @@ static int JS_ReadObjectAtoms(BCReaderState *s) return s->error_state = -1; } for(i = 0; i < s->idx_to_atom_count; i++) { - p = JS_ReadString(s); - if (!p) + if (bc_get_u8(s, &type)) { return -1; - atom = JS_NewAtomStr(s->ctx, p); + } + 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); + } 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; @@ -36584,8 +35842,8 @@ static void bc_reader_free(BCReaderState *s) js_free(s->ctx, s->objects); } -JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags) +JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags, JSSABTab *psab_tab) { BCReaderState ss, *s = &ss; JSValue obj; @@ -36599,7 +35857,6 @@ JSValue JS_ReadObject(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) @@ -36611,21 +35868,33 @@ JSValue JS_ReadObject(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 */ -static JSValue js_string_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); -static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); -static JSValue js_number_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); +static JSValue js_string_constructor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); +static JSValue js_boolean_constructor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); +static JSValue js_number_constructor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); -static int check_function(JSContext *ctx, JSValueConst obj) +static int check_function(JSContext *ctx, JSValue obj) { if (likely(JS_IsFunction(ctx, obj))) return 0; @@ -36639,6 +35908,7 @@ 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; @@ -36686,7 +35956,7 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, return val; } -static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, +static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValue obj, JSAtom atom, const JSCFunctionListEntry *e) { @@ -36756,13 +36026,13 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, } break; case JS_DEF_PROP_INT32: - val = JS_NewInt32(ctx, e->u.i32); + val = js_int32(e->u.i32); break; case JS_DEF_PROP_INT64: - val = JS_NewInt64(ctx, e->u.i64); + val = js_int64(e->u.i64); break; case JS_DEF_PROP_DOUBLE: - val = __JS_NewFloat64(ctx, e->u.f64); + val = js_float64(e->u.f64); break; case JS_DEF_PROP_UNDEFINED: val = JS_UNDEFINED; @@ -36779,7 +36049,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, return 0; } -void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, +void JS_SetPropertyFunctionList(JSContext *ctx, JSValue obj, const JSCFunctionListEntry *tab, int len) { int i; @@ -36817,16 +36087,17 @@ 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_NewInt32(ctx, e->u.i32); + val = js_int32(e->u.i32); break; case JS_DEF_PROP_INT64: - val = JS_NewInt64(ctx, e->u.i64); + val = js_int64(e->u.i64); break; case JS_DEF_PROP_DOUBLE: - val = __JS_NewFloat64(ctx, e->u.f64); + val = js_float64(e->u.f64); break; case JS_DEF_OBJECT: val = JS_NewObject(ctx); @@ -36843,21 +36114,20 @@ 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, + JSValue func_obj, + JSValue proto, int proto_flags, int ctor_flags) { JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, - JS_DupValue(ctx, proto), proto_flags); + js_dup(proto), proto_flags); JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, - JS_DupValue(ctx, func_obj), - ctor_flags); + js_dup(func_obj), ctor_flags); set_cycle_flag(ctx, func_obj); set_cycle_flag(ctx, proto); } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto) +void JS_SetConstructor(JSContext *ctx, JSValue func_obj, + JSValue proto) { JS_SetConstructor2(ctx, func_obj, proto, 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); @@ -36866,18 +36136,18 @@ void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, static void JS_NewGlobalCConstructor2(JSContext *ctx, JSValue func_obj, const char *name, - JSValueConst proto) + JSValue proto) { JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, - JS_DupValue(ctx, func_obj), + js_dup(func_obj), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); JS_SetConstructor(ctx, func_obj, proto); JS_FreeValue(ctx, func_obj); } -static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name, +static JSValue JS_NewGlobalCConstructor(JSContext *ctx, const char *name, JSCFunction *func, int length, - JSValueConst proto) + JSValue proto) { JSValue func_obj; func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0); @@ -36885,9 +36155,9 @@ static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name, return func_obj; } -static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name, +static JSValue JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name, JSCFunction *func, int length, - JSValueConst proto) + JSValue proto) { JSValue func_obj; func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0); @@ -36895,37 +36165,52 @@ static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *nam return func_obj; } -static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_global_eval(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_EvalObject(ctx, ctx->global_obj, argv[0], JS_EVAL_TYPE_INDIRECT, -1); } -static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_global_isNaN(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { double d; - /* XXX: does this work for bigfloat? */ if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - return JS_NewBool(ctx, isnan(d)); + return js_bool(isnan(d)); } -static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_global_isFinite(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { BOOL res; double d; if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; res = isfinite(d); - return JS_NewBool(ctx, res); + return js_bool(res); +} + +static JSValue js_microtask_job(JSContext *ctx, + int argc, JSValue *argv) +{ + return JS_Call(ctx, argv[0], ctx->global_obj, 0, NULL); +} + +static JSValue js_global_queueMicrotask(JSContext *ctx, JSValue this_val, + int argc, JSValue *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; } /* Object class */ -static JSValue JS_ToObject(JSContext *ctx, JSValueConst val) +static JSValue JS_ToObject(JSContext *ctx, JSValue val) { int tag = JS_VALUE_GET_NORM_TAG(val); JSValue obj; @@ -36934,21 +36219,13 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val) default: case JS_TAG_NULL: case JS_TAG_UNDEFINED: - return JS_ThrowTypeError(ctx, "cannot convert to object"); + return JS_ThrowTypeError(ctx, "Cannot convert undefined or null to object"); case JS_TAG_OBJECT: case JS_TAG_EXCEPTION: - return JS_DupValue(ctx, val); + return js_dup(val); case JS_TAG_BIG_INT: obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT); goto set_value; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: - obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT); - goto set_value; - case JS_TAG_BIG_DECIMAL: - obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_DECIMAL); - goto set_value; -#endif case JS_TAG_INT: case JS_TAG_FLOAT64: obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER); @@ -36958,7 +36235,7 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val) { JSString *p1 = JS_VALUE_GET_STRING(val); obj = JS_NewObjectClass(ctx, JS_CLASS_STRING); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0); + JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0); } goto set_value; case JS_TAG_BOOL: @@ -36968,7 +36245,7 @@ static 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_DupValue(ctx, val)); + JS_SetObjectData(ctx, obj, js_dup(val)); return obj; } } @@ -36981,36 +36258,24 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val) } static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, - JSValueConst desc) + JSValue desc) { JSValue val, getter, setter; + int present; int flags; if (!JS_IsObject(desc)) { - JS_ThrowTypeErrorNotAnObject(ctx); + JS_ThrowTypeError(ctx, "Property description must be an object"); return -1; } flags = 0; val = JS_UNDEFINED; getter = JS_UNDEFINED; setter = JS_UNDEFINED; - if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) { - JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable); - if (JS_IsException(prop)) - goto fail; - flags |= JS_PROP_HAS_CONFIGURABLE; - if (JS_ToBoolFree(ctx, prop)) - flags |= JS_PROP_CONFIGURABLE; - } - if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) { - JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable); - if (JS_IsException(prop)) - goto fail; - flags |= JS_PROP_HAS_WRITABLE; - if (JS_ToBoolFree(ctx, prop)) - flags |= JS_PROP_WRITABLE; - } - if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) { + present = JS_HasProperty(ctx, desc, JS_ATOM_enumerable); + if (present < 0) + goto fail; + if (present) { JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable); if (JS_IsException(prop)) goto fail; @@ -37018,33 +36283,64 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, if (JS_ToBoolFree(ctx, prop)) flags |= JS_PROP_ENUMERABLE; } - if (JS_HasProperty(ctx, desc, JS_ATOM_value)) { + present = JS_HasProperty(ctx, desc, JS_ATOM_configurable); + if (present < 0) + goto fail; + if (present) { + JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable); + if (JS_IsException(prop)) + goto fail; + flags |= JS_PROP_HAS_CONFIGURABLE; + if (JS_ToBoolFree(ctx, prop)) + flags |= JS_PROP_CONFIGURABLE; + } + present = JS_HasProperty(ctx, desc, JS_ATOM_value); + if (present < 0) + goto fail; + if (present) { flags |= JS_PROP_HAS_VALUE; val = JS_GetProperty(ctx, desc, JS_ATOM_value); if (JS_IsException(val)) goto fail; } - if (JS_HasProperty(ctx, desc, JS_ATOM_get)) { + present = JS_HasProperty(ctx, desc, JS_ATOM_writable); + if (present < 0) + goto fail; + if (present) { + JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable); + if (JS_IsException(prop)) + goto fail; + flags |= JS_PROP_HAS_WRITABLE; + if (JS_ToBoolFree(ctx, prop)) + flags |= JS_PROP_WRITABLE; + } + present = JS_HasProperty(ctx, desc, JS_ATOM_get); + if (present < 0) + goto fail; + if (present) { 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, "invalid getter"); + JS_ThrowTypeError(ctx, "Getter must be a function"); goto fail; } } - if (JS_HasProperty(ctx, desc, JS_ATOM_set)) { + present = JS_HasProperty(ctx, desc, JS_ATOM_set); + if (present < 0) + goto fail; + if (present) { 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, "invalid setter"); + JS_ThrowTypeError(ctx, "Setter must be a function"); goto fail; } } if ((flags & (JS_PROP_HAS_SET | JS_PROP_HAS_GET)) && (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE))) { - JS_ThrowTypeError(ctx, "cannot have setter/getter and value or writable"); + JS_ThrowTypeError(ctx, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute"); goto fail; } d->flags = flags; @@ -37059,8 +36355,8 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d, return -1; } -static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValueConst desc, +static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValue obj, + JSAtom prop, JSValue desc, int flags) { JSPropertyDescriptor d; @@ -37076,8 +36372,8 @@ static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj, } static __exception int JS_ObjectDefineProperties(JSContext *ctx, - JSValueConst obj, - JSValueConst properties) + JSValue obj, + JSValue properties) { JSValue props, desc; JSObject *p; @@ -37086,7 +36382,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, int ret = -1; if (!JS_IsObject(obj)) { - JS_ThrowTypeErrorNotAnObject(ctx); + JS_ThrowTypeError(ctx, "Object.defineProperties called on non-object"); return -1; } desc = JS_UNDEFINED; @@ -37096,12 +36392,16 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, p = JS_VALUE_GET_OBJ(props); 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) < 0) + if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, + JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY) < 0) goto exception; } ret = 0; @@ -37113,8 +36413,8 @@ exception: return ret; } -static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_object_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue ret; if (!JS_IsUndefined(new_target) && @@ -37136,15 +36436,15 @@ static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target, return ret; } -static JSValue js_object_create(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_create(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst proto, props; + JSValue proto, props; JSValue obj; proto = argv[0]; if (!JS_IsObject(proto) && !JS_IsNull(proto)) - return JS_ThrowTypeError(ctx, "not a prototype"); + return JS_ThrowTypeError(ctx, "object prototype may only be an Object or null"); obj = JS_NewObjectProto(ctx, proto); if (JS_IsException(obj)) return JS_EXCEPTION; @@ -37158,10 +36458,10 @@ static JSValue js_object_create(JSContext *ctx, JSValueConst this_val, return obj; } -static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { - JSValueConst val; + JSValue val; val = argv[0]; if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) { @@ -37174,21 +36474,21 @@ static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, return JS_GetPrototype(ctx, val); } -static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj; + JSValue obj; obj = argv[0]; if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0) return JS_EXCEPTION; - return JS_DupValue(ctx, obj); + return js_dup(obj); } /* magic = 1 if called as Reflect.defineProperty */ -static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_object_defineProperty(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { - JSValueConst obj, prop, desc; + JSValue obj, prop, desc; int ret, flags; JSAtom atom; @@ -37201,38 +36501,38 @@ 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 = 0; - if (!magic) - flags |= JS_PROP_THROW; + flags = JS_PROP_THROW | JS_PROP_DEFINE_PROPERTY; + if (magic) + flags = JS_PROP_REFLECT_DEFINE_PROPERTY; ret = JS_DefinePropertyDesc(ctx, obj, atom, desc, flags); JS_FreeAtom(ctx, atom); if (ret < 0) { return JS_EXCEPTION; } else if (magic) { - return JS_NewBool(ctx, ret); + return js_bool(ret); } else { - return JS_DupValue(ctx, obj); + return js_dup(obj); } } -static JSValue js_object_defineProperties(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_defineProperties(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // defineProperties(obj, properties) - JSValueConst obj = argv[0]; + JSValue obj = argv[0]; if (JS_ObjectDefineProperties(ctx, obj, argv[1])) return JS_EXCEPTION; else - return JS_DupValue(ctx, obj); + return js_dup(obj); } /* magic = 1 if called as __defineSetter__ */ -static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_object___defineGetter__(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue obj; - JSValueConst prop, value, get, set; + JSValue prop, value, get, set; int ret, flags; JSAtom atom; @@ -37274,10 +36574,10 @@ static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val, } } -static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { - JSValueConst prop; + JSValue prop; JSAtom atom; JSValue ret, obj; JSPropertyDescriptor desc; @@ -37287,7 +36587,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_DupValue(ctx, argv[0]); + obj = js_dup(argv[0]); } else { obj = JS_ToObject(ctx, argv[0]); if (JS_IsException(obj)) @@ -37308,19 +36608,22 @@ 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_DupValue(ctx, desc.getter), flags) < 0 - || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, desc.setter), flags) < 0) + 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) goto exception1; } else { - if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0 + if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(desc.value), flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0) + js_bool(desc.flags & JS_PROP_WRITABLE), + flags) < 0) goto exception1; } if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0), flags) < 0 + js_bool(desc.flags & JS_PROP_ENUMERABLE), + flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - JS_NewBool(ctx, (desc.flags & JS_PROP_CONFIGURABLE) != 0), flags) < 0) + js_bool(desc.flags & JS_PROP_CONFIGURABLE), + flags) < 0) goto exception1; js_free_desc(ctx, &desc); } @@ -37338,8 +36641,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { //getOwnPropertyDescriptors(obj) JSValue obj, r; @@ -37361,7 +36664,7 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst goto exception; for(i = 0; i < len; i++) { JSValue atomValue, desc; - JSValueConst args[2]; + JSValue args[2]; atomValue = JS_AtomToValue(ctx, props[i].atom); if (JS_IsException(atomValue)) @@ -37389,7 +36692,7 @@ exception: return JS_EXCEPTION; } -static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, +static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValue obj1, int flags, int kind) { JSValue obj, r, val, key, value; @@ -37468,31 +36771,121 @@ done: return r; } -static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_GetOwnPropertyNames2(ctx, argv[0], JS_GPN_STRING_MASK, JS_ITERATOR_KIND_KEY); } -static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_GetOwnPropertyNames2(ctx, argv[0], JS_GPN_SYMBOL_MASK, JS_ITERATOR_KIND_KEY); } -static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int kind) +static JSValue js_object_groupBy(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue cb, res, iter, next, groups, k, v, prop; + JSValue args[2]; + int64_t idx; + BOOL 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, &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, JSValue this_val, + int argc, JSValue *argv, int kind) { return JS_GetOwnPropertyNames2(ctx, argv[0], JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind); } -static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int reflect) +static JSValue js_object_isExtensible(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int reflect) { - JSValueConst obj; + JSValue obj; int ret; obj = argv[0]; @@ -37506,13 +36899,13 @@ static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int reflect) +static JSValue js_object_preventExtensions(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int reflect) { - JSValueConst obj; + JSValue obj; int ret; obj = argv[0]; @@ -37520,22 +36913,22 @@ static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val if (reflect) return JS_ThrowTypeErrorNotAnObject(ctx); else - return JS_DupValue(ctx, obj); + return js_dup(obj); } ret = JS_PreventExtensions(ctx, obj); if (ret < 0) return JS_EXCEPTION; if (reflect) { - return JS_NewBool(ctx, ret); + return js_bool(ret); } else { if (!ret) return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); - return JS_DupValue(ctx, obj); + return js_dup(obj); } } -static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj; JSAtom atom; @@ -37557,11 +36950,11 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_hasOwn(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj; JSAtom atom; @@ -37583,17 +36976,17 @@ static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_valueOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_ToObject(ctx, this_val); } -static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, tag; int is_array; @@ -37601,9 +36994,9 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val, JSObject *p; if (JS_IsNull(this_val)) { - tag = JS_NewString(ctx, "Null"); + tag = js_new_string8(ctx, "Null"); } else if (JS_IsUndefined(this_val)) { - tag = JS_NewString(ctx, "Undefined"); + tag = js_new_string8(ctx, "Undefined"); } else { obj = JS_ToObject(ctx, this_val); if (JS_IsException(obj)) @@ -37647,14 +37040,14 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val, return JS_ConcatString3(ctx, "[object ", tag, "]"); } -static JSValue js_object_toLocaleString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_toLocaleString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_Invoke(ctx, this_val, JS_ATOM_toString, 0, NULL); } -static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_assign(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // Object.assign(obj, source1) JSValue obj, s; @@ -37681,17 +37074,23 @@ exception: return JS_EXCEPTION; } -static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int freeze_flag) +static JSValue js_object_seal(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int freeze_flag) { - JSValueConst obj = argv[0]; + JSValue obj = argv[0]; JSObject *p; JSPropertyEnum *props; uint32_t len, i; int flags, desc_flags, res; if (!JS_IsObject(obj)) - return JS_DupValue(ctx, 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"); + } res = JS_PreventExtensions(ctx, obj); if (res < 0) @@ -37699,8 +37098,7 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, if (!res) { return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); } - - 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; @@ -37725,22 +37123,22 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, goto exception; } js_free_prop_enum(ctx, props, len); - return JS_DupValue(ctx, obj); + return js_dup(obj); exception: js_free_prop_enum(ctx, props, len); return JS_EXCEPTION; } -static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_frozen) +static JSValue js_object_isSealed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int is_frozen) { - JSValueConst obj = argv[0]; + JSValue obj = argv[0]; JSObject *p; JSPropertyEnum *props; uint32_t len, i; int flags, res; - + if (!JS_IsObject(obj)) return JS_TRUE; @@ -37769,20 +37167,20 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, if (res < 0) return JS_EXCEPTION; res ^= 1; -done: +done: js_free_prop_enum(ctx, props, len); - return JS_NewBool(ctx, res); + return js_bool(res); exception: js_free_prop_enum(ctx, props, len); return JS_EXCEPTION; } -static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_fromEntries(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, iter, next_method = JS_UNDEFINED; - JSValueConst iterable; + JSValue iterable; BOOL done; /* RequireObjectCoercible() not necessary because it is tested in @@ -37792,14 +37190,14 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, obj = JS_NewObject(ctx); if (JS_IsException(obj)) return obj; - + iter = JS_GetIterator(ctx, iterable, FALSE); if (JS_IsException(iter)) goto fail; next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next_method)) goto fail; - + for(;;) { JSValue key, value, item; item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); @@ -37809,7 +37207,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, item); break; } - + key = JS_UNDEFINED; value = JS_UNDEFINED; if (!JS_IsObject(item)) { @@ -37846,109 +37244,14 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -#if 0 -/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */ -static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_is(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - int ret; - ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]), - JS_DupValue(ctx, argv[2]), - JS_PROP_C_W_E | JS_PROP_THROW); - if (ret < 0) - return JS_EXCEPTION; - else - return JS_NewBool(ctx, ret); + return js_bool(js_same_value(ctx, argv[0], argv[1])); } -static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ToObject(ctx, argv[0]); -} - -static JSValue js_object___toPrimitive(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int hint = HINT_NONE; - - if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT) - hint = JS_VALUE_GET_INT(argv[1]); - - return JS_ToPrimitive(ctx, argv[0], hint); -} -#endif - -/* return an empty string if not an object */ -static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSAtom atom; - JSObject *p; - uint32_t tag; - int class_id; - - tag = JS_VALUE_GET_NORM_TAG(argv[0]); - if (tag == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(argv[0]); - class_id = p->class_id; - if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0])) - class_id = JS_CLASS_BYTECODE_FUNCTION; - atom = ctx->rt->class_array[class_id].class_name; - } else { - atom = JS_ATOM_empty_string; - } - return JS_AtomToString(ctx, atom); -} - -static JSValue js_object_is(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1])); -} - -#if 0 -static JSValue js_object___getObjectData(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_GetObjectData(ctx, argv[0]); -} - -static JSValue js_object___setObjectData(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - if (JS_SetObjectData(ctx, argv[0], JS_DupValue(ctx, argv[1]))) - return JS_EXCEPTION; - return JS_DupValue(ctx, argv[1]); -} - -static JSValue js_object___toPropertyKey(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ToPropertyKey(ctx, argv[0]); -} - -static JSValue js_object___isObject(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, JS_IsObject(argv[0])); -} - -static JSValue js_object___isSameValueZero(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, js_same_value_zero(ctx, argv[0], argv[1])); -} - -static JSValue js_object___isConstructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_NewBool(ctx, JS_IsConstructor(ctx, argv[0])); -} -#endif - -static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, - JSValueConst defaultConstructor) +static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValue obj, + JSValue defaultConstructor) { JSValue ctor, species; @@ -37958,7 +37261,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, if (JS_IsException(ctor)) return ctor; if (JS_IsUndefined(ctor)) - return JS_DupValue(ctx, defaultConstructor); + return js_dup(defaultConstructor); if (!JS_IsObject(ctor)) { JS_FreeValue(ctx, ctor); return JS_ThrowTypeErrorNotAnObject(ctx); @@ -37968,7 +37271,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, if (JS_IsException(species)) return species; if (JS_IsUndefined(species) || JS_IsNull(species)) - return JS_DupValue(ctx, defaultConstructor); + return js_dup(defaultConstructor); if (!JS_IsConstructor(ctx, species)) { JS_FreeValue(ctx, species); return JS_ThrowTypeError(ctx, "not a constructor"); @@ -37976,15 +37279,7 @@ static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj, return species; } -#if 0 -static JSValue js_object___speciesConstructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_SpeciesConstructor(ctx, argv[0], argv[1]); -} -#endif - -static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val) +static JSValue js_object_get___proto__(JSContext *ctx, JSValue this_val) { JSValue val, ret; @@ -37996,8 +37291,8 @@ static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val) return ret; } -static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val, - JSValueConst proto) +static JSValue js_object_set___proto__(JSContext *ctx, JSValue this_val, + JSValue proto) { if (JS_IsUndefined(this_val) || JS_IsNull(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -38009,11 +37304,11 @@ static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, v1; - JSValueConst v; + JSValue v; int res; v = argv[0]; @@ -38022,7 +37317,7 @@ 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_DupValue(ctx, v); + v1 = js_dup(v); for(;;) { v1 = JS_GetPrototypeFree(ctx, v1); if (JS_IsException(v1)) @@ -38041,7 +37336,7 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, v1); JS_FreeValue(ctx, obj); - return JS_NewBool(ctx, res); + return js_bool(res); exception: JS_FreeValue(ctx, v1); @@ -38049,8 +37344,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, res = JS_EXCEPTION; JSAtom prop = JS_ATOM_NULL; @@ -38068,7 +37363,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_ if (has_prop < 0) goto exception; if (has_prop) { - res = JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0); + res = js_bool(desc.flags & JS_PROP_ENUMERABLE); js_free_desc(ctx, &desc); } else { res = JS_FALSE; @@ -38080,8 +37375,8 @@ exception: return res; } -static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int setter) +static JSValue js_object___lookupGetter__(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int setter) { JSValue obj, res = JS_EXCEPTION; JSAtom prop = JS_ATOM_NULL; @@ -38101,7 +37396,7 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, goto exception; if (has_prop) { if (desc.flags & JS_PROP_GETSET) - res = JS_DupValue(ctx, setter ? desc.setter : desc.getter); + res = js_dup(setter ? desc.setter : desc.getter); else res = JS_UNDEFINED; js_free_desc(ctx, &desc); @@ -38133,7 +37428,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_MAGIC_DEF("groupBy", 2, js_object_groupBy, 0 ), + JS_CFUNC_DEF("groupBy", 2, js_object_groupBy ), 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 ), @@ -38147,17 +37442,6 @@ static const JSCFunctionListEntry js_object_funcs[] = { JS_CFUNC_MAGIC_DEF("freeze", 1, js_object_seal, 1 ), JS_CFUNC_MAGIC_DEF("isSealed", 1, js_object_isSealed, 0 ), JS_CFUNC_MAGIC_DEF("isFrozen", 1, js_object_isSealed, 1 ), - JS_CFUNC_DEF("__getClass", 1, js_object___getClass ), - //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ), - //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ), - //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ), - //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ), - //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ), - //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ), - //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ), - //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ), - //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ), - //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ), JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ), JS_CFUNC_DEF("hasOwn", 2, js_object_hasOwn ), }; @@ -38178,15 +37462,15 @@ static const JSCFunctionListEntry js_object_proto_funcs[] = { /* Function class */ -static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_proto(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return JS_UNDEFINED; } /* XXX: add a specific eval mode so that Function("}), ({") is rejected */ -static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv, int magic) +static JSValue js_function_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv, int magic) { JSFunctionKindEnum func_kind = magic; int i, n, ret; @@ -38195,7 +37479,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, string_buffer_init(ctx, b, 0); string_buffer_putc8(b, '('); - + if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) { string_buffer_puts8(b, "async "); } @@ -38239,7 +37523,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, realm = JS_GetFunctionRealm(ctx, new_target); if (!realm) goto fail1; - proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]); + proto = js_dup(realm->class_proto[func_kind_to_class_id[func_kind]]); } ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE); JS_FreeValue(ctx, proto); @@ -38256,7 +37540,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, } static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, - JSValueConst obj) + JSValue obj) { JSValue len_val; len_val = JS_GetProperty(ctx, obj, JS_ATOM_length); @@ -38268,7 +37552,7 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, } static __exception int js_get_length64(JSContext *ctx, int64_t *pres, - JSValueConst obj) + JSValue obj) { JSValue len_val; len_val = JS_GetProperty(ctx, obj, JS_ATOM_length); @@ -38279,6 +37563,11 @@ 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, JSValue 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; @@ -38290,7 +37579,7 @@ static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len) /* XXX: should use ValueArray */ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, - JSValueConst array_arg) + JSValue array_arg) { uint32_t len, i; JSValue *tab, ret; @@ -38303,7 +37592,9 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, if (js_get_length32(ctx, &len, array_arg)) return NULL; if (len > JS_MAX_LOCAL_VARS) { - JS_ThrowInternalError(ctx, "too many arguments"); + // XXX: check for stack overflow? + JS_ThrowRangeError(ctx, "too many arguments in function call (only %d allowed)", + JS_MAX_LOCAL_VARS); return NULL; } /* avoid allocating 0 bytes */ @@ -38315,7 +37606,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_DupValue(ctx, p->u.array.u.values[i]); + tab[i] = js_dup(p->u.array.u.values[i]); } } else { for(i = 0; i < len; i++) { @@ -38333,10 +37624,10 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, /* magic value: 0 = normal apply, 1 = apply for constructor, 2 = Reflect.apply */ -static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_function_apply(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { - JSValueConst this_arg, array_arg; + JSValue this_arg, array_arg; uint32_t len; JSValue *tab, ret; @@ -38352,16 +37643,16 @@ 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, (JSValueConst *)tab); + ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab); } else { - ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab); + ret = JS_Call(ctx, this_val, this_arg, len, tab); } free_arg_list(ctx, tab, len); return ret; } -static JSValue js_function_call(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_call(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { if (argc <= 0) { return JS_Call(ctx, this_val, JS_UNDEFINED, 0, NULL); @@ -38370,8 +37661,8 @@ static JSValue js_function_call(JSContext *ctx, JSValueConst this_val, } } -static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_bind(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSBoundFunction *bf; JSValue func_obj, name1, len_val; @@ -38391,11 +37682,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_DupValue(ctx, this_val); - bf->this_val = JS_DupValue(ctx, argv[0]); + bf->func_obj = js_dup(this_val); + bf->this_val = js_dup(argv[0]); bf->argc = arg_count; for(i = 0; i < arg_count; i++) { - bf->argv[i] = JS_DupValue(ctx, argv[i + 1]); + bf->argv[i] = js_dup(argv[i + 1]); } p->u.bound_function = bf; @@ -38404,7 +37695,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, if (ret < 0) goto exception; if (!ret) { - len_val = JS_NewInt32(ctx, 0); + len_val = js_int32(0); } else { len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length); if (JS_IsException(len_val)) @@ -38416,7 +37707,7 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, len1 = 0; else len1 -= arg_count; - len_val = JS_NewInt32(ctx, len1); + len_val = js_int32(len1); } else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) { double d = JS_VALUE_GET_FLOAT64(len_val); if (isnan(d)) { @@ -38428,10 +37719,10 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, else d -= (double)arg_count; /* also converts -0 to +0 */ } - len_val = JS_NewFloat64(ctx, d); + len_val = js_number(d); } else { JS_FreeValue(ctx, len_val); - len_val = JS_NewInt32(ctx, 0); + len_val = js_int32(0); } } JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, @@ -38455,8 +37746,8 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; JSFunctionKindEnum func_kind = JS_FUNC_NORMAL; @@ -38467,10 +37758,9 @@ 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; - if (b->has_debug && b->debug.source) { - return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len); - } - func_kind = b->func_kind; + /* `b->source` must be pure ASCII or UTF-8 encoded */ + if (b->source) + return JS_NewStringLen(ctx, b->source, b->source_len); } { JSValue name; @@ -38499,15 +37789,15 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, } } -static JSValue js_function_hasInstance(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_function_hasInstance(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int ret; ret = JS_OrdinaryIsInstanceOf(ctx, argv[0], this_val); if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } static const JSCFunctionListEntry js_function_proto_funcs[] = { @@ -38517,18 +37807,21 @@ 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_DEF("lineNumber", js_function_proto_lineNumber, 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)), }; /* Error class */ -static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) +static JSValue iterator_to_array(JSContext *ctx, JSValue items) { JSValue iter, next_method = JS_UNDEFINED; JSValue v, r = JS_UNDEFINED; int64_t k; BOOL done; - + iter = JS_GetIterator(ctx, items, FALSE); if (JS_IsException(iter)) goto exception; @@ -38560,12 +37853,13 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) goto done; } -static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv, int magic) +static JSValue js_error_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv, int magic) { - JSValue obj, msg, proto; - JSValueConst message, options; - int arg_index; + JSValue obj, msg, proto, cause; + JSValue message; + int opts; + BOOL present; if (JS_IsUndefined(new_target)) new_target = JS_GetActiveFunction(ctx); @@ -38574,8 +37868,8 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, return proto; if (!JS_IsObject(proto)) { JSContext *realm; - JSValueConst proto1; - + JSValue proto1; + JS_FreeValue(ctx, proto); realm = JS_GetFunctionRealm(ctx, new_target); if (!realm) @@ -38585,15 +37879,20 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, } else { proto1 = realm->native_error_proto[magic]; } - proto = JS_DupValue(ctx, proto1); + proto = js_dup(proto1); } obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR); JS_FreeValue(ctx, proto); if (JS_IsException(obj)) return obj; - arg_index = (magic == JS_AGGREGATE_ERROR); + if (magic == JS_AGGREGATE_ERROR) { + message = argv[1]; + opts = 2; + } else { + message = argv[0]; + opts = 1; + } - message = argv[arg_index++]; if (!JS_IsUndefined(message)) { msg = JS_ToString(ctx, message); if (unlikely(JS_IsException(msg))) @@ -38602,19 +37901,16 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } - if (arg_index < argc) { - options = argv[arg_index]; - if (JS_IsObject(options)) { - int present = JS_HasProperty(ctx, options, JS_ATOM_cause); - if (present < 0) + 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))) goto exception; - 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); - } + JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } } @@ -38627,15 +37923,15 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, } /* skip the Error() function in the backtrace */ - build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); + build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); return obj; exception: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } -static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_error_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue name, msg; @@ -38669,20 +37965,85 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = { JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; +static JSValue js_error_isError(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + return js_bool(JS_IsError(ctx, argv[0])); +} + +static JSValue js_error_get_stackTraceLimit(JSContext *ctx, JSValue this_val) +{ + JSValue val; + + val = JS_ToObject(ctx, this_val); + if (JS_IsException(val)) + return val; + JS_FreeValue(ctx, val); + return js_int32(ctx->error_stack_trace_limit); +} + +static JSValue js_error_set_stackTraceLimit(JSContext *ctx, JSValue this_val, JSValue value) +{ + if (JS_IsUndefined(this_val) || JS_IsNull(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); + int limit; + if (JS_ToInt32(ctx, &limit, value) < 0) + return JS_EXCEPTION; + ctx->error_stack_trace_limit = limit; + return JS_UNDEFINED; +} + +static JSValue js_error_get_prepareStackTrace(JSContext *ctx, JSValue 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, JSValue this_val, JSValue 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, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue 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; +} + +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 ), +}; + /* AggregateError */ /* used by C code. */ static JSValue js_aggregate_error_constructor(JSContext *ctx, - JSValueConst errors) + JSValue errors) { JSValue obj; - + obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[JS_AGGREGATE_ERROR], JS_CLASS_ERROR); if (JS_IsException(obj)) return obj; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors), + JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, js_dup(errors), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); return obj; } @@ -38690,7 +38051,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx, /* Array */ static int JS_CopySubArray(JSContext *ctx, - JSValueConst obj, int64_t to_pos, + JSValue obj, int64_t to_pos, int64_t from_pos, int64_t count, int dir) { JSObject *p; @@ -38727,14 +38088,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_DupValue(ctx, p->u.array.u.values[from - j])); + js_dup(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_DupValue(ctx, p->u.array.u.values[from + j])); + js_dup(p->u.array.u.values[from + j])); } } i += l; @@ -38742,7 +38103,7 @@ static int JS_CopySubArray(JSContext *ctx, fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val); if (fromPresent < 0) goto exception; - + if (fromPresent) { if (JS_SetPropertyInt64(ctx, obj, to, val) < 0) goto exception; @@ -38759,8 +38120,8 @@ static int JS_CopySubArray(JSContext *ctx, return -1; } -static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_array_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue obj; int i; @@ -38770,13 +38131,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_DupValue(ctx, argv[0]), TRUE)) + if (JS_ToArrayLengthFree(ctx, &len, js_dup(argv[0]), TRUE)) goto fail; - if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(len)) < 0) goto fail; } else { for(i = 0; i < argc; i++) { - if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0) + if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0) goto fail; } } @@ -38786,12 +38147,12 @@ fail: return JS_EXCEPTION; } -static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_from(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // from(items, mapfn = void 0, this_arg = void 0) - JSValueConst items = argv[0], mapfn, this_arg; - JSValueConst args[2]; + JSValue items = argv[0], mapfn, this_arg; + JSValue args[2]; JSValue stack[2]; JSValue iter, r, v, v2, arrayLike; int64_t k, len; @@ -38826,7 +38187,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, r = JS_NewArray(ctx); if (JS_IsException(r)) goto exception; - stack[0] = JS_DupValue(ctx, items); + stack[0] = js_dup(items); if (js_for_of_start(ctx, &stack[1], FALSE)) goto exception; for (k = 0;; k++) { @@ -38837,7 +38198,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, break; if (mapping) { args[0] = v; - args[1] = JS_NewInt32(ctx, k); + args[1] = js_int32(k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -38854,7 +38215,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_NewInt64(ctx, len); + v = js_int64(len); args[0] = v; if (JS_IsConstructor(ctx, this_val)) { r = JS_CallConstructor(ctx, this_val, 1, args); @@ -38870,7 +38231,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, goto exception; if (mapping) { args[0] = v; - args[1] = JS_NewInt32(ctx, k); + args[1] = js_int32(k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -38882,7 +38243,7 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0) + if (JS_SetProperty(ctx, r, JS_ATOM_length, js_uint32(k)) < 0) goto exception; goto done; @@ -38899,27 +38260,27 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val, return r; } -static JSValue js_array_of(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_of(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, args[1]; int i; if (JS_IsConstructor(ctx, this_val)) { - args[0] = JS_NewInt32(ctx, argc); - obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args); + args[0] = js_int32(argc); + obj = JS_CallConstructor(ctx, this_val, 1, 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_DupValue(ctx, argv[i]), + if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(argv[i]), JS_PROP_THROW) < 0) { goto fail; } } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) { + if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_uint32(argc)) < 0) { fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -38927,30 +38288,30 @@ static JSValue js_array_of(JSContext *ctx, JSValueConst this_val, return obj; } -static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_isArray(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int ret; ret = JS_IsArray(ctx, argv[0]); if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } static JSValue js_get_this(JSContext *ctx, - JSValueConst this_val) + JSValue this_val) { - return JS_DupValue(ctx, this_val); + return js_dup(this_val); } -static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj, - JSValueConst len_val) +static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValue obj, + JSValue len_val) { JSValue ctor, ret, species; int res; JSContext *realm; - + res = JS_IsArray(ctx, obj); if (res < 0) return JS_EXCEPTION; @@ -38997,7 +38358,7 @@ static const JSCFunctionListEntry js_array_funcs[] = { JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), }; -static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj) +static int JS_isConcatSpreadable(JSContext *ctx, JSValue obj) { JSValue val; @@ -39011,14 +38372,13 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj) return JS_IsArray(ctx, obj); } -static JSValue js_array_at(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_at(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { 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; @@ -39028,26 +38388,20 @@ 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 { - int present = JS_TryGetPropertyInt64(ctx, obj, idx, &ret); - if (present < 0) - goto exception; - if (!present) - ret = JS_UNDEFINED; + ret = JS_GetPropertyInt64(ctx, obj, idx); } - JS_FreeValue(ctx, obj); - return ret; + exception: JS_FreeValue(ctx, obj); - return JS_EXCEPTION; + return ret; } -static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_with(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, obj, ret, *arrp, *pval; JSObject *p; @@ -39060,6 +38414,11 @@ 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; @@ -39067,28 +38426,32 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, idx = len + idx; if (idx < 0 || idx >= len) { - JS_ThrowRangeError(ctx, "out of bound"); + JS_ThrowRangeError(ctx, "invalid array index: %" PRId64, idx); goto exception; } - arr = js_allocate_fast_array(ctx, len); + arr = JS_NewArray(ctx); 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_DupValue(ctx, arrp[i]); - *pval = JS_DupValue(ctx, argv[1]); + *pval = js_dup(arrp[i]); + *pval = js_dup(argv[1]); for (i++, pval++; i < len; i++, pval++) - *pval = JS_DupValue(ctx, arrp[i]); + *pval = js_dup(arrp[i]); } else { for (; i < idx; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto fill_and_fail; - *pval = JS_DupValue(ctx, argv[1]); + *pval = js_dup(argv[1]); for (i++, pval++; i < len; i++, pval++) { if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { fill_and_fail: @@ -39099,7 +38462,7 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) goto exception; ret = arr; @@ -39111,11 +38474,11 @@ exception: return ret; } -static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_concat(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, arr, val; - JSValueConst e; + JSValue e; int64_t len, k, n; int i, res; @@ -39124,7 +38487,7 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, if (JS_IsException(obj)) goto exception; - arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); + arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); if (JS_IsException(arr)) goto exception; n = 0; @@ -39159,13 +38522,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_DupValue(ctx, e), + if (JS_DefinePropertyValueInt64(ctx, arr, n, js_dup(e), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; n++; } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0) goto exception; JS_FreeValue(ctx, obj); @@ -39184,26 +38547,60 @@ exception: #define special_filter 4 #define special_TA 8 -static int js_typed_array_get_length_internal(JSContext *ctx, JSValueConst obj); +static JSObject *get_typed_array(JSContext *ctx, JSValue this_val) +{ + 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; +} + +// 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, JSValue 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); + JSValue this_val, + int argc, JSValue *argv); -static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int special) +static JSValue js_array_every(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int special) { JSValue obj, val, index_val, res, ret; - JSValueConst args[3]; - JSValueConst func, this_arg; + JSValue args[3]; + JSValue func, this_arg; int64_t len, k, n; int present; ret = JS_UNDEFINED; val = JS_UNDEFINED; if (special & special_TA) { - obj = JS_DupValue(ctx, this_val); - len = js_typed_array_get_length_internal(ctx, obj); + obj = js_dup(this_val); + len = js_typed_array_get_length_unsafe(ctx, obj); if (len < 0) goto exception; } else { @@ -39215,7 +38612,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, this_arg = JS_UNDEFINED; if (argc > 1) this_arg = argv[1]; - + if (check_function(ctx, func)) goto exception; @@ -39230,18 +38627,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_NewInt64(ctx, len)); + ret = JS_ArraySpeciesCreate(ctx, obj, js_int64(len)); if (JS_IsException(ret)) goto exception; break; case special_filter: - ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); + ret = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); if (JS_IsException(ret)) goto exception; break; case special_map | special_TA: args[0] = obj; - args[1] = JS_NewInt32(ctx, len); + args[1] = js_int32(len); ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(ret)) goto exception; @@ -39266,9 +38663,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, goto exception; } if (present) { - index_val = JS_NewInt64(ctx, k); - if (JS_IsException(index_val)) - goto exception; + index_val = js_int64(k); args[0] = val; args[1] = index_val; args[2] = obj; @@ -39297,13 +38692,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_NewInt32(ctx, k), res, JS_PROP_THROW) < 0) + if (JS_SetPropertyValue(ctx, ret, js_int32(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_DupValue(ctx, val), + if (JS_DefinePropertyValueInt64(ctx, ret, n++, js_dup(val), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } @@ -39320,7 +38715,7 @@ done: if (special == (special_filter | special_TA)) { JSValue arr; args[0] = obj; - args[1] = JS_NewInt32(ctx, n); + args[1] = js_int32(n); arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(arr)) goto exception; @@ -39345,20 +38740,20 @@ exception: #define special_reduce 0 #define special_reduceRight 1 -static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int special) +static JSValue js_array_reduce(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int special) { JSValue obj, val, index_val, acc, acc1; - JSValueConst args[4]; - JSValueConst func; + JSValue args[4]; + JSValue func; int64_t len, k, k1; int present; acc = JS_UNDEFINED; val = JS_UNDEFINED; if (special & special_TA) { - obj = JS_DupValue(ctx, this_val); - len = js_typed_array_get_length_internal(ctx, obj); + obj = js_dup(this_val); + len = js_typed_array_get_length_unsafe(ctx, obj); if (len < 0) goto exception; } else { @@ -39373,7 +38768,7 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, k = 0; if (argc > 1) { - acc = JS_DupValue(ctx, argv[1]); + acc = js_dup(argv[1]); } else { for(;;) { if (k >= len) { @@ -39409,9 +38804,7 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, goto exception; } if (present) { - index_val = JS_NewInt64(ctx, k1); - if (JS_IsException(index_val)) - goto exception; + index_val = js_int64(k1); args[0] = acc; args[1] = val; args[2] = index_val; @@ -39436,8 +38829,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_fill(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj; int64_t len, start, end; @@ -39460,8 +38853,7 @@ 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_DupValue(ctx, argv[0])) < 0) + if (JS_SetPropertyInt64(ctx, obj, start, js_dup(argv[0])) < 0) goto exception; start++; } @@ -39472,19 +38864,20 @@ static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_includes(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, val; - int64_t len, n, res; + int64_t len, n; JSValue *arrp; uint32_t count; + int res; obj = JS_ToObject(ctx, this_val); if (js_get_length64(ctx, &len, obj)) goto exception; - res = FALSE; + res = TRUE; if (len > 0) { n = 0; if (argc > 1) { @@ -39493,10 +38886,8 @@ 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_DupValue(ctx, argv[0]), - JS_DupValue(ctx, arrp[n]), + if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), JS_EQ_SAME_VALUE_ZERO)) { - res = TRUE; goto done; } } @@ -39505,27 +38896,27 @@ 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_DupValue(ctx, argv[0]), val, + if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_SAME_VALUE_ZERO)) { - res = TRUE; - break; + goto done; } } } + res = FALSE; done: JS_FreeValue(ctx, obj); - return JS_NewBool(ctx, res); + return js_bool(res); exception: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } -static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_indexOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, val; - int64_t len, n, res; + int64_t len, n; JSValue *arrp; uint32_t count; @@ -39533,7 +38924,6 @@ 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) { @@ -39542,9 +38932,8 @@ 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_DupValue(ctx, argv[0]), - JS_DupValue(ctx, arrp[n]), JS_EQ_STRICT)) { - res = n; + if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), + JS_EQ_STRICT)) { goto done; } } @@ -39554,55 +38943,63 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) { - res = n; - break; + if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { + goto done; } } } } + n = -1; done: JS_FreeValue(ctx, obj); - return JS_NewInt64(ctx, res); + return js_int64(n); exception: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } -static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_lastIndexOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, val; - int64_t len, n, res; - int present; + int64_t len, n; + JSValue *arrp; + uint32_t count; 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; } - /* XXX: should special case fast arrays */ + 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; + } + } + } for (; n >= 0; n--) { - present = JS_TryGetPropertyInt64(ctx, obj, n, &val); + int present = JS_TryGetPropertyInt64(ctx, obj, n, &val); if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) { - res = n; - break; + if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { + goto done; } } } } + n = -1; + done: JS_FreeValue(ctx, obj); - return JS_NewInt64(ctx, res); + return js_int64(n); exception: JS_FreeValue(ctx, obj); @@ -39610,17 +39007,17 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, } enum { - special_find, - special_findIndex, - special_findLast, - special_findLastIndex, + ArrayFind, + ArrayFindIndex, + ArrayFindLast, + ArrayFindLastIndex, }; -static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int mode) +static JSValue js_array_find(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int mode) { - JSValueConst func, this_arg; - JSValueConst args[3]; + JSValue func, this_arg; + JSValue args[3]; JSValue obj, val, index_val, res; int64_t len, k, end; int dir; @@ -39639,21 +39036,18 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, if (argc > 1) this_arg = argv[1]; - if (mode == special_findLast || mode == special_findLastIndex) { + k = 0; + dir = 1; + end = len; + if (mode == ArrayFindLast || mode == ArrayFindLastIndex) { k = len - 1; dir = -1; end = -1; - } else { - k = 0; - dir = 1; - end = len; } // TODO(bnoordhuis) add fast path for fast arrays for(; k != end; k += dir) { - index_val = JS_NewInt64(ctx, k); - if (JS_IsException(index_val)) - goto exception; + index_val = js_int64(k); val = JS_GetPropertyValue(ctx, obj, index_val); if (JS_IsException(val)) goto exception; @@ -39664,7 +39058,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, if (JS_IsException(res)) goto exception; if (JS_ToBoolFree(ctx, res)) { - if (mode == special_findIndex || mode == special_findLastIndex) { + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) { JS_FreeValue(ctx, val); JS_FreeValue(ctx, obj); return index_val; @@ -39678,8 +39072,8 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, index_val); } JS_FreeValue(ctx, obj); - if (mode == special_findIndex || mode == special_findLastIndex) - return JS_NewInt32(ctx, -1); + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) + return js_int32(-1); else return JS_UNDEFINED; @@ -39690,8 +39084,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, method, ret; @@ -39713,8 +39107,8 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_array_join(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int toLocaleString) +static JSValue js_array_join(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int toLocaleString) { JSValue obj, sep = JS_UNDEFINED, el; StringBuffer b_s, *b = &b_s; @@ -39770,8 +39164,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int shift) +static JSValue js_array_pop(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int shift) { JSValue obj, res = JS_UNDEFINED; int64_t len, newLen; @@ -39811,7 +39205,7 @@ static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0) goto exception; JS_FreeValue(ctx, obj); @@ -39823,8 +39217,8 @@ static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int unshift) +static JSValue js_array_push(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int unshift) { JSValue obj; int i; @@ -39845,23 +39239,22 @@ 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_DupValue(ctx, argv[i])) < 0) + if (JS_SetPropertyInt64(ctx, obj, from + i, js_dup(argv[i])) < 0) goto exception; } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(newLen)) < 0) goto exception; JS_FreeValue(ctx, obj); - return JS_NewInt64(ctx, newLen); + return js_int64(newLen); exception: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } -static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_reverse(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, lval, hval; JSValue *arrp; @@ -39933,8 +39326,8 @@ static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val, // leaves holes in sparse arrays intact whereas a.toReversed() replaces them // with undefined, thus in effect creating a dense array. // Does not use Array[@@species], always returns a base Array. -static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_toReversed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, obj, ret, *arrp, *pval; JSObject *p; @@ -39947,18 +39340,26 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - arr = js_allocate_fast_array(ctx, len); + if (len > UINT32_MAX) { + JS_ThrowRangeError(ctx, "invalid array length"); + goto exception; + } + + arr = JS_NewArray(ctx); 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_DupValue(ctx, arrp[i]); + *pval = js_dup(arrp[i]); } else { // Query order is observable; test262 expects descending order. for (; i >= 0; i--, pval++) { @@ -39971,7 +39372,7 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) goto exception; } @@ -39984,8 +39385,8 @@ exception: return ret; } -static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int splice) +static JSValue js_array_slice(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int splice) { JSValue obj, arr, val, len_val; int64_t len, start, k, final, n, count, del_count, new_len; @@ -40005,8 +39406,7 @@ 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 { @@ -40028,7 +39428,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, } count = max_int64(final - start, 0); } - len_val = JS_NewInt64(ctx, count); + len_val = js_int64(count); arr = JS_ArraySpeciesCreate(ctx, obj, len_val); JS_FreeValue(ctx, len_val); if (JS_IsException(arr)) @@ -40045,7 +39445,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_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0) + if (JS_CreateDataPropertyUint32(ctx, arr, n, js_dup(arrp[k]), JS_PROP_THROW) < 0) goto exception; } } @@ -40059,7 +39459,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, goto exception; } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(n)) < 0) goto exception; if (splice) { @@ -40076,10 +39476,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_DupValue(ctx, argv[i + 2])) < 0) + if (JS_SetPropertyInt64(ctx, obj, start + i, js_dup(argv[i + 2])) < 0) goto exception; } - if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, new_len)) < 0) + if (JS_SetProperty(ctx, obj, JS_ATOM_length, js_int64(new_len)) < 0) goto exception; } JS_FreeValue(ctx, obj); @@ -40091,8 +39491,8 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_toSpliced(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, obj, ret, *arrp, *pval, *last; JSObject *p; @@ -40125,12 +39525,17 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, add = argc - 2; newlen = len + add - del; - if (newlen > MAX_SAFE_INTEGER) { - JS_ThrowTypeError(ctx, "invalid array length"); + 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"); + } goto exception; } - arr = js_allocate_fast_array(ctx, newlen); + arr = JS_NewArray(ctx); if (JS_IsException(arr)) goto exception; @@ -40138,22 +39543,26 @@ 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_DupValue(ctx, arrp[i]); + *pval = js_dup(arrp[i]); for (j = 0; j < add; j++, pval++) - *pval = JS_DupValue(ctx, argv[2 + j]); + *pval = js_dup(argv[2 + j]); for (i += del; i < len; i++, pval++) - *pval = JS_DupValue(ctx, arrp[i]); + *pval = js_dup(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_DupValue(ctx, argv[2 + j]); + *pval = js_dup(argv[2 + j]); for (i += del; i < len; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; @@ -40161,7 +39570,7 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, assert(pval == last); - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, newlen)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(newlen)) < 0) goto exception; done: @@ -40177,8 +39586,8 @@ exception: return ret; } -static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_copyWithin(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj; int64_t len, from, to, final, count; @@ -40212,11 +39621,11 @@ static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target, - JSValueConst source, int64_t sourceLen, +static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValue target, + JSValue source, int64_t sourceLen, int64_t targetIndex, int depth, - JSValueConst mapperFunction, - JSValueConst thisArg) + JSValue mapperFunction, + JSValue thisArg) { JSValue element; int64_t sourceIndex, elementLen; @@ -40234,10 +39643,10 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target, if (!present) continue; if (!JS_IsUndefined(mapperFunction)) { - JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source }; + JSValue args[3] = { element, js_int64(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, args[0]); + JS_FreeValue(ctx, args[1]); if (JS_IsException(element)) return -1; } @@ -40274,11 +39683,11 @@ fail: return -1; } -static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int map) +static JSValue js_array_flatten(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int map) { JSValue obj, arr; - JSValueConst mapperFunction, thisArg; + JSValue mapperFunction, thisArg; int64_t sourceLen; int depthNum; @@ -40303,7 +39712,7 @@ static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val, goto exception; } } - arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); + arr = JS_ArraySpeciesCreate(ctx, obj, js_int32(0)); if (JS_IsException(arr)) goto exception; if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum, @@ -40330,13 +39739,13 @@ struct array_sort_context { JSContext *ctx; int exception; int has_method; - JSValueConst method; + JSValue method; }; static int js_array_cmp_generic(const void *a, const void *b, void *opaque) { struct array_sort_context *psc = opaque; JSContext *ctx = psc->ctx; - JSValueConst argv[2]; + JSValue argv[2]; JSValue res; ValueSlot *ap = (ValueSlot *)(void *)a; ValueSlot *bp = (ValueSlot *)(void *)b; @@ -40381,7 +39790,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(ctx, ap->str, bp->str); + cmp = js_string_compare(ap->str, bp->str); } if (cmp != 0) return cmp; @@ -40394,8 +39803,8 @@ exception: return 0; } -static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_sort(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { struct array_sort_context asc = { ctx, 0, 0, argv[0] }; JSValue obj = JS_UNDEFINED; @@ -40484,8 +39893,8 @@ fail: // leaves holes in sparse arrays intact whereas a.toSorted() replaces them // with undefined, thus in effect creating a dense array. // Does not use Array[@@species], always returns a base Array. -static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_array_toSorted(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, obj, ret, *arrp, *pval; JSObject *p; @@ -40503,17 +39912,26 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - arr = js_allocate_fast_array(ctx, len); + if (len > UINT32_MAX) { + JS_ThrowRangeError(ctx, "invalid array length"); + goto exception; + } + + arr = JS_NewArray(ctx); 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_DupValue(ctx, arrp[i]); + *pval = js_dup(arrp[i]); } else { for (; i < len; i++, pval++) { if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { @@ -40524,7 +39942,7 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0) + if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) goto exception; } @@ -40558,7 +39976,7 @@ static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val) } } -static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_array_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -40568,7 +39986,7 @@ static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, } } -static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) +static JSValue js_create_array(JSContext *ctx, int len, JSValue *tab) { JSValue obj; int i; @@ -40577,7 +39995,7 @@ static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) if (JS_IsException(obj)) return JS_EXCEPTION; for(i = 0; i < len; i++) { - if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, tab[i]), 0) < 0) { + if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(tab[i]), 0) < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -40585,8 +40003,8 @@ static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) return obj; } -static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_create_array_iterator(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue enum_obj, arr; JSArrayIteratorData *it; @@ -40613,7 +40031,7 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, it->obj = arr; it->kind = kind; it->idx = 0; - JS_SetOpaque(enum_obj, it); + JS_SetOpaqueInternal(enum_obj, it); return enum_obj; fail1: JS_FreeValue(ctx, enum_obj); @@ -40622,8 +40040,8 @@ static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_array_iterator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic) { JSArrayIteratorData *it; @@ -40639,8 +40057,8 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_OBJ(it->obj); if (p->class_id >= JS_CLASS_UINT8C_ARRAY && p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail1; } len = p->u.array.count; @@ -40662,7 +40080,7 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, it->idx = idx + 1; *pdone = FALSE; if (it->kind == JS_ITERATOR_KIND_KEY) { - return JS_NewUint32(ctx, idx); + return js_uint32(idx); } else { val = JS_GetPropertyUint32(ctx, it->obj, idx); if (JS_IsException(val)) @@ -40670,9 +40088,9 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, if (it->kind == JS_ITERATOR_KIND_VALUE) { return val; } else { - JSValueConst args[2]; + JSValue args[2]; JSValue num; - num = JS_NewUint32(ctx, idx); + num = js_uint32(idx); args[0] = num; args[1] = val; obj = js_create_array(ctx, 2, args); @@ -40683,14 +40101,813 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, } } -static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +typedef struct JSIteratorWrapData { + JSValue wrapped_iter; + JSValue wrapped_next; +} JSIteratorWrapData; + +static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val) { - return JS_DupValue(ctx, this_val); + JSObject *p = JS_VALUE_GET_OBJ(val); + JSIteratorWrapData *it = p->u.iterator_wrap_data; + if (it) { + JS_FreeValueRT(rt, it->wrapped_iter); + JS_FreeValueRT(rt, it->wrapped_next); + js_free_rt(rt, it); + } } +static void js_iterator_wrap_mark(JSRuntime *rt, JSValue val, + JS_MarkFunc *mark_func) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSIteratorWrapData *it = p->u.iterator_wrap_data; + if (it) { + JS_MarkValue(rt, it->wrapped_iter, mark_func); + JS_MarkValue(rt, it->wrapped_next, mark_func); + } +} + +static JSValue js_iterator_wrap_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, + BOOL *pdone, int magic) +{ + JSIteratorWrapData *it; + JSValue method, ret; + 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; + } + 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[] = { + JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_wrap_next, GEN_MAGIC_NEXT ), + JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ), +}; + +static JSValue js_iterator_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) +{ + JSObject *p; + + 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); +} + +static JSValue js_iterator_from(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue obj, method, iter; + JSIteratorWrapData *it; + int ret; + + 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)) + 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); + } else { + iter = JS_GetIterator2(ctx, obj, method); + JS_FreeValue(ctx, method); + if (JS_IsException(iter)) + return JS_EXCEPTION; + } + return iter; +fail: + JS_FreeValue(ctx, method); + JS_FreeValue(ctx, iter); + return JS_EXCEPTION; +} + +static int check_iterator(JSContext *ctx, JSValue obj) +{ + if (!JS_IsObject(obj)) { + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + return 0; +} + +typedef struct JSIteratorHelperData { + JSValue obj; + JSValue next; + JSValue func; // predicate (filter) or mapper (flatMap, map) + JSValue inner; // innerValue (flatMap) + int64_t count; // limit (drop, take) or counter (filter, map, flatMap) + JSIteratorHelperKindEnum kind : 8; + uint8_t executing : 1; + uint8_t done : 1; +} JSIteratorHelperData; + +static JSValue js_create_iterator_helper(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) +{ + JSValue func, obj, method; + int64_t count; + JSIteratorHelperData *it; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + func = JS_UNDEFINED; + count = 0; + + switch(magic) { + case JS_ITERATOR_HELPER_KIND_DROP: + case JS_ITERATOR_HELPER_KIND_TAKE: + { + JSValue v; + double dlimit; + v = JS_ToNumber(ctx, argv[0]); + if (JS_IsException(v)) + return JS_EXCEPTION; + // Check for Infinity. + if (JS_ToFloat64(ctx, &dlimit, v)) { + JS_FreeValue(ctx, v); + return JS_EXCEPTION; + } + if (isnan(dlimit)) { + JS_FreeValue(ctx, v); + goto fail; + } + if (!isfinite(dlimit)) { + JS_FreeValue(ctx, v); + if (dlimit < 0) + goto fail; + else + count = MAX_SAFE_INTEGER; + } else { + v = JS_ToIntegerFree(ctx, v); + if (JS_IsException(v)) + return JS_EXCEPTION; + if (JS_ToInt64Free(ctx, &count, v)) + return JS_EXCEPTION; + } + if (count < 0) { + fail: + return JS_ThrowRangeError(ctx, "must be positive"); + } + } + break; + case JS_ITERATOR_HELPER_KIND_FILTER: + case JS_ITERATOR_HELPER_KIND_FLAT_MAP: + case JS_ITERATOR_HELPER_KIND_MAP: + { + func = argv[0]; + if (check_function(ctx, func)) + return JS_EXCEPTION; + } + break; + default: + abort(); + break; + } + + method = JS_GetProperty(ctx, this_val, JS_ATOM_next); + if (JS_IsException(method)) + return JS_EXCEPTION; + obj = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_HELPER); + if (JS_IsException(obj)) { + JS_FreeValue(ctx, method); + return JS_EXCEPTION; + } + it = js_malloc(ctx, sizeof(*it)); + if (!it) { + JS_FreeValue(ctx, obj); + JS_FreeValue(ctx, method); + return JS_EXCEPTION; + } + it->kind = magic; + it->obj = js_dup(this_val); + it->func = js_dup(func); + it->next = method; + it->inner = JS_UNDEFINED; + it->count = count; + it->executing = 0; + it->done = 0; + JS_SetOpaqueInternal(obj, it); + return obj; +} + +static JSValue js_iterator_proto_func(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) +{ + JSValue item, method, ret, func, index_val, r; + JSValue args[2]; + int64_t idx; + BOOL done; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + if (check_function(ctx, argv[0])) + return JS_EXCEPTION; + func = js_dup(argv[0]); + method = JS_GetProperty(ctx, this_val, JS_ATOM_next); + if (JS_IsException(method)) + goto fail; + + r = JS_UNDEFINED; + + switch(magic) { + case JS_ITERATOR_HELPER_KIND_EVERY: + { + r = JS_TRUE; + for (idx = 0; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; + index_val = js_int64(idx); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto fail; + if (!JS_ToBoolFree(ctx, ret)) { + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) + r = JS_EXCEPTION; + else + r = JS_FALSE; + break; + } + index_val = JS_UNDEFINED; + ret = JS_UNDEFINED; + item = JS_UNDEFINED; + } + } + break; + case JS_ITERATOR_HELPER_KIND_FIND: + { + for (idx = 0; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; + index_val = js_int64(idx); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) { + JS_FreeValue(ctx, item); + goto fail; + } + if (JS_ToBoolFree(ctx, ret)) { + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) { + JS_FreeValue(ctx, item); + r = JS_EXCEPTION; + } else { + r = item; + } + break; + } + index_val = JS_UNDEFINED; + ret = JS_UNDEFINED; + item = JS_UNDEFINED; + } + } + break; + case JS_ITERATOR_HELPER_KIND_FOR_EACH: + { + for (idx = 0; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; + index_val = js_int64(idx); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto fail; + JS_FreeValue(ctx, ret); + index_val = JS_UNDEFINED; + ret = JS_UNDEFINED; + item = JS_UNDEFINED; + } + } + break; + case JS_ITERATOR_HELPER_KIND_SOME: + { + r = JS_FALSE; + for (idx = 0; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; + index_val = js_int64(idx); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto fail; + if (JS_ToBoolFree(ctx, ret)) { + if (JS_IteratorClose(ctx, this_val, FALSE) < 0) + r = JS_EXCEPTION; + else + r = JS_TRUE; + break; + } + index_val = JS_UNDEFINED; + ret = JS_UNDEFINED; + item = JS_UNDEFINED; + } + } + break; + default: + abort(); + break; + } + + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, method); + return r; +fail: + JS_IteratorClose(ctx, this_val, TRUE); + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, method); + return JS_EXCEPTION; +} + +static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue item, method, ret, func, index_val, acc; + JSValue args[3]; + int64_t idx; + BOOL done; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + if (check_function(ctx, argv[0])) + return JS_EXCEPTION; + acc = JS_UNDEFINED; + func = js_dup(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]); + idx = 0; + } else { + acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(acc)) + goto exception; + if (done) { + JS_ThrowTypeError(ctx, "empty iterator"); + goto exception; + } + idx = 1; + } + for (/* empty */; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto exception; + if (done) + break; + index_val = js_int64(idx); + args[0] = acc; + args[1] = item; + args[2] = index_val; + ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto exception; + JS_FreeValue(ctx, acc); + acc = ret; + index_val = JS_UNDEFINED; + ret = JS_UNDEFINED; + item = JS_UNDEFINED; + } + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, method); + return acc; +exception: + JS_IteratorClose(ctx, this_val, TRUE); + JS_FreeValue(ctx, acc); + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, method); + return JS_EXCEPTION; +} + +static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue item, method, result; + int64_t idx; + BOOL done; + + result = JS_UNDEFINED; + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + method = JS_GetProperty(ctx, this_val, JS_ATOM_next); + if (JS_IsException(method)) + return JS_EXCEPTION; + result = JS_NewArray(ctx); + if (JS_IsException(result)) + goto exception; + for (idx = 0; /*empty*/; idx++) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto exception; + if (done) + break; + if (JS_DefinePropertyValueInt64(ctx, result, idx, item, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) + goto exception; + } + if (JS_SetProperty(ctx, result, JS_ATOM_length, js_uint32(idx)) < 0) + goto exception; + JS_FreeValue(ctx, method); + return result; +exception: + JS_FreeValue(ctx, result); + JS_FreeValue(ctx, method); + return JS_EXCEPTION; +} + +static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + return js_dup(this_val); +} + +static JSValue js_iterator_proto_get_toStringTag(JSContext *ctx, JSValue this_val) +{ + return JS_AtomToString(ctx, JS_ATOM_Iterator); +} + +static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValue this_val, JSValue val) +{ + int res; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + 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) + return JS_EXCEPTION; + } else { + if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val), JS_PROP_C_W_E) < 0) + return JS_EXCEPTION; + } + return JS_UNDEFINED; +} + +static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSIteratorHelperData *it = p->u.iterator_helper_data; + if (it) { + JS_FreeValueRT(rt, it->obj); + JS_FreeValueRT(rt, it->func); + JS_FreeValueRT(rt, it->next); + JS_FreeValueRT(rt, it->inner); + js_free_rt(rt, it); + } +} + +static void js_iterator_helper_mark(JSRuntime *rt, JSValue val, + JS_MarkFunc *mark_func) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSIteratorHelperData *it = p->u.iterator_helper_data; + if (it) { + JS_MarkValue(rt, it->obj, mark_func); + JS_MarkValue(rt, it->func, mark_func); + JS_MarkValue(rt, it->next, mark_func); + JS_MarkValue(rt, it->inner, mark_func); + } +} + +static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, + BOOL *pdone, int magic) +{ + JSIteratorHelperData *it; + JSValue ret; + + *pdone = FALSE; + + it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER); + if (!it) + return JS_EXCEPTION; + if (it->executing) + return JS_ThrowTypeError(ctx, "cannot invoke a running iterator"); + if (it->done) { + *pdone = TRUE; + return JS_UNDEFINED; + } + + it->executing = 1; + + switch (it->kind) { + case JS_ITERATOR_HELPER_KIND_DROP: + { + JSValue item, method; + if (magic == GEN_MAGIC_NEXT) { + method = js_dup(it->next); + } else { + method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); + if (JS_IsException(method)) + goto fail; + } + while (it->count > 0) { + it->count--; + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + if (JS_IsException(item)) { + JS_FreeValue(ctx, method); + goto fail; + } + JS_FreeValue(ctx, item); + if (magic == GEN_MAGIC_RETURN) + *pdone = TRUE; + if (*pdone) { + JS_FreeValue(ctx, method); + ret = JS_UNDEFINED; + goto done; + } + } + + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto fail; + ret = item; + goto done; + } + break; + case JS_ITERATOR_HELPER_KIND_FILTER: + { + JSValue item, method, selected, index_val, args[2]; + if (magic == GEN_MAGIC_NEXT) { + method = js_dup(it->next); + } else { + method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); + if (JS_IsException(method)) + goto fail; + } + filter_again: + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + if (JS_IsException(item)) { + JS_FreeValue(ctx, method); + goto fail; + } + if (*pdone || magic == GEN_MAGIC_RETURN) { + JS_FreeValue(ctx, method); + ret = item; + goto done; + } + index_val = js_int64(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, method); + goto fail; + } + if (JS_ToBoolFree(ctx, selected)) { + JS_FreeValue(ctx, method); + ret = item; + goto done; + } + goto filter_again; + } + break; + case JS_ITERATOR_HELPER_KIND_FLAT_MAP: + { + JSValue item, method, index_val, args[2], iter; + flat_map_again: + if (JS_IsUndefined(it->inner)) { + if (magic == GEN_MAGIC_NEXT) { + method = js_dup(it->next); + } else { + method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); + if (JS_IsException(method)) + goto fail; + } + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto fail; + if (*pdone || magic == GEN_MAGIC_RETURN) { + ret = item; + goto done; + } + index_val = js_int64(it->count++); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto fail; + if (!JS_IsObject(ret)) { + JS_FreeValue(ctx, ret); + JS_ThrowTypeError(ctx, "not an object"); + goto fail; + } + method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator); + if (JS_IsException(method)) { + JS_FreeValue(ctx, ret); + goto fail; + } + if (JS_IsNull(method) || JS_IsUndefined(method)) { + JS_FreeValue(ctx, method); + iter = ret; + } else { + iter = JS_GetIterator2(ctx, ret, method); + JS_FreeValue(ctx, method); + JS_FreeValue(ctx, ret); + if (JS_IsException(iter)) + goto fail; + } + + it->inner = iter; + } + + if (magic == GEN_MAGIC_NEXT) + method = JS_GetProperty(ctx, it->inner, JS_ATOM_next); + else + method = JS_GetProperty(ctx, it->inner, JS_ATOM_return); + if (JS_IsException(method)) { + inner_fail: + JS_IteratorClose(ctx, it->inner, FALSE); + JS_FreeValue(ctx, it->inner); + it->inner = JS_UNDEFINED; + goto fail; + } + if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) { + goto inner_end; + } else { + item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto inner_fail; + } + if (*pdone) { + inner_end: + *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; + } + ret = item; + goto done; + } + break; + case JS_ITERATOR_HELPER_KIND_MAP: + { + JSValue item, method, index_val, args[2]; + if (magic == GEN_MAGIC_NEXT) { + method = js_dup(it->next); + } else { + method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); + if (JS_IsException(method)) + goto fail; + } + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto fail; + if (*pdone || magic == GEN_MAGIC_RETURN) { + ret = item; + goto done; + } + index_val = js_int64(it->count++); + args[0] = item; + args[1] = index_val; + ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); + JS_FreeValue(ctx, index_val); + if (JS_IsException(ret)) + goto fail; + goto done; + } + break; + case JS_ITERATOR_HELPER_KIND_TAKE: + { + JSValue item, method; + if (it->count > 0) { + if (magic == GEN_MAGIC_NEXT) { + method = js_dup(it->next); + } else { + method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); + if (JS_IsException(method)) + goto fail; + } + it->count--; + item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto fail; + ret = item; + goto done; + } + + *pdone = TRUE; + if (JS_IteratorClose(ctx, it->obj, FALSE)) + ret = JS_EXCEPTION; + else + ret = JS_UNDEFINED; + goto done; + } + break; + default: + abort(); + } + +done: + it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1; + it->executing = 0; + return ret; +fail: + /* close the iterator object, preserving pending exception */ + JS_IteratorClose(ctx, it->obj, TRUE); + ret = JS_EXCEPTION; + goto done; +} + +static const JSCFunctionListEntry js_iterator_funcs[] = { + JS_CFUNC_DEF("from", 1, js_iterator_from ), +}; + static const JSCFunctionListEntry js_iterator_proto_funcs[] = { + JS_CFUNC_MAGIC_DEF("drop", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_DROP ), + JS_CFUNC_MAGIC_DEF("filter", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FILTER ), + JS_CFUNC_MAGIC_DEF("flatMap", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FLAT_MAP ), + JS_CFUNC_MAGIC_DEF("map", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_MAP ), + JS_CFUNC_MAGIC_DEF("take", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_TAKE ), + JS_CFUNC_MAGIC_DEF("every", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_EVERY ), + JS_CFUNC_MAGIC_DEF("find", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FIND), + JS_CFUNC_MAGIC_DEF("forEach", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FOR_EACH ), + JS_CFUNC_MAGIC_DEF("some", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_SOME ), + JS_CFUNC_DEF("reduce", 1, js_iterator_proto_reduce ), + JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ), JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ), + JS_CGETSET_DEF("[Symbol.toStringTag]", js_iterator_proto_get_toStringTag, js_iterator_proto_set_toStringTag), +}; + +static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = { + JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_helper_next, GEN_MAGIC_NEXT ), + JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_helper_next, GEN_MAGIC_RETURN ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ), }; static const JSCFunctionListEntry js_array_proto_funcs[] = { @@ -40705,10 +40922,10 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ), JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ), JS_CFUNC_DEF("fill", 1, js_array_fill ), - JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, special_find ), - JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, special_findIndex ), - JS_CFUNC_MAGIC_DEF("findLast", 1, js_array_find, special_findLast ), - JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_array_find, special_findLastIndex ), + JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, ArrayFind ), + JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, ArrayFindIndex ), + JS_CFUNC_MAGIC_DEF("findLast", 1, js_array_find, ArrayFindLast ), + JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_array_find, ArrayFindLastIndex ), JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ), JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ), JS_CFUNC_DEF("includes", 1, js_array_includes ), @@ -40742,39 +40959,26 @@ static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = { /* Number */ -static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_number_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue val, obj; if (argc == 0) { - val = JS_NewInt32(ctx, 0); + val = js_int32(0); } else { val = JS_ToNumeric(ctx, argv[0]); if (JS_IsException(val)) return val; switch(JS_VALUE_GET_TAG(val)) { case JS_TAG_BIG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { - JSBigFloat *p = JS_VALUE_GET_PTR(val); + JSBigInt *p = JS_VALUE_GET_PTR(val); double d; bf_get_float64(&p->num, &d, BF_RNDN); JS_FreeValue(ctx, val); - val = __JS_NewFloat64(ctx, d); + val = js_float64(d); } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_DECIMAL: - val = JS_ToStringFree(ctx, val); - if (JS_IsException(val)) - return val; - val = JS_ToNumberFree(ctx, val); - if (JS_IsException(val)) - return val; - break; -#endif default: break; } @@ -40789,59 +40993,42 @@ 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) +static JSValue js_number_isNaN(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { if (!JS_IsNumber(argv[0])) return JS_FALSE; return js_global_isNaN(ctx, this_val, argc, argv); } -static JSValue js_number_isFinite(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_isFinite(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { if (!JS_IsNumber(argv[0])) return JS_FALSE; return js_global_isFinite(ctx, this_val, argc, argv); } -static JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_isInteger(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int ret; ret = JS_NumberIsInteger(ctx, argv[0]); if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_isSafeInteger(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { double d; if (!JS_IsNumber(argv[0])) return JS_FALSE; if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - return JS_NewBool(ctx, is_safe_integer(d)); + return js_bool(is_safe_integer(d)); } static const JSCFunctionListEntry js_number_funcs[] = { @@ -40854,52 +41041,51 @@ 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_DOUBLE_DEF("NaN", NAN, 0 ), + JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc 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) +static JSValue js_thisNumberValue(JSContext *ctx, JSValue this_val) { if (JS_IsNumber(this_val)) - return JS_DupValue(ctx, this_val); + return js_dup(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_DupValue(ctx, p->u.object_data); + return js_dup(p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a number"); } -static JSValue js_number_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_valueOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_thisNumberValue(ctx, this_val); } -static int js_get_radix(JSContext *ctx, JSValueConst val) +static int js_get_radix(JSContext *ctx, JSValue val) { int radix; if (JS_ToInt32Sat(ctx, &radix, val)) return -1; if (radix < 2 || radix > 36) { - JS_ThrowRangeError(ctx, "radix must be between 2 and 36"); + JS_ThrowRangeError(ctx, "toString() radix argument must be between 2 and 36"); return -1; } return radix; } -static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_number_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { + char buf[72]; JSValue val; int base; double d; @@ -40908,22 +41094,32 @@ static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val, if (JS_IsException(val)) return val; if (magic || JS_IsUndefined(argv[0])) { + if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) { + size_t len = i32toa(buf, JS_VALUE_GET_INT(val)); + return js_new_string8_len(ctx, buf, len); + } base = 10; } else { base = js_get_radix(ctx, argv[0]); - if (base < 0) - goto fail; + if (base < 0) { + JS_FreeValue(ctx, val); + return JS_EXCEPTION; + } + } + if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) { + size_t len = i32toa_radix(buf, JS_VALUE_GET_INT(val), base); + return js_new_string8_len(ctx, buf, len); } if (JS_ToFloat64Free(ctx, &d, val)) return JS_EXCEPTION; - return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT); - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; + if (base != 10) + return js_dtoa_radix(ctx, d, base); + + return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING); } -static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_toFixed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val; int f; @@ -40936,21 +41132,23 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (JS_ToInt32Sat(ctx, &f, argv[0])) return JS_EXCEPTION; - if (f < 0 || f > 100) - return JS_ThrowRangeError(ctx, "invalid number of digits"); + if (f < 0 || f > 100) { + return JS_ThrowRangeError(ctx, "toFixed() digits argument must be between 0 and 100"); + } if (fabs(d) >= 1e21) { - return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d)); + // use ToString(d) + return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING); } else { - return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT); + return js_dtoa(ctx, d, f, JS_DTOA_FIXED); } } -static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_toExponential(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val; - int f, flags; double d; + int f; val = js_thisNumberValue(ctx, this_val); if (JS_IsException(val)) @@ -40959,23 +41157,19 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (JS_ToInt32Sat(ctx, &f, argv[0])) return JS_EXCEPTION; - if (!isfinite(d)) { - return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d)); + if (!isfinite(d)) + return js_dtoa_infinite(ctx, d); + if (!JS_IsUndefined(argv[0])) { + if (f < 0 || f > 100) { + return JS_ThrowRangeError(ctx, "toExponential() argument must be between 0 and 100"); + } + f += 1; /* number of significant digits between 1 and 101 */ } - if (JS_IsUndefined(argv[0])) { - flags = 0; - f = 0; - } else { - if (f < 0 || f > 100) - return JS_ThrowRangeError(ctx, "invalid number of digits"); - f++; - flags = JS_DTOA_FIXED_FORMAT; - } - return js_dtoa(ctx, d, 10, f, flags | JS_DTOA_FORCE_EXP); + return js_dtoa(ctx, d, f, JS_DTOA_EXPONENTIAL); } -static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_number_toPrecision(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val; int p; @@ -40987,16 +41181,15 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val, if (JS_ToFloat64Free(ctx, &d, val)) return JS_EXCEPTION; if (JS_IsUndefined(argv[0])) - goto to_string; + return js_dtoa(ctx, d, 0, JS_DTOA_TOSTRING); if (JS_ToInt32Sat(ctx, &p, argv[0])) return JS_EXCEPTION; - if (!isfinite(d)) { - to_string: - return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d)); + if (!isfinite(d)) + return js_dtoa_infinite(ctx, d); + if (p < 1 || p > 100) { + return JS_ThrowRangeError(ctx, "toPrecision() argument must be between 1 and 100"); } - if (p < 1 || p > 100) - return JS_ThrowRangeError(ctx, "invalid number of digits"); - return js_dtoa(ctx, d, 10, p, JS_DTOA_FIXED_FORMAT); + return js_dtoa(ctx, d, p, JS_DTOA_PRECISION); } static const JSCFunctionListEntry js_number_proto_funcs[] = { @@ -41008,54 +41201,54 @@ static const JSCFunctionListEntry js_number_proto_funcs[] = { JS_CFUNC_DEF("valueOf", 0, js_number_valueOf ), }; -static JSValue js_parseInt(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_parseInt(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - const char *str, *p; + const char *str; int radix, flags; JSValue ret; + size_t len; - str = JS_ToCString(ctx, argv[0]); + str = JS_ToCStringLen(ctx, &len, argv[0]); if (!str) return JS_EXCEPTION; if (JS_ToInt32(ctx, &radix, argv[1])) { JS_FreeCString(ctx, str); return JS_EXCEPTION; } - if (radix != 0 && (radix < 2 || radix > 36)) { - ret = JS_NAN; - } else { - p = str; - p += skip_spaces(p); - flags = ATOD_INT_ONLY | ATOD_ACCEPT_PREFIX_AFTER_SIGN; - ret = js_atof(ctx, p, NULL, radix, flags); + flags = ATOD_TRIM_SPACES; + if (radix == 0) { + flags |= ATOD_ACCEPT_HEX_PREFIX; // Only 0x and 0X are supported + radix = 10; } + ret = js_atof(ctx, str, len, NULL, radix, flags); JS_FreeCString(ctx, str); return ret; } -static JSValue js_parseFloat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_parseFloat(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - const char *str, *p; + const char *str; JSValue ret; + int flags; + size_t len; - str = JS_ToCString(ctx, argv[0]); + str = JS_ToCStringLen(ctx, &len, argv[0]); if (!str) return JS_EXCEPTION; - p = str; - p += skip_spaces(p); - ret = js_atof(ctx, p, NULL, 10, 0); + flags = ATOD_TRIM_SPACES | ATOD_ACCEPT_FLOAT | ATOD_ACCEPT_INFINITY; + ret = js_atof(ctx, str, len, NULL, 10, flags); JS_FreeCString(ctx, str); return ret; } /* Boolean */ -static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_boolean_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue val, obj; - val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0])); + val = js_bool(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)) @@ -41066,10 +41259,10 @@ static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target, } } -static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val) +static JSValue js_thisBooleanValue(JSContext *ctx, JSValue this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL) - return JS_DupValue(ctx, this_val); + return js_dup(this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); @@ -41081,8 +41274,8 @@ static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val) return JS_ThrowTypeError(ctx, "not a boolean"); } -static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_boolean_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val = js_thisBooleanValue(ctx, this_val); if (JS_IsException(val)) @@ -41091,8 +41284,8 @@ static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val, JS_ATOM_true : JS_ATOM_false); } -static JSValue js_boolean_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_boolean_valueOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_thisBooleanValue(ctx, this_val); } @@ -41106,7 +41299,7 @@ static const JSCFunctionListEntry js_boolean_proto_funcs[] = { static int js_string_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop) + JSValue obj, JSAtom prop) { JSObject *p; JSString *p1; @@ -41120,10 +41313,7 @@ static int js_string_get_own_property(JSContext *ctx, idx = __JS_AtomToUInt32(prop); if (idx < p1->len) { if (desc) { - if (p1->is_wide_char) - ch = p1->u.str16[idx]; - else - ch = p1->u.str8[idx]; + ch = string_get(p1, idx); desc->flags = JS_PROP_ENUMERABLE; desc->value = js_new_string_char(ctx, ch); desc->getter = JS_UNDEFINED; @@ -41137,15 +41327,15 @@ static int js_string_get_own_property(JSContext *ctx, } static int js_string_define_own_property(JSContext *ctx, - JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, - JSValueConst setter, int flags) + JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, + JSValue setter, int flags) { uint32_t idx; JSObject *p; JSString *p1, *p2; - + if (__JS_AtomIsTaggedInt(prop)) { idx = __JS_AtomToUInt32(prop); p = JS_VALUE_GET_OBJ(this_obj); @@ -41177,7 +41367,7 @@ static int js_string_define_own_property(JSContext *ctx, } static int js_string_delete_property(JSContext *ctx, - JSValueConst obj, JSAtom prop) + JSValue obj, JSAtom prop) { uint32_t idx; @@ -41196,8 +41386,8 @@ static const JSClassExoticMethods js_string_exotic_methods = { .delete_property = js_string_delete_property, }; -static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_string_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue val, obj; if (argc == 0) { @@ -41218,7 +41408,7 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, obj = js_create_from_ctor(ctx, new_target, JS_CLASS_STRING); if (!JS_IsException(obj)) { JS_SetObjectData(ctx, obj, val); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0); + JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0); } return obj; } else { @@ -41226,27 +41416,33 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, } } -static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val) +static JSValue js_thisStringValue(JSContext *ctx, JSValue this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING) - return JS_DupValue(ctx, this_val); + return js_dup(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_DupValue(ctx, p->u.object_data); + return js_dup(p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a string"); } -static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_fromCharCode(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { 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++) { @@ -41259,15 +41455,30 @@ static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val, return string_buffer_end(b); } -static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_fromCodePoint(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { double d; int i, c; - StringBuffer b_s, *b = &b_s; + 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); + } + } /* 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++) { @@ -41278,7 +41489,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 (!(d >= 0 && d <= 0x10ffff) || (c = (int)d) != d) goto range_error; } if (string_buffer_putc(b, c)) @@ -41289,12 +41500,12 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val, range_error: JS_ThrowRangeError(ctx, "invalid code point"); fail: - string_buffer_free(b); + if (b) string_buffer_free(b); return JS_EXCEPTION; } -static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_raw(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // raw(temp,...a) JSValue cooked, val, raw; @@ -41311,7 +41522,7 @@ static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val, goto exception; if (js_get_length64(ctx, &n, raw) < 0) goto exception; - + for (i = 0; i < n; i++) { val = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, raw, i)); if (JS_IsException(val)) @@ -41334,8 +41545,8 @@ exception: } /* only used in test262 */ -JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { uint32_t start, end, i, n; StringBuffer b_s, *b = &b_s; @@ -41360,19 +41571,35 @@ JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, return string_buffer_end(b); } -#if 0 -static JSValue js_string___isSpace(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_at(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - int c; - if (JS_ToInt32(ctx, &c, argv[0])) - return JS_EXCEPTION; - return JS_NewBool(ctx, lre_is_space(c)); -} -#endif + JSValue val, ret; + JSString *p; + int idx, c; -static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + 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); + 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; +} + +static JSValue js_string_charCodeAt(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val, ret; JSString *p; @@ -41389,18 +41616,15 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val, if (idx < 0 || idx >= p->len) { ret = JS_NAN; } else { - if (p->is_wide_char) - c = p->u.str16[idx]; - else - c = p->u.str8[idx]; - ret = JS_NewInt32(ctx, c); + c = string_get(p, idx); + ret = js_int32(c); } JS_FreeValue(ctx, val); return ret; } -static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_at) +static JSValue js_string_charAt(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val, ret; JSString *p; @@ -41414,26 +41638,18 @@ 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) { - if (is_at) - ret = JS_UNDEFINED; - else - ret = js_new_string8(ctx, NULL, 0); + ret = JS_AtomToString(ctx, JS_ATOM_empty_string); } else { - if (p->is_wide_char) - c = p->u.str16[idx]; - else - c = p->u.str8[idx]; + c = string_get(p, idx); ret = js_new_string_char(ctx, c); } JS_FreeValue(ctx, val); return ret; } -static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_codePointAt(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val, ret; JSString *p; @@ -41451,14 +41667,14 @@ static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; } else { c = string_getc(p, &idx); - ret = JS_NewInt32(ctx, c); + ret = js_int32(c); } JS_FreeValue(ctx, val); return ret; } -static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_concat(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue r; int i; @@ -41470,7 +41686,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_DupValue(ctx, argv[i])); + r = JS_ConcatString(ctx, r, js_dup(argv[i])); } return r; } @@ -41533,86 +41749,83 @@ 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, c; - if (!p->is_wide_char) - return -1; - for(i = 0; i < p->len; i++) { - c = p->u.str16[i]; - if (c >= 0xD800 && c <= 0xDFFF) { - if (c >= 0xDC00 || (i + 1) >= p->len) - return i; - c = p->u.str16[i + 1]; - if (c < 0xDC00 || c > 0xDFFF) - return i; - i++; - } - } - return -1; -} - -static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_isWellFormed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str; + JSValue ret; JSString *p; - BOOL ret; - - str = JS_ToStringCheckObject(ctx, this_val); - if (JS_IsException(str)) - return JS_EXCEPTION; - p = JS_VALUE_GET_STRING(str); - ret = (js_string_find_invalid_codepoint(p) < 0); - JS_FreeValue(ctx, str); - return JS_NewBool(ctx, ret); -} - -static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue str, ret; - JSString *p; - int c, i; + uint32_t c, i, n; + ret = JS_TRUE; str = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(str)) return JS_EXCEPTION; p = JS_VALUE_GET_STRING(str); - /* avoid reallocating the string if it is well-formed */ - i = js_string_find_invalid_codepoint(p); - if (i < 0) - return str; + if (!p->is_wide_char || p->len == 0) + goto done; // by definition well-formed - ret = js_new_string16(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 < p->len; i++) { + for (i = 0, n = p->len; i < n; i++) { c = p->u.str16[i]; - if (c >= 0xD800 && c <= 0xDFFF) { - if (c >= 0xDC00 || (i + 1) >= p->len) { - p->u.str16[i] = 0xFFFD; - } else { - c = p->u.str16[i + 1]; - if (c < 0xDC00 || c > 0xDFFF) { - p->u.str16[i] = 0xFFFD; - } else { - i++; - } - } - } + if (!is_surrogate(c)) + continue; + if (is_lo_surrogate(c) || i + 1 == n) + break; + c = p->u.str16[++i]; + if (!is_lo_surrogate(c)) + break; } + + if (i < n) + ret = JS_FALSE; + +done: + JS_FreeValue(ctx, str); return ret; } -static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int lastIndexOf) +static JSValue js_string_toWellFormed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue str; + JSValue ret; + JSString *p; + uint32_t c, i, n; + + 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 + + // TODO(bnoordhuis) don't clone when input is well-formed + 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 = p->u.str16[i]; + if (!is_surrogate(c)) + continue; + if (is_lo_surrogate(c) || i + 1 == n) { + p->u.str16[i] = 0xFFFD; + continue; + } + c = p->u.str16[++i]; + if (!is_lo_surrogate(c)) + p->u.str16[--i] = 0xFFFD; + } + + return ret; +} + +static JSValue js_string_indexOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int lastIndexOf) { JSValue str, v; int i, len, v_len, pos, start, stop, ret, inc; @@ -41668,7 +41881,7 @@ static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, str); JS_FreeValue(ctx, v); - return JS_NewInt32(ctx, ret); + return js_int32(ret); fail: JS_FreeValue(ctx, str); @@ -41677,10 +41890,10 @@ fail: } /* return < 0 if exception or TRUE/FALSE */ -static int js_is_regexp(JSContext *ctx, JSValueConst obj); +static int js_is_regexp(JSContext *ctx, JSValue obj); -static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_string_includes(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue str, v = JS_UNDEFINED; int i, len, v_len, pos, start, stop, ret; @@ -41693,7 +41906,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, ret = js_is_regexp(ctx, argv[0]); if (ret) { if (ret > 0) - JS_ThrowTypeError(ctx, "regex not supported"); + JS_ThrowTypeError(ctx, "regexp not supported"); goto fail; } v = JS_ToString(ctx, argv[0]); @@ -41735,7 +41948,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, done: JS_FreeValue(ctx, str); JS_FreeValue(ctx, v); - return JS_NewBool(ctx, ret); + return js_bool(ret); fail: JS_FreeValue(ctx, str); @@ -41743,11 +41956,11 @@ fail: return JS_EXCEPTION; } -static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp) +static int check_regexp_g_flag(JSContext *ctx, JSValue regexp) { int ret; JSValue flags; - + ret = js_is_regexp(ctx, regexp); if (ret < 0) return -1; @@ -41772,12 +41985,12 @@ static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp) return 0; } -static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int atom) +static JSValue js_string_match(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int atom) { // match(rx), search(rx), matchAll(rx) // atom is JS_ATOM_Symbol_match, JS_ATOM_Symbol_search, or JS_ATOM_Symbol_matchAll - JSValueConst O = this_val, regexp = argv[0], args[2]; + JSValue O = this_val, regexp = argv[0], args[2]; JSValue matcher, S, rx, result, str; int args_len; @@ -41805,10 +42018,10 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, args[0] = regexp; str = JS_UNDEFINED; if (atom == JS_ATOM_Symbol_matchAll) { - str = JS_NewString(ctx, "g"); + str = js_new_string8(ctx, "g"); if (JS_IsException(str)) goto fail; - args[args_len++] = (JSValueConst)str; + args[args_len++] = str; } rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args); JS_FreeValue(ctx, str); @@ -41817,16 +42030,16 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, S); return JS_EXCEPTION; } - result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S); + result = JS_InvokeFree(ctx, rx, atom, 1, &S); JS_FreeValue(ctx, S); return result; } -static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string___GetSubstitution(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // GetSubstitution(matched, str, position, captures, namedCaptures, rep) - JSValueConst matched, str, captures, namedCaptures, rep; + JSValue matched, str, captures, namedCaptures, rep; JSValue capture, name, s; uint32_t position, len, matched_len, captures_len; int i, j, j0, k, k1; @@ -41930,13 +42143,13 @@ exception: return JS_EXCEPTION; } -static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_string_replace(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int is_replaceAll) { // replace(rx, rep) - JSValueConst O = this_val, searchValue = argv[0], replaceValue = argv[1]; - JSValueConst args[6]; + JSValue O = this_val, searchValue = argv[0], replaceValue = argv[1]; + JSValue args[6]; JSValue str, search_str, replaceValue_str, repl_str; JSString *sp, *searchp; StringBuffer b_s, *b = &b_s; @@ -42007,13 +42220,13 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, } if (functionalReplace) { args[0] = search_str; - args[1] = JS_NewInt32(ctx, pos); + args[1] = js_int32(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_NewInt32(ctx, pos); + args[2] = js_int32(pos); args[3] = JS_UNDEFINED; args[4] = JS_UNDEFINED; args[5] = replaceValue_str; @@ -42021,7 +42234,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, } if (JS_IsException(repl_str)) goto exception; - + string_buffer_concat(b, sp, endOfLastMatch, pos); string_buffer_concat_value_free(b, repl_str); endOfLastMatch = pos + searchp->len; @@ -42043,12 +42256,12 @@ exception: return JS_EXCEPTION; } -static JSValue js_string_split(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_split(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // split(sep, limit) - JSValueConst O = this_val, separator = argv[0], limit = argv[1]; - JSValueConst args[2]; + JSValue O = this_val, separator = argv[0], limit = argv[1]; + JSValue args[2]; JSValue S, A, R, T; uint32_t lim, lengthA; int64_t p, q, s, r, e; @@ -42133,8 +42346,8 @@ exception: return JS_EXCEPTION; } -static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_substring(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str, ret; int a, b, start, end; @@ -42167,8 +42380,8 @@ static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_substr(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str, ret; int a, len, n; @@ -42195,8 +42408,8 @@ static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_slice(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str, ret; int len, start, end; @@ -42223,8 +42436,8 @@ static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int padEnd) +static JSValue js_string_pad(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int padEnd) { JSValue str, v = JS_UNDEFINED; StringBuffer b_s, *b = &b_s; @@ -42255,7 +42468,7 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, } } if (n > JS_STRING_LEN_MAX) { - JS_ThrowInternalError(ctx, "string too long"); + JS_ThrowRangeError(ctx, "invalid string length"); goto fail2; } if (string_buffer_init(ctx, b, n)) @@ -42294,8 +42507,8 @@ fail1: return JS_EXCEPTION; } -static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_string_repeat(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str; StringBuffer b_s, *b = &b_s; @@ -42318,7 +42531,7 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val, if (len == 0 || n == 1) return str; if (val * len > JS_STRING_LEN_MAX) { - JS_ThrowInternalError(ctx, "string too long"); + JS_ThrowRangeError(ctx, "invalid string length"); goto fail; } if (string_buffer_init2(ctx, b, n * len, p->is_wide_char)) @@ -42338,8 +42551,8 @@ fail: return JS_EXCEPTION; } -static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_string_trim(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue str, ret; int a, b, len; @@ -42364,12 +42577,6 @@ static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_string___quote(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ToQuotedString(ctx, this_val); -} - /* return 0 if before the first char */ static int string_prevc(JSString *p, int *pidx) { @@ -42381,10 +42588,10 @@ static int string_prevc(JSString *p, int *pidx) idx--; if (p->is_wide_char) { c = p->u.str16[idx]; - if (c >= 0xdc00 && c < 0xe000 && idx > 0) { + if (is_lo_surrogate(c) && idx > 0) { c1 = p->u.str16[idx - 1]; - if (c1 >= 0xd800 && c1 <= 0xdc00) { - c = (((c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; + if (is_hi_surrogate(c1)) { + c = from_surrogate(c1, c); idx--; } } @@ -42423,8 +42630,84 @@ static BOOL test_final_sigma(JSString *p, int sigma_pos) return !lre_is_cased(c1); } -static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int to_lower) +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, JSValue this_val, + int argc, JSValue *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, JSValue this_val, + int argc, JSValue *argv, int to_lower) { JSValue val; StringBuffer b_s, *b = &b_s; @@ -42461,35 +42744,18 @@ 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, JSValueConst val1) +static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValue val1) { JSValue val; - JSString *p; - uint32_t *buf; - int i, j, len; + int len; val = JS_ToString(ctx, val1); if (JS_IsException(val)) return -1; - 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); + len = to_utf32_buf(ctx, JS_VALUE_GET_STRING(val), pbuf); JS_FreeValue(ctx, val); - *pbuf = buf; - return j; - fail: - *pbuf = NULL; - return -1; + return len; } static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len) @@ -42508,38 +42774,23 @@ 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) +static JSValue js_string_normalize(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { const char *form, *p; size_t form_len; - int is_compat, out_len; + int is_compat, buf_len, out_len; UnicodeNormalizationEnum n_type; JSValue val; - uint32_t *out_buf; + uint32_t *buf, *out_buf; val = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(val)) return val; + 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; @@ -42565,14 +42816,15 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, form); JS_ThrowRangeError(ctx, "bad normalization form"); fail1: - JS_FreeValue(ctx, val); + js_free(ctx, buf); return JS_EXCEPTION; } JS_FreeCString(ctx, form); } - out_len = js_string_normalize1(ctx, &out_buf, val, n_type); - JS_FreeValue(ctx, val); + 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 JS_EXCEPTION; val = JS_NewUTF32String(ctx, out_buf, out_len); @@ -42580,134 +42832,17 @@ 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) +static JSValue js_string_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { 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, +static JSValue js_string_iterator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic) { JSArrayIteratorData *it; @@ -42738,7 +42873,7 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, if (c <= 0xffff) { return js_new_string_char(ctx, c); } else { - return js_new_string16(ctx, p->u.str16 + start, 2); + return js_new_string16_len(ctx, p->u.str16 + start, 2); } } @@ -42759,8 +42894,8 @@ enum { magic_string_sup, }; -static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_string_CreateHTML(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue str; const JSString *p; @@ -42768,7 +42903,7 @@ static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val, static struct { const char *tag, *attr; } const defs[] = { { "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL }, { "tt", NULL }, { "font", "color" }, { "font", "size" }, { "i", NULL }, - { "a", "href" }, { "small", NULL }, { "strike", NULL }, + { "a", "href" }, { "small", NULL }, { "strike", NULL }, { "sub", NULL }, { "sup", NULL }, }; @@ -42817,18 +42952,13 @@ 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_MAGIC_DEF("at", 1, js_string_charAt, 1 ), + JS_CFUNC_DEF("at", 1, js_string_at ), JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ), - JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ), + JS_CFUNC_DEF("charAt", 1, js_string_charAt ), JS_CFUNC_DEF("concat", 1, js_string_concat ), JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ), JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ), @@ -42857,8 +42987,8 @@ 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("__quote", 1, js_string___quote ), 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 ), @@ -42885,19 +43015,6 @@ static const JSCFunctionListEntry js_string_iterator_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "String Iterator", JS_PROP_CONFIGURABLE ), }; -#ifdef CONFIG_ALL_UNICODE -static const JSCFunctionListEntry js_string_proto_normalize[] = { - JS_CFUNC_DEF("normalize", 0, js_string_normalize ), -}; -#endif - -void JS_AddIntrinsicStringNormalize(JSContext *ctx) -{ -#ifdef CONFIG_ALL_UNICODE - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize, - countof(js_string_proto_normalize)); -#endif -} /* Math */ @@ -42929,8 +43046,8 @@ 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) +static JSValue js_math_min_max(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { BOOL is_max = magic; double r, a; @@ -42938,7 +43055,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_float64(is_max ? NEG_INF : INF); } tag = JS_VALUE_GET_TAG(argv[0]); @@ -42957,7 +43074,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, r1 = min_int(r1, a1); } - return JS_NewInt32(ctx, r1); + return js_int32(r1); } else { if (JS_ToFloat64(ctx, &r, argv[0])) return JS_EXCEPTION; @@ -42978,7 +43095,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, } i++; } - return JS_NewFloat64(ctx, r); + return js_number(r); } } @@ -43020,8 +43137,8 @@ static double js_math_round(double a) return u.d; } -static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_math_hypot(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { double r, a; int i; @@ -43041,7 +43158,12 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, } } } - return JS_NewFloat64(ctx, r); + return js_float64(r); +} + +static double js_math_f16round(double a) +{ + return fromfp16(tofp16(a)); } static double js_math_fround(double a) @@ -43049,21 +43171,23 @@ static double js_math_fround(double a) return (float)a; } -static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_math_imul(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - int a, b; + uint32_t a, b, c; + int32_t d; - if (JS_ToInt32(ctx, &a, argv[0])) + if (JS_ToUint32(ctx, &a, argv[0])) return JS_EXCEPTION; - if (JS_ToInt32(ctx, &b, argv[1])) + if (JS_ToUint32(ctx, &b, argv[1])) return JS_EXCEPTION; - /* purposely ignoring overflow */ - return JS_NewInt32(ctx, a * b); + c = a * b; + memcpy(&d, &c, sizeof(d)); + return js_int32(d); } -static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_math_clz32(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { uint32_t a, r; @@ -43073,7 +43197,65 @@ static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, r = 32; else r = clz32(a); - return JS_NewInt32(ctx, r); + return js_int32(r); +} + +static JSValue js_math_sumPrecise(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue iter, next, item, ret; + bf_t a, b; + BOOL done; + double d; + int r; + + iter = JS_GetIterator(ctx, argv[0], /*async*/FALSE); + if (JS_IsException(iter)) + return JS_EXCEPTION; + bf_init(ctx->bf_ctx, &a); + bf_init(ctx->bf_ctx, &b); + ret = JS_EXCEPTION; + next = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next)) + goto fail; + bf_set_zero(&a, /*is_neg*/TRUE); + for (;;) { + item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; // item == JS_UNDEFINED + switch (JS_VALUE_GET_TAG(item)) { + default: + JS_FreeValue(ctx, item); + JS_ThrowTypeError(ctx, "not a number"); + goto fail; + case JS_TAG_INT: + d = JS_VALUE_GET_INT(item); + break; + case JS_TAG_FLOAT64: + d = JS_VALUE_GET_FLOAT64(item); + break; + } + if (bf_set_float64(&b, d)) + goto oom; + // Infinity + -Infinity results in BF_ST_INVALID_OP, sets |a| to nan + if ((r = bf_add(&a, &a, &b, BF_PREC_INF, BF_RNDN))) + if (r != BF_ST_INVALID_OP) + goto oom; + } + bf_get_float64(&a, &d, BF_RNDN); // return value deliberately ignored + ret = js_float64(d); +fail: + JS_IteratorClose(ctx, iter, JS_IsException(ret)); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + bf_delete(&a); + bf_delete(&b); + return ret; +oom: + JS_ThrowOutOfMemory(ctx); + goto fail; } /* xorshift* random number generator by Marsaglia */ @@ -43090,16 +43272,14 @@ static uint64_t xorshift64star(uint64_t *pstate) static void js_random_init(JSContext *ctx) { - struct timeval tv; - gettimeofday(&tv, NULL); - ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; + ctx->random_state = js__gettimeofday_us(); /* the state must be non zero */ if (ctx->random_state == 0) ctx->random_state = 1; } -static JSValue js_math_random(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_math_random(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSFloat64Union u; uint64_t v; @@ -43107,47 +43287,79 @@ 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_NewFloat64(ctx, u.d - 1.0); + return js_float64(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("sqrt", 1, f_f, js_math_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("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("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_math_pow ), + 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 ), JS_CFUNC_SPECIAL_DEF("fround", 1, f_f, js_math_fround ), JS_CFUNC_DEF("imul", 2, js_math_imul ), JS_CFUNC_DEF("clz32", 1, js_math_clz32 ), + JS_CFUNC_DEF("sumPrecise", 1, js_math_sumPrecise ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Math", JS_PROP_CONFIGURABLE ), JS_PROP_DOUBLE_DEF("E", 2.718281828459045, 0 ), JS_PROP_DOUBLE_DEF("LN10", 2.302585092994046, 0 ), @@ -43167,11 +43379,20 @@ 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) -{ +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 time_t ti; - int res; - + struct tm tm; + time /= 1000; /* convert to seconds */ if (sizeof(time_t) == 4) { /* on 32-bit systems, we need to clamp the time value to the @@ -43194,73 +43415,21 @@ static int getTimezoneOffset(int64_t time) } } ti = time; -#if defined(_WIN32) - { - struct tm *tm; - time_t gm_ti, loc_ti; - - tm = gmtime(&ti); - gm_ti = mktime(tm); - - tm = localtime(&ti); - loc_ti = mktime(tm); + localtime_r(&ti, &tm); +#ifdef NO_TM_GMTOFF + struct tm gmt; + gmtime_r(&ti, &gmt); - res = (gm_ti - loc_ti) / 60; - } + /* disable DST adjustment on the local tm struct */ + tm.tm_isdst = 0; + + return (int)difftime(mktime(&gmt), mktime(&tm)) / 60; #else - { - struct tm tm; - localtime_r(&ti, &tm); - res = -tm.tm_gmtoff / 60; - } + return -tm.tm_gmtoff / 60; +#endif /* NO_TM_GMTOFF */ #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, JSValue val) @@ -43272,8 +43441,8 @@ static void js_regexp_finalizer(JSRuntime *rt, JSValue val) } /* create a string containing the RegExp bytecode */ -static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, - JSValueConst flags) +static JSValue js_compile_regexp(JSContext *ctx, JSValue pattern, + JSValue flags) { const char *str; int re_flags, mask; @@ -43307,7 +43476,10 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, mask = LRE_FLAG_DOTALL; break; case 'u': - mask = LRE_FLAG_UTF16; + mask = LRE_FLAG_UNICODE; + break; + case 'v': + mask = LRE_FLAG_UNICODE_SETS; break; case 'y': mask = LRE_FLAG_STICKY; @@ -43325,7 +43497,11 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, JS_FreeCString(ctx, str); } - str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16)); + 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)); if (!str) return JS_EXCEPTION; re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg, @@ -43336,14 +43512,14 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, return JS_EXCEPTION; } - ret = js_new_string8(ctx, re_bytecode_buf, re_bytecode_len); + ret = js_new_string8_len(ctx, (char *)re_bytecode_buf, re_bytecode_len); js_free(ctx, re_bytecode_buf); return ret; } /* create a RegExp object from a string containing the RegExp bytecode and the source pattern */ -static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, +static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValue ctor, JSValue pattern, JSValue bc) { JSValue obj; @@ -43367,12 +43543,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_NewInt32(ctx, 0), + JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, js_int32(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, JSValue obj, BOOL throw_error) { if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(obj); @@ -43386,7 +43562,7 @@ static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_erro } /* return < 0 if exception or TRUE/FALSE */ -static int js_is_regexp(JSContext *ctx, JSValueConst obj) +static int js_is_regexp(JSContext *ctx, JSValue obj) { JSValue m; @@ -43400,11 +43576,11 @@ static int js_is_regexp(JSContext *ctx, JSValueConst obj) return js_get_regexp(ctx, obj, FALSE) != NULL; } -static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_regexp_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue pattern, flags, bc, val; - JSValueConst pat, flags1; + JSValue pat, flags1; JSRegExp *re; int pat_is_regexp; @@ -43425,14 +43601,14 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, res = js_same_value(ctx, ctor, new_target); JS_FreeValue(ctx, ctor); if (res) - return JS_DupValue(ctx, pat); + return js_dup(pat); } } re = js_get_regexp(ctx, pat, FALSE); if (re) { - pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern)); + pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re->pattern)); if (JS_IsUndefined(flags1)) { - bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode)); + bc = js_dup(JS_MKPTR(JS_TAG_STRING, re->bytecode)); goto no_compilation; } else { flags = JS_ToString(ctx, flags1); @@ -43450,11 +43626,11 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, if (JS_IsException(flags)) goto fail; } else { - flags = JS_DupValue(ctx, flags1); + flags = js_dup(flags1); } } else { - pattern = JS_DupValue(ctx, pat); - flags = JS_DupValue(ctx, flags1); + pattern = js_dup(pat); + flags = js_dup(flags1); } if (JS_IsUndefined(pattern)) { pattern = JS_AtomToString(ctx, JS_ATOM_empty_string); @@ -43478,11 +43654,11 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, return JS_EXCEPTION; } -static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_compile(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSRegExp *re1, *re; - JSValueConst pattern1, flags1; + JSValue pattern1, flags1; JSValue bc, pattern; re = js_get_regexp(ctx, this_val, TRUE); @@ -43494,8 +43670,8 @@ static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val, if (re1) { if (!JS_IsUndefined(flags1)) return JS_ThrowTypeError(ctx, "flags must be undefined"); - pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->pattern)); - bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->bytecode)); + pattern = js_dup(JS_MKPTR(JS_TAG_STRING, re1->pattern)); + bc = js_dup(JS_MKPTR(JS_TAG_STRING, re1->bytecode)); } else { bc = JS_UNDEFINED; if (JS_IsUndefined(pattern1)) @@ -43513,37 +43689,16 @@ 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_NewInt32(ctx, 0)) < 0) + js_int32(0)) < 0) return JS_EXCEPTION; - return JS_DupValue(ctx, this_val); + return js_dup(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) +static JSValue js_regexp_get_source(JSContext *ctx, JSValue this_val) { JSRegExp *re; JSString *p; @@ -43564,8 +43719,8 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) if (p->len == 0) { empty_regex: - return JS_NewString(ctx, "(?:)"); - } + return js_new_string8(ctx, "(?:)"); + } string_buffer_init2(ctx, b, p->len, p->is_wide_char); /* Escape '/' and newline sequences as needed */ @@ -43609,7 +43764,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) return string_buffer_end(b); } -static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mask) +static JSValue js_regexp_get_flag(JSContext *ctx, JSValue this_val, int mask) { JSRegExp *re; int flags; @@ -43624,12 +43779,12 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas else return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP); } - + flags = lre_get_flags(re->bytecode->u.str8); - return JS_NewBool(ctx, (flags & mask) != 0); + return js_bool(flags & mask); } -static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val) +static JSValue js_regexp_get_flags(JSContext *ctx, JSValue this_val) { char str[8], *p = str; int res; @@ -43667,19 +43822,26 @@ static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val) 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'; - return JS_NewStringLen(ctx, str, p - str); + if (p == str) + return JS_AtomToString(ctx, JS_ATOM_empty_string); + return js_new_string8_len(ctx, str, p - str); exception: return JS_EXCEPTION; } -static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue pattern, flags; StringBuffer b_s, *b = &b_s; @@ -43716,8 +43878,55 @@ void *lre_realloc(void *opaque, void *ptr, size_t size) return js_realloc_rt(ctx->rt, ptr, size); } -static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_escape(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + StringBuffer b_s, *b = &b_s; + JSString *p; + uint32_t c, i; + char s[16]; + + if (!JS_IsString(argv[0])) + return JS_ThrowTypeError(ctx, "not a string"); + p = JS_VALUE_GET_STRING(argv[0]); + string_buffer_init2(ctx, b, 0, p->is_wide_char); + for (i = 0; i < p->len; i++) { + c = p->is_wide_char ? (uint32_t)p->u.str16[i] : (uint32_t)p->u.str8[i]; + if (c < 33) { + if (c >= 9 && c <= 13) { + string_buffer_putc8(b, '\\'); + string_buffer_putc8(b, "tnvfr"[c - 9]); + } else { + goto hex2; + } + } else if (c < 128) { + if ((c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')) { + if (i == 0) + goto hex2; + } else if (strchr(",-=<>#&!%:;@~'`\"", c)) { + goto hex2; + } else if (c != '_') { + string_buffer_putc8(b, '\\'); + } + string_buffer_putc8(b, c); + } else if (c < 256) { + 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) { + snprintf(s, sizeof(s), "\\u%04x", c); + string_buffer_puts8(b, s); + } else { + string_buffer_putc16(b, c); + } + } + return string_buffer_end(b); +} + +static JSValue js_regexp_exec(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); JSString *str; @@ -43772,7 +43981,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_NewInt32(ctx, 0)) < 0) + js_int32(0)) < 0) goto fail; } } else { @@ -43783,7 +43992,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_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0) + js_int32((capture[1] - str_buf) >> shift)) < 0) goto fail; } obj = JS_NewArray(ctx); @@ -43812,8 +44021,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; group_name_ptr += strlen(group_name_ptr) + 1; @@ -43825,26 +44033,26 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } if (!JS_IsUndefined(indices)) { - val = JS_UNDEFINED; + JSValue val = JS_UNDEFINED; if (start != -1) { val = JS_NewArray(ctx); if (JS_IsException(val)) goto fail; if (JS_DefinePropertyValueUint32(ctx, val, 0, - JS_NewInt32(ctx, start), + js_int32(start), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; } if (JS_DefinePropertyValueUint32(ctx, val, 1, - JS_NewInt32(ctx, end), + js_int32(end), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; } } if (name && !JS_IsUndefined(indices_groups)) { - val = JS_DupValue(ctx, val); + val = js_dup(val); if (JS_DefinePropertyValueStr(ctx, indices_groups, name, val, prop_flags) < 0) { JS_FreeValue(ctx, val); @@ -43857,7 +44065,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } } - val = JS_UNDEFINED; + JSValue val = JS_UNDEFINED; if (start != -1) { val = js_sub_string(ctx, str, start, end); if (JS_IsException(val)) @@ -43866,7 +44074,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, if (name) { if (JS_DefinePropertyValueStr(ctx, groups, name, - JS_DupValue(ctx, val), + js_dup(val), prop_flags) < 0) { JS_FreeValue(ctx, val); goto fail; @@ -43883,7 +44091,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } - t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift); + t = js_int32((capture[0] - str_buf) >> shift); if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0) goto fail; @@ -43917,7 +44125,7 @@ fail: } /* delete portions of a string that match a given regex */ -static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg) +static JSValue JS_RegExpDelete(JSContext *ctx, JSValue this_val, JSValue arg) { JSRegExp *re = js_get_regexp(ctx, this_val, TRUE); JSString *str; @@ -43968,7 +44176,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon if (ret >= 0) { if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - JS_NewInt32(ctx, 0)) < 0) + js_int32(0)) < 0) goto fail; } } else { @@ -43987,12 +44195,12 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon next_src_pos = end; if (!(re_flags & LRE_FLAG_GLOBAL)) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, - JS_NewInt32(ctx, end)) < 0) + js_int32(end)) < 0) goto fail; break; } if (end == start) { - if (!(re_flags & LRE_FLAG_UTF16) || (unsigned)end >= str->len || !str->is_wide_char) { + if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= str->len || !str->is_wide_char) { end++; } else { string_getc(str, &end); @@ -44012,7 +44220,7 @@ fail: return JS_EXCEPTION; } -static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s) +static JSValue JS_RegExpExec(JSContext *ctx, JSValue r, JSValue s) { JSValue method, ret; @@ -44033,21 +44241,8 @@ 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) +static JSValue js_regexp_test(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val; BOOL ret; @@ -44057,14 +44252,14 @@ static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; ret = !JS_IsNull(val); JS_FreeValue(ctx, val); - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // [Symbol.match](str) - JSValueConst rx = this_val; + JSValue rx = this_val; JSValue A, S, flags, result, matchStr; int global, n, fullUnicode, isEmpty; JSString *p; @@ -44097,7 +44292,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, if (fullUnicode < 0) goto exception; - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) goto exception; A = JS_NewArray(ctx); if (JS_IsException(A)) @@ -44123,7 +44318,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_NewInt64(ctx, nextIndex)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) goto exception; } } @@ -44164,7 +44359,7 @@ static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val) } } -static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -44176,12 +44371,12 @@ 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, + JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic) { JSRegExpStringIteratorData *it; - JSValueConst R, S; + JSValue R, S; JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED; JSString *sp; @@ -44212,8 +44407,7 @@ 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_NewInt64(ctx, nextIndex)) < 0) + if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) goto exception; } JS_FreeValue(ctx, matchStr); @@ -44229,17 +44423,17 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx, return JS_EXCEPTION; } -static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // [Symbol.matchAll](str) - JSValueConst R = this_val; + JSValue R = this_val; JSValue S, C, flags, matcher, iter; - JSValueConst args[2]; + JSValue args[2]; JSString *strp; int64_t lastIndex; JSRegExpStringIteratorData *it; - + if (!JS_IsObject(R)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -44247,7 +44441,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, flags = JS_UNDEFINED; matcher = JS_UNDEFINED; iter = JS_UNDEFINED; - + S = JS_ToString(ctx, argv[0]); if (JS_IsException(S)) goto exception; @@ -44265,10 +44459,9 @@ 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_NewInt64(ctx, lastIndex)) < 0) + if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, js_int64(lastIndex)) < 0) goto exception; - + iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR); if (JS_IsException(iter)) goto exception; @@ -44281,7 +44474,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, it->global = string_indexof_char(strp, 'g', 0) >= 0; it->unicode = string_indexof_char(strp, 'u', 0) >= 0; it->done = FALSE; - JS_SetOpaque(iter, it); + JS_SetOpaqueInternal(iter, it); JS_FreeValue(ctx, C); JS_FreeValue(ctx, flags); @@ -44355,7 +44548,7 @@ static int value_buffer_append(ValueBuffer *b, JSValue val) return 0; } -static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx) +static int js_is_standard_regexp(JSContext *ctx, JSValue rx) { JSValue val; int res; @@ -44377,12 +44570,12 @@ static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx) return res; } -static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // [Symbol.replace](str, rep) - JSValueConst rx = this_val, rep = argv[1]; - JSValueConst args[6]; + JSValue rx = this_val, rep = argv[1]; + JSValue args[6]; JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res; JSString *p, *sp, *rp; StringBuffer b_s, *b = &b_s; @@ -44407,7 +44600,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, str = JS_ToString(ctx, argv[0]); if (JS_IsException(str)) goto exception; - + sp = JS_VALUE_GET_STRING(str); rp = NULL; functionalReplace = JS_IsFunction(ctx, rep); @@ -44433,7 +44626,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, 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_NewInt32(ctx, 0)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) goto exception; } @@ -44463,13 +44656,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_NewInt64(ctx, nextIndex)) < 0) + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int64(nextIndex)) < 0) goto exception; } } nextSourcePosition = 0; for(j = 0; j < results->len; j++) { - JSValueConst result; + JSValue result; result = results->arr[j]; if (js_get_length32(ctx, &nCaptures, result) < 0) goto exception; @@ -44489,7 +44682,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_DupValue(ctx, matched), + if (JS_DefinePropertyValueInt64(ctx, tab, 0, js_dup(matched), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; for(n = 1; n < nCaptures; n++) { @@ -44511,12 +44704,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_NewInt32(ctx, position), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_int32(position), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; - if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, str), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(str), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; if (!JS_IsUndefined(namedCaptures)) { - if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } args[0] = JS_UNDEFINED; @@ -44534,7 +44727,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, } args[0] = matched; args[1] = str; - args[2] = JS_NewInt32(ctx, position); + args[2] = js_int32(position); args[3] = tab; args[4] = namedCaptures1; args[5] = rep_val; @@ -44570,10 +44763,10 @@ done1: return res; } -static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst rx = this_val; + JSValue rx = this_val; JSValue str, previousLastIndex, currentLastIndex, result, index; if (!JS_IsObject(rx)) @@ -44590,8 +44783,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_NewInt32(ctx, 0))) { - if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) { + if (!js_same_value(ctx, previousLastIndex, js_int32(0))) { + if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) { goto exception; } } @@ -44613,7 +44806,7 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, currentLastIndex); if (JS_IsNull(result)) { - return JS_NewInt32(ctx, -1); + return js_int32(-1); } else { index = JS_GetProperty(ctx, result, JS_ATOM_index); JS_FreeValue(ctx, result); @@ -44628,12 +44821,12 @@ exception: return JS_EXCEPTION; } -static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // [Symbol.split](str, limit) - JSValueConst rx = this_val; - JSValueConst args[2]; + JSValue rx = this_val; + JSValue args[2]; JSValue str, ctor, splitter, A, flags, z, sub; JSString *strp; uint32_t lim, size, p, q; @@ -44693,9 +44886,9 @@ 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_NewInt32(ctx, q)) < 0) + if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, js_int32(q)) < 0) goto exception; - JS_FreeValue(ctx, z); + JS_FreeValue(ctx, z); z = JS_RegExpExec(ctx, splitter, str); if (JS_IsException(z)) goto exception; @@ -44721,9 +44914,14 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &numberOfCaptures, z)) goto exception; for(i = 1; i < numberOfCaptures; i++) { - sub = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, z, i)); + 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) @@ -44750,14 +44948,13 @@ done: JS_FreeValue(ctx, ctor); JS_FreeValue(ctx, splitter); JS_FreeValue(ctx, flags); - JS_FreeValue(ctx, z); + JS_FreeValue(ctx, z); return A; } 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[] = { @@ -44767,7 +44964,8 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, LRE_FLAG_IGNORECASE ), JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, LRE_FLAG_MULTILINE ), JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, LRE_FLAG_DOTALL ), - JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UTF16 ), + JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE ), + JS_CGETSET_MAGIC_DEF("unicodeSets", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE_SETS ), JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, LRE_FLAG_STICKY ), JS_CGETSET_MAGIC_DEF("hasIndices", js_regexp_get_flag, NULL, LRE_FLAG_INDICES ), JS_CFUNC_DEF("exec", 1, js_regexp_exec ), @@ -44779,8 +44977,6 @@ 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[] = { @@ -44795,7 +44991,7 @@ void JS_AddIntrinsicRegExpCompiler(JSContext *ctx) void JS_AddIntrinsicRegExp(JSContext *ctx) { - JSValueConst obj; + JSValue obj; JS_AddIntrinsicRegExpCompiler(ctx); @@ -44804,11 +45000,11 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) countof(js_regexp_proto_funcs)); obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2, ctx->class_proto[JS_CLASS_REGEXP]); - ctx->regexp_ctor = JS_DupValue(ctx, obj); + ctx->regexp_ctor = js_dup(obj); JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs)); ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = - JS_NewObjectProto(ctx, ctx->iterator_proto); + 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)); @@ -44816,15 +45012,6 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) /* 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; @@ -44836,7 +45023,7 @@ static JSValue json_parse_value(JSParseState *s) { JSValue prop_val; JSAtom prop_name; - + if (json_next_token(s)) goto fail; val = JS_NewObject(ctx); @@ -44848,15 +45035,17 @@ 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 { - js_parse_error(s, "expecting property name"); + json_parse_error(s, s->token.ptr, "Expected property name or '}'"); goto fail; } if (json_next_token(s)) goto fail1; - if (json_parse_expect(s, ':')) + if (s->token.val != ':') { + json_parse_error(s, s->token.ptr, "Expected ':' after property name"); + goto fail1; + } + if (json_next_token(s)) goto fail1; prop_val = json_parse_value(s); if (JS_IsException(prop_val)) { @@ -44870,15 +45059,17 @@ 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_parse_expect(s, '}')) + if (json_next_token(s)) goto fail; } break; @@ -44893,29 +45084,29 @@ static JSValue json_parse_value(JSParseState *s) if (JS_IsException(val)) goto fail; if (s->token.val != ']') { - idx = 0; - for(;;) { + for(idx = 0;; idx++) { 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_parse_expect(s, ']')) + if (json_next_token(s)) goto fail; } break; case TOK_STRING: - val = JS_DupValue(ctx, s->token.u.str.str); + val = js_dup(s->token.u.str.str); if (json_next_token(s)) goto fail; break; @@ -44927,7 +45118,7 @@ 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_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true)); + val = js_bool(s->token.u.ident.atom == JS_ATOM_true); } else if (s->token.u.ident.atom == JS_ATOM_null) { val = JS_NULL; } else { @@ -44939,7 +45130,7 @@ static JSValue json_parse_value(JSParseState *s) default: def_token: if (s->token.val == TOK_EOF) { - js_parse_error(s, "unexpected end of input"); + js_parse_error(s, "Unexpected end of JSON input"); } else { js_parse_error(s, "unexpected token: '%.*s'", (int)(s->buf_ptr - s->token.ptr), s->token.ptr); @@ -44952,14 +45143,13 @@ static JSValue json_parse_value(JSParseState *s) return JS_EXCEPTION; } -JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, - const char *filename, int flags) +/* '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) { JSParseState s1, *s = &s1; JSValue val = JS_UNDEFINED; 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); @@ -44976,17 +45166,11 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, 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) +static JSValue internalize_json_property(JSContext *ctx, JSValue holder, + JSAtom name, JSValue reviver) { JSValue val, new_el, name_val, res; - JSValueConst args[2]; + JSValue args[2]; int ret, is_array; uint32_t i, len = 0; JSAtom prop; @@ -45051,11 +45235,11 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, return JS_EXCEPTION; } -static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_json_parse(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj, root; - JSValueConst reviver; + JSValue reviver; const char *str; size_t len; @@ -45086,7 +45270,7 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val, } typedef struct JSONStringifyContext { - JSValueConst replacer_func; + JSValue replacer_func; JSValue stack; JSValue property_list; JSValue gap; @@ -45101,27 +45285,25 @@ static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) { } static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, - JSValueConst holder, JSValue val, JSValueConst key) + JSValue holder, JSValue val, JSValue key) { JSValue v; - JSValueConst args[2]; + JSValue args[2]; - if (JS_IsObject(val) || - JS_IsBigInt(ctx, val) /* XXX: probably useless */ - ) { - 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_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; @@ -45140,9 +45322,6 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, case JS_TAG_STRING: case JS_TAG_INT: case JS_TAG_FLOAT64: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif case JS_TAG_BOOL: case JS_TAG_NULL: case JS_TAG_BIG_INT: @@ -45160,74 +45339,60 @@ exception: } static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, - JSValueConst holder, JSValue val, - JSValueConst indent) + JSValue holder, JSValue val, + JSValue indent) { JSValue indent1, sep, sep1, tab, v, prop; JSObject *p; int64_t i, len; int cl, ret; BOOL has_content; - + indent1 = JS_UNDEFINED; sep = JS_UNDEFINED; sep1 = JS_UNDEFINED; tab = JS_UNDEFINED; prop = JS_UNDEFINED; - switch (JS_VALUE_GET_NORM_TAG(val)) { - case JS_TAG_OBJECT: + if (JS_IsObject(val)) { p = JS_VALUE_GET_OBJ(val); cl = p->class_id; if (cl == JS_CLASS_STRING) { val = JS_ToStringFree(ctx, val); if (JS_IsException(val)) goto exception; - val = JS_ToQuotedStringFree(ctx, val); - if (JS_IsException(val)) - goto exception; - return string_buffer_concat_value_free(jsc->b, val); + goto concat_primitive; } else if (cl == JS_CLASS_NUMBER) { val = JS_ToNumberFree(ctx, val); if (JS_IsException(val)) goto exception; - return string_buffer_concat_value_free(jsc->b, val); - } else if (cl == JS_CLASS_BOOLEAN) { - ret = string_buffer_concat_value(jsc->b, p->u.object_data); - JS_FreeValue(ctx, val); - return ret; - } else -#ifdef CONFIG_BIGNUM - if (cl == JS_CLASS_BIG_FLOAT) { - return string_buffer_concat_value_free(jsc->b, val); - } else -#endif - if (cl == JS_CLASS_BIG_INT) { - JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify"); - 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)); + goto concat_primitive; } - v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val); + v = js_array_includes(ctx, jsc->stack, 1, &val); if (JS_IsException(v)) goto exception; if (JS_ToBoolFree(ctx, v)) { JS_ThrowTypeError(ctx, "circular reference"); goto exception; } - indent1 = JS_ConcatString(ctx, JS_DupValue(ctx, indent), JS_DupValue(ctx, jsc->gap)); + indent1 = JS_ConcatString(ctx, js_dup(indent), js_dup(jsc->gap)); if (JS_IsException(indent1)) goto exception; if (!JS_IsEmptyString(jsc->gap)) { - sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), ""); + sep = JS_ConcatString3(ctx, "\n", js_dup(indent1), ""); if (JS_IsException(sep)) goto exception; - sep1 = JS_NewString(ctx, " "); + sep1 = js_new_string8(ctx, " "); if (JS_IsException(sep1)) goto exception; } else { - sep = JS_DupValue(ctx, jsc->empty); - sep1 = JS_DupValue(ctx, jsc->empty); + sep = js_dup(jsc->empty); + sep1 = js_dup(jsc->empty); } - v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0); + v = js_array_push(ctx, jsc->stack, 1, &val, 0); if (check_exception_free(ctx, v)) goto exception; ret = JS_IsArray(ctx, val); @@ -45245,7 +45410,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_NewInt64(ctx, i)); + prop = JS_ToStringFree(ctx, js_int64(i)); if (JS_IsException(prop)) goto exception; v = js_json_check(ctx, jsc, val, v, prop); @@ -45265,9 +45430,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, string_buffer_putc8(jsc->b, ']'); } else { if (!JS_IsUndefined(jsc->property_list)) - tab = JS_DupValue(ctx, jsc->property_list); + tab = js_dup(jsc->property_list); else - tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY); + tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY); if (JS_IsException(tab)) goto exception; if (js_get_length64(ctx, &len, tab)) @@ -45279,7 +45444,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, prop = JS_GetPropertyInt64(ctx, tab, i); if (JS_IsException(prop)) goto exception; - v = JS_GetPropertyValue(ctx, val, JS_DupValue(ctx, prop)); + v = JS_GetPropertyValue(ctx, val, js_dup(prop)); if (JS_IsException(v)) goto exception; v = js_json_check(ctx, jsc, val, v, prop); @@ -45317,6 +45482,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, JS_FreeValue(ctx, indent1); JS_FreeValue(ctx, prop); return 0; + } + concat_primitive: + switch (JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_STRING: val = JS_ToQuotedStringFree(ctx, val); if (JS_IsException(val)) @@ -45328,21 +45496,18 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, } goto concat_value; case JS_TAG_INT: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif case JS_TAG_BOOL: case JS_TAG_NULL: concat_value: return string_buffer_concat_value_free(jsc->b, val); case JS_TAG_BIG_INT: - JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify"); + JS_ThrowTypeError(ctx, "BigInt are forbidden in JSON.stringify"); goto exception; default: JS_FreeValue(ctx, val); return 0; } - + exception: JS_FreeValue(ctx, val); JS_FreeValue(ctx, tab); @@ -45353,8 +45518,8 @@ exception: return -1; } -JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, - JSValueConst replacer, JSValueConst space0) +JSValue JS_JSONStringify(JSContext *ctx, JSValue obj, + JSValue replacer, JSValue space0) { StringBuffer b_s; JSONStringifyContext jsc_s, *jsc = &jsc_s; @@ -45413,7 +45578,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, continue; } present = js_array_includes(ctx, jsc->property_list, - 1, (JSValueConst *)&v); + 1, &v); if (JS_IsException(present)) { JS_FreeValue(ctx, v); goto exception; @@ -45426,7 +45591,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, } } } - space = JS_DupValue(ctx, space0); + space = js_dup(space0); if (JS_IsObject(space)) { JSObject *p = JS_VALUE_GET_OBJ(space); if (p->class_id == JS_CLASS_NUMBER) { @@ -45448,7 +45613,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, JSString *p = JS_VALUE_GET_STRING(space); jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10)); } else { - jsc->gap = JS_DupValue(ctx, jsc->empty); + jsc->gap = js_dup(jsc->empty); } JS_FreeValue(ctx, space); if (JS_IsException(jsc->gap)) @@ -45457,10 +45622,10 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, if (JS_IsException(wrapper)) goto exception; if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string, - JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0) + js_dup(obj), JS_PROP_C_W_E) < 0) goto exception; - val = JS_DupValue(ctx, obj); - + val = js_dup(obj); + val = js_json_check(ctx, jsc, wrapper, val, jsc->empty); if (JS_IsException(val)) goto exception; @@ -45487,8 +45652,8 @@ done: return ret; } -static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_json_stringify(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // stringify(val, replacer, space) return JS_JSONStringify(ctx, argv[0], argv[1], argv[2]); @@ -45512,16 +45677,16 @@ void JS_AddIntrinsicJSON(JSContext *ctx) /* Reflect */ -static JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_apply(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 2); } -static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_construct(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst func, array_arg, new_target; + JSValue func, array_arg, new_target; JSValue *tab, ret; uint32_t len; @@ -45537,15 +45702,15 @@ 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, (JSValueConst *)tab); + ret = JS_CallConstructor2(ctx, func, new_target, len, tab); free_arg_list(ctx, tab, len); return ret; } -static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj; + JSValue obj; JSAtom atom; int ret; @@ -45560,13 +45725,13 @@ static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_get(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj, prop, receiver; + JSValue obj, prop, receiver; JSAtom atom; JSValue ret; @@ -45586,10 +45751,10 @@ static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_has(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj, prop; + JSValue obj, prop; JSAtom atom; int ret; @@ -45605,13 +45770,13 @@ static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_set(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj, prop, val, receiver; + JSValue obj, prop, val, receiver; int ret; JSAtom atom; @@ -45627,28 +45792,28 @@ 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_SetPropertyInternal(ctx, obj, atom, - JS_DupValue(ctx, val), receiver, 0); + ret = JS_SetPropertyInternal2(ctx, obj, atom, js_dup(val), receiver, + 0, NULL); JS_FreeAtom(ctx, atom); if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { int ret; ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE); if (ret < 0) return JS_EXCEPTION; else - return JS_NewBool(ctx, ret); + return js_bool(ret); } -static JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_reflect_ownKeys(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -45690,7 +45855,7 @@ static void js_proxy_finalizer(JSRuntime *rt, JSValue val) } } -static void js_proxy_mark(JSRuntime *rt, JSValueConst val, +static void js_proxy_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY); @@ -45706,7 +45871,7 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx) } static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, - JSValueConst obj, JSAtom name) + JSValue obj, JSAtom name) { JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); JSValue method; @@ -45716,7 +45881,7 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, JS_ThrowStackOverflow(ctx); return NULL; } - + /* 's' should never be NULL */ if (s->is_revoked) { JS_ThrowTypeErrorRevokedProxy(ctx); @@ -45731,7 +45896,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_getPrototypeOf(JSContext *ctx, JSValue obj) { JSProxyData *s; JSValue method, ret, proto1; @@ -45742,7 +45907,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, (JSValueConst *)&s->target); + ret = JS_CallFree(ctx, method, s->handler, 1, &s->target); if (JS_IsException(ret)) return ret; if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL && @@ -45772,12 +45937,12 @@ 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_setPrototypeOf(JSContext *ctx, JSValue obj, + JSValue proto_val, BOOL throw_flag) { JSProxyData *s; JSValue method, ret, proto1; - JSValueConst args[2]; + JSValue args[2]; BOOL res; int res2; @@ -45817,7 +45982,7 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, return TRUE; } -static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj) +static int js_proxy_isExtensible(JSContext *ctx, JSValue obj) { JSProxyData *s; JSValue method, ret; @@ -45829,7 +45994,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, (JSValueConst *)&s->target); + ret = JS_CallFree(ctx, method, s->handler, 1, &s->target); if (JS_IsException(ret)) return -1; res = JS_ToBoolFree(ctx, ret); @@ -45843,7 +46008,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj) return res; } -static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj) +static int js_proxy_preventExtensions(JSContext *ctx, JSValue obj) { JSProxyData *s; JSValue method, ret; @@ -45855,7 +46020,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, (JSValueConst *)&s->target); + ret = JS_CallFree(ctx, method, s->handler, 1, &s->target); if (JS_IsException(ret)) return -1; res = JS_ToBoolFree(ctx, ret); @@ -45871,13 +46036,13 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj) return res; } -static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) +static int js_proxy_has(JSContext *ctx, JSValue obj, JSAtom atom) { JSProxyData *s; JSValue method, ret1, atom_val; int ret, res; JSObject *p; - JSValueConst args[2]; + JSValue args[2]; BOOL res2; s = get_proxy_method(ctx, &method, obj, JS_ATOM_has); @@ -45915,13 +46080,13 @@ static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) return ret; } -static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst receiver) +static JSValue js_proxy_get(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue receiver) { JSProxyData *s; JSValue method, ret, atom_val; int res; - JSValueConst args[3]; + JSValue args[3]; JSPropertyDescriptor desc; s = get_proxy_method(ctx, &method, obj, JS_ATOM_get); @@ -45943,8 +46108,10 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, if (JS_IsException(ret)) return JS_EXCEPTION; res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); - if (res < 0) + if (res < 0) { + JS_FreeValue(ctx, ret); return JS_EXCEPTION; + } if (res) { if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) { if (!js_same_value(ctx, desc.value, ret)) { @@ -45963,21 +46130,21 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, return ret; } -static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst value, JSValueConst receiver, int flags) +static int js_proxy_set(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue value, JSValue receiver, int flags) { JSProxyData *s; JSValue method, ret1, atom_val; int ret, res; - JSValueConst args[4]; + JSValue args[4]; s = get_proxy_method(ctx, &method, obj, JS_ATOM_set); if (!s) return -1; if (JS_IsUndefined(method)) { - return JS_SetPropertyInternal(ctx, s->target, atom, - JS_DupValue(ctx, value), receiver, - flags); + return JS_SetPropertyInternal2(ctx, s->target, atom, + js_dup(value), receiver, + flags, NULL); } atom_val = JS_AtomToValue(ctx, atom); if (JS_IsException(atom_val)) { @@ -46021,8 +46188,8 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, return ret; } -static JSValue js_create_desc(JSContext *ctx, JSValueConst val, - JSValueConst getter, JSValueConst setter, +static JSValue js_create_desc(JSContext *ctx, JSValue val, + JSValue getter, JSValue setter, int flags) { JSValue ret; @@ -46030,43 +46197,43 @@ 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_DupValue(ctx, getter), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(getter), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_SET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(setter), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_VALUE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val), + JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(val), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_WRITABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0), + js_bool(flags & JS_PROP_WRITABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_ENUMERABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0), + js_bool(flags & JS_PROP_ENUMERABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_CONFIGURABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0), + js_bool(flags & JS_PROP_CONFIGURABLE), JS_PROP_C_W_E); } return ret; } static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc, - JSValueConst obj, JSAtom prop) + JSValue obj, JSAtom prop) { JSProxyData *s; JSValue method, trap_result_obj, prop_val; int res, target_desc_ret, ret; JSObject *p; - JSValueConst args[2]; + JSValue args[2]; JSPropertyDescriptor result_desc, target_desc; s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor); @@ -46115,7 +46282,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc JS_FreeValue(ctx, trap_result_obj); if (res < 0) return -1; - + if (target_desc_ret) { /* convert result_desc.flags to defineProperty flags */ flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; @@ -46156,16 +46323,16 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc return ret; } -static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, +static int js_proxy_define_own_property(JSContext *ctx, JSValue obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags) { JSProxyData *s; JSValue method, ret1, prop_val, desc_val; int res, ret; JSObject *p; - JSValueConst args[3]; + JSValue args[3]; JSPropertyDescriptor desc; BOOL setting_not_configurable; @@ -46256,13 +46423,13 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, return 1; } -static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, +static int js_proxy_delete_property(JSContext *ctx, JSValue obj, JSAtom atom) { JSProxyData *s; JSValue method, ret, atom_val; int res, res2, is_extensible; - JSValueConst args[2]; + JSValue args[2]; s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty); if (!s) @@ -46321,7 +46488,7 @@ static int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom) static int js_proxy_get_own_property_names(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, - JSValueConst obj) + JSValue obj) { JSProxyData *s; JSValue method, prop_array, val; @@ -46339,7 +46506,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, (JSValueConst *)&s->target); + prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target); if (JS_IsException(prop_array)) return -1; tab = NULL; @@ -46436,13 +46603,13 @@ static int js_proxy_get_own_property_names(JSContext *ctx, return -1; } -static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_proxy_call_constructor(JSContext *ctx, JSValue func_obj, + JSValue new_target, + int argc, JSValue *argv) { JSProxyData *s; JSValue method, arg_array, ret; - JSValueConst args[3]; + JSValue args[3]; s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_construct); if (!s) @@ -46470,17 +46637,17 @@ static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj, return ret; } -static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags) +static JSValue js_proxy_call(JSContext *ctx, JSValue func_obj, + JSValue this_obj, + int argc, JSValue *argv, int flags) { JSProxyData *s; JSValue method, arg_array, ret; - JSValueConst args[3]; + JSValue args[3]; if (flags & JS_CALL_FLAG_CONSTRUCTOR) return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv); - + s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply); if (!s) return JS_EXCEPTION; @@ -46505,15 +46672,17 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, return ret; } -static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) +static int js_proxy_isArray(JSContext *ctx, JSValue 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; } + if (s->is_revoked) { JS_ThrowTypeErrorRevokedProxy(ctx); return -1; @@ -46531,10 +46700,10 @@ static const JSClassExoticMethods js_proxy_exotic_methods = { .set_property = js_proxy_set, }; -static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_proxy_constructor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst target, handler; + JSValue target, handler; JSValue obj; JSProxyData *s; @@ -46552,17 +46721,17 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - s->target = JS_DupValue(ctx, target); - s->handler = JS_DupValue(ctx, handler); + s->target = js_dup(target); + s->handler = js_dup(handler); s->is_func = JS_IsFunction(ctx, target); s->is_revoked = FALSE; - JS_SetOpaque(obj, s); + JS_SetOpaqueInternal(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, +static JSValue js_proxy_revoke(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY); @@ -46577,13 +46746,13 @@ static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, } static JSValue js_proxy_revoke_constructor(JSContext *ctx, - JSValueConst proxy_obj) + JSValue proxy_obj) { return JS_NewCFunctionData(ctx, js_proxy_revoke, 0, 0, 1, &proxy_obj); } -static JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_proxy_revocable(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue proxy_obj, revoke_obj = JS_UNDEFINED, obj; @@ -46637,8 +46806,8 @@ void JS_AddIntrinsicProxy(JSContext *ctx) /* Symbol */ -static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_symbol_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { JSValue str; JSString *p; @@ -46653,44 +46822,44 @@ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, return JS_EXCEPTION; p = JS_VALUE_GET_STRING(str); } - return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL); + return JS_NewSymbolInternal(ctx, p, JS_ATOM_TYPE_SYMBOL); } -static JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val) +static JSValue js_thisSymbolValue(JSContext *ctx, JSValue this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL) - return JS_DupValue(ctx, this_val); + return js_dup(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_DupValue(ctx, p->u.object_data); + return js_dup(p->u.object_data); } } return JS_ThrowTypeError(ctx, "not a symbol"); } -static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_symbol_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val, ret; val = js_thisSymbolValue(ctx, this_val); if (JS_IsException(val)) return val; /* XXX: use JS_ToStringInternal() with a flags */ - ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val); + ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val); JS_FreeValue(ctx, val); return ret; } -static JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_symbol_valueOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_thisSymbolValue(ctx, this_val); } -static JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val) +static JSValue js_symbol_get_description(JSContext *ctx, JSValue this_val) { JSValue val, ret; JSAtomStruct *p; @@ -46717,19 +46886,19 @@ static const JSCFunctionListEntry js_symbol_proto_funcs[] = { JS_CGETSET_DEF("description", js_symbol_get_description, NULL ), }; -static JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_symbol_for(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str; str = JS_ToString(ctx, argv[0]); if (JS_IsException(str)) return JS_EXCEPTION; - return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL); + return JS_NewSymbolInternal(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL); } -static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_symbol_keyFor(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSAtomStruct *p; @@ -46738,7 +46907,7 @@ 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_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + return js_dup(JS_MKPTR(JS_TAG_STRING, p)); } static const JSCFunctionListEntry js_symbol_funcs[] = { @@ -46752,7 +46921,6 @@ 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 JSMapRecord *next_weak_ref; struct list_head link; struct list_head hash_link; JSValue key; @@ -46772,12 +46940,12 @@ typedef struct JSMapState { #define MAGIC_SET (1 << 0) #define MAGIC_WEAK (1 << 1) -static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv, int magic) { JSMapState *s; JSValue obj, adder = JS_UNDEFINED, iter = JS_UNDEFINED, next_method = JS_UNDEFINED; - JSValueConst arr; + JSValue arr; BOOL is_set, is_weak; is_set = magic & MAGIC_SET; @@ -46790,7 +46958,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, goto fail; init_list_head(&s->records); s->is_weak = is_weak; - JS_SetOpaque(obj, s); + JS_SetOpaqueInternal(obj, s); s->hash_size = 1; s->hash_table = js_malloc(ctx, sizeof(s->hash_table[0]) * s->hash_size); if (!s->hash_table) @@ -46829,14 +46997,14 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, break; } if (is_set) { - ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item); + ret = JS_Call(ctx, adder, obj, 1, &item); if (JS_IsException(ret)) { JS_FreeValue(ctx, item); goto fail; } } else { JSValue key, value; - JSValueConst args[2]; + JSValue args[2]; key = JS_UNDEFINED; value = JS_UNDEFINED; if (!JS_IsObject(item)) { @@ -46883,23 +47051,24 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, } /* XXX: could normalize strings to speed up comparison */ -static JSValueConst map_normalize_key(JSContext *ctx, JSValueConst key) +static JSValue map_normalize_key(JSContext *ctx, JSValue key) { uint32_t tag = JS_VALUE_GET_TAG(key); /* convert -0.0 to +0.0 */ if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) { - key = JS_NewInt32(ctx, 0); + key = js_int32(0); } return key; } /* XXX: better hash ? */ -static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) +static uint32_t map_hash_key(JSContext *ctx, JSValue key) { uint32_t tag = JS_VALUE_GET_NORM_TAG(key); uint32_t h; double d; JSFloat64Union u; + bf_t *a; switch(tag) { case JS_TAG_BOOL: @@ -46913,8 +47082,12 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163; break; case JS_TAG_INT: - d = JS_VALUE_GET_INT(key) * 3163; + d = JS_VALUE_GET_INT(key); goto hash_float64; + case JS_TAG_BIG_INT: + a = JS_GetBigInt(key); + h = hash_string8((void *)a->tab, a->len * sizeof(*a->tab), 0); + break; case JS_TAG_FLOAT64: d = JS_VALUE_GET_FLOAT64(key); /* normalize the NaN */ @@ -46923,9 +47096,9 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) hash_float64: u.d = d; h = (u.u32[0] ^ u.u32[1]) * 3163; - break; + return h ^= JS_TAG_FLOAT64; default: - h = 0; /* XXX: bignum support */ + h = 0; break; } h ^= tag; @@ -46933,7 +47106,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) } static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s, - JSValueConst key) + JSValue key) { struct list_head *el; JSMapRecord *mr; @@ -46980,8 +47153,29 @@ static void map_hash_resize(JSContext *ctx, JSMapState *s) s->record_count_threshold = new_hash_size * 2; } +static JSWeakRefRecord **get_first_weak_ref(JSValue 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) + JSValue key) { uint32_t h; JSMapRecord *mr; @@ -46993,14 +47187,18 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s, mr->map = s; mr->empty = FALSE; if (s->is_weak) { - JSObject *p = JS_VALUE_GET_OBJ(key); - /* Add the weak reference */ - mr->next_weak_ref = p->first_weak_ref; - p->first_weak_ref = mr; + 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); } else { - JS_DupValue(ctx, key); + js_dup(key); } - mr->key = (JSValue)key; + mr->key = key; h = map_hash_key(ctx, key) & (s->hash_size - 1); list_add_tail(&mr->hash_link, &s->hash_table[h]); list_add_tail(&mr->link, &s->records); @@ -47015,21 +47213,20 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s, 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_weak_ref(JSRuntime *rt, JSMapRecord *mr) +static void delete_map_weak_ref(JSRuntime *rt, JSMapRecord *mr) { - JSMapRecord **pmr, *mr1; - JSObject *p; + JSWeakRefRecord **pwr, *wr; - p = JS_VALUE_GET_OBJ(mr->key); - pmr = &p->first_weak_ref; + pwr = get_first_weak_ref(mr->key); for(;;) { - mr1 = *pmr; - assert(mr1 != NULL); - if (mr1 == mr) + wr = *pwr; + assert(wr != NULL); + if (wr->kind == JS_WEAK_REF_KIND_MAP && wr->u.map_record == mr) break; - pmr = &mr1->next_weak_ref; + pwr = &wr->next_weak_ref; } - *pmr = mr1->next_weak_ref; + *pwr = wr->next_weak_ref; + js_free_rt(rt, wr); } static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) @@ -47038,7 +47235,7 @@ static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) return; list_del(&mr->hash_link); if (s->is_weak) { - delete_weak_ref(rt, mr); + delete_map_weak_ref(rt, mr); } else { JS_FreeValueRT(rt, mr->key); } @@ -47065,45 +47262,21 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr) } } -static void reset_weak_ref(JSRuntime *rt, JSObject *p) -{ - JSMapRecord *mr, *mr_next; - JSMapState *s; - - /* first pass to remove the records from the WeakMap/WeakSet - lists */ - for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) { - s = mr->map; - assert(s->is_weak); - assert(!mr->empty); /* no iterator on WeakMap/WeakSet */ - list_del(&mr->hash_link); - list_del(&mr->link); - } - - /* second pass to free the values to avoid modifying the weak - reference list while traversing it. */ - for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) { - mr_next = mr->next_weak_ref; - JS_FreeValueRT(rt, mr->value); - js_free_rt(rt, mr); - } - - p->first_weak_ref = NULL; /* fail safe */ -} - -static JSValue js_map_set(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_set(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; - JSValueConst key, value; + JSValue key, value; + int is_set; if (!s) return JS_EXCEPTION; + is_set = (magic & MAGIC_SET); key = map_normalize_key(ctx, argv[0]); - if (s->is_weak && !JS_IsObject(key)) - return JS_ThrowTypeErrorNotAnObject(ctx); - if (magic & MAGIC_SET) + 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) value = JS_UNDEFINED; else value = argv[1]; @@ -47115,16 +47288,16 @@ static JSValue js_map_set(JSContext *ctx, JSValueConst this_val, if (!mr) return JS_EXCEPTION; } - mr->value = JS_DupValue(ctx, value); - return JS_DupValue(ctx, this_val); + mr->value = js_dup(value); + return js_dup(this_val); } -static JSValue js_map_get(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_get(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; - JSValueConst key; + JSValue key; if (!s) return JS_EXCEPTION; @@ -47133,29 +47306,29 @@ static JSValue js_map_get(JSContext *ctx, JSValueConst this_val, if (!mr) return JS_UNDEFINED; else - return JS_DupValue(ctx, mr->value); + return js_dup(mr->value); } -static JSValue js_map_has(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_has(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; - JSValueConst key; + JSValue key; if (!s) return JS_EXCEPTION; key = map_normalize_key(ctx, argv[0]); mr = map_find_record(ctx, s, key); - return JS_NewBool(ctx, (mr != NULL)); + return js_bool(mr != NULL); } -static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_delete(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; - JSValueConst key; + JSValue key; if (!s) return JS_EXCEPTION; @@ -47167,8 +47340,8 @@ static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val, return JS_TRUE; } -static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_clear(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); struct list_head *el, *el1; @@ -47183,19 +47356,19 @@ static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_map_get_size(JSContext *ctx, JSValueConst this_val, int magic) +static JSValue js_map_get_size(JSContext *ctx, JSValue this_val, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); if (!s) return JS_EXCEPTION; - return JS_NewUint32(ctx, s->record_count); + return js_uint32(s->record_count); } -static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_map_forEach(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); - JSValueConst func, this_arg; + JSValue func, this_arg; JSValue ret, args[3]; struct list_head *el; JSMapRecord *mr; @@ -47217,13 +47390,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_DupValue(ctx, mr->key); + args[1] = js_dup(mr->key); if (magic) args[0] = args[1]; else - args[0] = JS_DupValue(ctx, mr->value); - args[2] = (JSValue)this_val; - ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args); + args[0] = js_dup(mr->value); + args[2] = this_val; + ret = JS_Call(ctx, func, this_arg, 3, args); JS_FreeValue(ctx, args[0]); if (!magic) JS_FreeValue(ctx, args[1]); @@ -47239,12 +47412,11 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_map) +static JSValue js_map_groupBy(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst cb, args[2]; - JSValue res, iter, next, groups, key, v, prop; - JSAtom key_atom = JS_ATOM_NULL; + JSValue cb, res, iter, next, groups, k, v, prop; + JSValue args[2]; int64_t idx; BOOL done; @@ -47257,29 +47429,20 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, if (JS_IsException(iter)) return JS_EXCEPTION; - key = JS_UNDEFINED; - key_atom = JS_ATOM_NULL; + 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; - if (is_map) { - groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0); - } else { - groups = JS_NewObjectProto(ctx, JS_NULL); - } + groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0); 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; @@ -47287,21 +47450,12 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, break; // v is JS_UNDEFINED args[0] = v; - args[1] = JS_NewInt64(ctx, idx); - key = JS_Call(ctx, cb, ctx->global_obj, 2, args); - if (JS_IsException(key)) - goto iterator_close_exception; + args[1] = js_int64(idx); + k = JS_Call(ctx, cb, ctx->global_obj, 2, args); + if (JS_IsException(k)) + goto exception; - 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); - } + prop = js_map_get(ctx, groups, 1, &k, 0); if (JS_IsException(prop)) goto exception; @@ -47309,33 +47463,24 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, prop = JS_NewArray(ctx); if (JS_IsException(prop)) goto exception; - 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; - } - } + 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); } - res = js_array_push(ctx, prop, 1, (JSValueConst *)&v, /*unshift*/0); + + res = js_array_push(ctx, prop, 1, &v, /*unshift*/0); if (JS_IsException(res)) goto exception; // res is an int64 JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, key); - JS_FreeAtom(ctx, key_atom); + JS_FreeValue(ctx, k); JS_FreeValue(ctx, v); prop = JS_UNDEFINED; - key = JS_UNDEFINED; - key_atom = JS_ATOM_NULL; + k = JS_UNDEFINED; v = JS_UNDEFINED; } @@ -47343,12 +47488,9 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, next); return groups; - iterator_close_exception: - JS_IteratorClose(ctx, iter, TRUE); - exception: - JS_FreeAtom(ctx, key_atom); +exception: JS_FreeValue(ctx, prop); - JS_FreeValue(ctx, key); + JS_FreeValue(ctx, k); JS_FreeValue(ctx, v); JS_FreeValue(ctx, groups); JS_FreeValue(ctx, iter); @@ -47372,7 +47514,7 @@ static void js_map_finalizer(JSRuntime *rt, JSValue val) mr = list_entry(el, JSMapRecord, link); if (!mr->empty) { if (s->is_weak) - delete_weak_ref(rt, mr); + delete_map_weak_ref(rt, mr); else JS_FreeValueRT(rt, mr->key); JS_FreeValueRT(rt, mr->value); @@ -47384,7 +47526,7 @@ 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_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); JSMapState *s; @@ -47428,7 +47570,7 @@ static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val) } } -static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_map_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -47440,8 +47582,8 @@ static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, } } -static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_create_map_iterator(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSIteratorKindEnum kind; JSMapState *s; @@ -47461,17 +47603,17 @@ static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, enum_obj); goto fail; } - it->obj = JS_DupValue(ctx, this_val); + it->obj = js_dup(this_val); it->kind = kind; it->cur_record = NULL; - JS_SetOpaque(enum_obj, it); + JS_SetOpaqueInternal(enum_obj, it); return enum_obj; fail: return JS_EXCEPTION; } -static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_map_iterator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, BOOL *pdone, int magic) { JSMapIteratorData *it; @@ -47519,24 +47661,700 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val, *pdone = FALSE; if (it->kind == JS_ITERATOR_KIND_KEY) { - return JS_DupValue(ctx, mr->key); + return js_dup(mr->key); } else { - JSValueConst args[2]; + JSValue args[2]; args[0] = mr->key; if (magic) args[1] = mr->key; else args[1] = mr->value; if (it->kind == JS_ITERATOR_KIND_VALUE) { - return JS_DupValue(ctx, args[1]); + return js_dup(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), 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) +{ + return js_map_write(s, map_state, MAGIC_SET); +} + +static int js_setlike_get_size(JSContext *ctx, JSValue setlike, int64_t *pout) +{ + JSMapState *s; + JSValue v; + double d; + + s = JS_GetOpaque(setlike, JS_CLASS_SET); + if (s) { + *pout = s->record_count; + } else { + v = JS_GetProperty(ctx, setlike, JS_ATOM_size); + if (JS_IsException(v)) + return -1; + if (JS_IsUndefined(v)) { + JS_ThrowTypeError(ctx, ".size is undefined"); + return -1; + } + if (JS_ToFloat64Free(ctx, &d, v) < 0) + return -1; + if (isnan(d)) { + JS_ThrowTypeError(ctx, ".size is not a number"); + return -1; + } + *pout = d; + } + return 0; +} + +static int js_setlike_get_has(JSContext *ctx, JSValue setlike, JSValue *pout) +{ + JSValue v; + + v = JS_GetProperty(ctx, setlike, JS_ATOM_has); + if (JS_IsException(v)) + return -1; + if (JS_IsUndefined(v)) { + JS_ThrowTypeError(ctx, ".has is undefined"); + return -1; + } + if (!JS_IsFunction(ctx, v)) { + JS_ThrowTypeError(ctx, ".has is not a function"); + JS_FreeValue(ctx, v); + return -1; + } + *pout = v; + return 0; +} + +static int js_setlike_get_keys(JSContext *ctx, JSValue setlike, JSValue *pout) +{ + JSValue v; + + v = JS_GetProperty(ctx, setlike, JS_ATOM_keys); + if (JS_IsException(v)) + return -1; + if (JS_IsUndefined(v)) { + JS_ThrowTypeError(ctx, ".keys is undefined"); + return -1; + } + if (!JS_IsFunction(ctx, v)) { + JS_ThrowTypeError(ctx, ".keys is not a function"); + JS_FreeValue(ctx, v); + return -1; + } + *pout = v; + return 0; +} + +static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue item, iter, keys, has, next, rv, rval; + BOOL done, found; + JSMapState *s; + int64_t size; + int ok; + + has = JS_UNDEFINED; + iter = JS_UNDEFINED; + keys = JS_UNDEFINED; + next = JS_UNDEFINED; + rval = JS_EXCEPTION; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + goto exception; + // order matters! + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + goto exception; + if (js_setlike_get_has(ctx, argv[0], &has) < 0) + goto exception; + if (js_setlike_get_keys(ctx, argv[0], &keys) < 0) + goto exception; + if (s->record_count > size) { + 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 = FALSE; + do { + item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); + 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)); + JS_FreeValue(ctx, item); + } while (!found); + } else { + iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); + if (JS_IsException(iter)) + goto exception; + 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; + rv = JS_Call(ctx, has, argv[0], 1, &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); + } + rval = !found ? JS_TRUE : JS_FALSE; +exception: + JS_FreeValue(ctx, has); + JS_FreeValue(ctx, keys); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + return rval; +} + +static JSValue js_set_isSubsetOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue item, iter, keys, has, next, rv, rval; + BOOL done, found; + JSMapState *s; + int64_t size; + int ok; + + has = JS_UNDEFINED; + iter = JS_UNDEFINED; + keys = JS_UNDEFINED; + next = JS_UNDEFINED; + rval = JS_EXCEPTION; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + goto exception; + // order matters! + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + goto exception; + if (js_setlike_get_has(ctx, argv[0], &has) < 0) + goto exception; + if (js_setlike_get_keys(ctx, argv[0], &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; + 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, argv[0], 1, &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); +fini: + rval = found ? JS_TRUE : JS_FALSE; +exception: + JS_FreeValue(ctx, has); + JS_FreeValue(ctx, keys); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + return rval; +} + +static JSValue js_set_isSupersetOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue item, iter, keys, has, next, rval; + BOOL done, found; + JSMapState *s; + int64_t size; + + has = JS_UNDEFINED; + iter = JS_UNDEFINED; + keys = JS_UNDEFINED; + next = JS_UNDEFINED; + rval = JS_EXCEPTION; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + goto exception; + // order matters! + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + goto exception; + if (js_setlike_get_has(ctx, argv[0], &has) < 0) + goto exception; + if (js_setlike_get_keys(ctx, argv[0], &keys) < 0) + goto exception; + found = FALSE; + if (s->record_count < size) + goto fini; + 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; + do { + item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); + 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)); + JS_FreeValue(ctx, item); + } while (found); +fini: + rval = found ? JS_TRUE : JS_FALSE; +exception: + JS_FreeValue(ctx, has); + JS_FreeValue(ctx, keys); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + return rval; +} + +static JSValue js_set_intersection(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue newset, item, iter, keys, has, next, rv; + JSMapState *s, *t; + JSMapRecord *mr; + int64_t size; + BOOL done; + int ok; + + has = JS_UNDEFINED; + iter = JS_UNDEFINED; + keys = JS_UNDEFINED; + next = JS_UNDEFINED; + newset = JS_UNDEFINED; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + goto exception; + // order matters! + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + goto exception; + if (js_setlike_get_has(ctx, argv[0], &has) < 0) + goto exception; + if (js_setlike_get_keys(ctx, argv[0], &keys) < 0) + goto exception; + if (s->record_count > size) { + 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_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 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); + if (JS_IsException(item)) + goto exception; + if (done) // item is JS_UNDEFINED + break; + item = map_normalize_key(ctx, item); + if (!map_find_record(ctx, s, item)) { + 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 { + JS_FreeValue(ctx, item); + goto exception; + } + } + } else { + iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); + if (JS_IsException(iter)) + goto exception; + newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); + if (JS_IsException(newset)) + goto exception; + t = JS_GetOpaque(newset, JS_CLASS_SET); + for (;;) { + 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, argv[0], 1, &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; + } + } + } + goto fini; +exception: + JS_FreeValue(ctx, newset); + newset = JS_EXCEPTION; +fini: + JS_FreeValue(ctx, has); + JS_FreeValue(ctx, keys); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + return newset; +} + +static JSValue js_set_difference(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue newset, item, iter, keys, has, next, rv; + JSMapState *s, *t; + JSMapRecord *mr; + int64_t size; + BOOL done; + int ok; + + has = JS_UNDEFINED; + iter = JS_UNDEFINED; + keys = JS_UNDEFINED; + next = JS_UNDEFINED; + newset = JS_UNDEFINED; + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + goto exception; + // order matters! + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + goto exception; + if (js_setlike_get_has(ctx, argv[0], &has) < 0) + goto exception; + if (js_setlike_get_keys(ctx, argv[0], &keys) < 0) + goto exception; + if (s->record_count > size) { + 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_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); + 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); + JS_FreeValue(ctx, item); + } + } else { + iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET); + if (JS_IsException(iter)) + goto exception; + newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET); + if (JS_IsException(newset)) + goto exception; + t = JS_GetOpaque(newset, JS_CLASS_SET); + for (;;) { + 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, argv[0], 1, &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; + } + } + } + goto fini; +exception: + JS_FreeValue(ctx, newset); + newset = JS_EXCEPTION; +fini: + JS_FreeValue(ctx, has); + JS_FreeValue(ctx, keys); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, next); + return newset; +} + +static JSValue js_set_symmetricDifference(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue newset, item, iter, next, rv; + struct list_head *el; + JSMapState *s, *t; + JSMapRecord *mr; + int64_t size; + BOOL done, present; + + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + // order matters! they're JS-observable side effects + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + return JS_EXCEPTION; + if (js_setlike_get_has(ctx, argv[0], &rv) < 0) + return JS_EXCEPTION; + JS_FreeValue(ctx, rv); + 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); + iter = JS_UNDEFINED; + next = JS_UNDEFINED; + // 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_GetProperty(ctx, argv[0], JS_ATOM_keys); + if (JS_IsException(iter)) + goto exception; + iter = JS_CallFree(ctx, iter, argv[0], 0, NULL); + if (JS_IsException(iter)) + goto exception; + next = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next)) + 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; + // note the subtlety here: due to mutating iterators, it's + // possible for keys to disappear during iteration; test262 + // still expects us to maintain insertion order though, so + // we first check |this|, then |new|; |new| is a copy of |this| + // - if item exists in |this|, delete (if it exists) from |new| + // - if item misses in |this| and |new|, add to |new| + // - if item exists in |new| but misses in |this|, *don't* add it, + // mutating iterator erased it + item = map_normalize_key(ctx, item); + 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); + 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); + goto exception; + } + mr->value = JS_UNDEFINED; + } + } + goto fini; +exception: + JS_FreeValue(ctx, newset); + newset = JS_EXCEPTION; +fini: + JS_FreeValue(ctx, next); + JS_FreeValue(ctx, iter); + return newset; +} + +static JSValue js_set_union(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue newset, item, iter, next, rv; + struct list_head *el; + JSMapState *s, *t; + JSMapRecord *mr; + int64_t size; + BOOL done; + + s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET); + if (!s) + return JS_EXCEPTION; + // order matters! they're JS-observable side effects + if (js_setlike_get_size(ctx, argv[0], &size) < 0) + return JS_EXCEPTION; + if (js_setlike_get_has(ctx, argv[0], &rv) < 0) + return JS_EXCEPTION; + JS_FreeValue(ctx, rv); + 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); + iter = JS_UNDEFINED; + next = JS_UNDEFINED; + 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_GetProperty(ctx, argv[0], JS_ATOM_keys); + if (JS_IsException(iter)) + goto exception; + iter = JS_CallFree(ctx, iter, argv[0], 0, NULL); + if (JS_IsException(iter)) + goto exception; + next = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next)) + 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, &item, MAGIC_SET); + JS_FreeValue(ctx, item); + if (JS_IsException(rv)) + goto exception; + JS_FreeValue(ctx, rv); + } + goto fini; +exception: + JS_FreeValue(ctx, newset); + newset = JS_EXCEPTION; +fini: + JS_FreeValue(ctx, next); + JS_FreeValue(ctx, iter); + return newset; +} + static const JSCFunctionListEntry js_map_funcs[] = { - JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 1 ), + JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ), + JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), +}; + +static const JSCFunctionListEntry js_set_funcs[] = { JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), }; @@ -47567,6 +48385,13 @@ static const JSCFunctionListEntry js_set_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, MAGIC_SET ), JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ), JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ), + JS_CFUNC_DEF("isDisjointFrom", 1, js_set_isDisjointFrom ), + JS_CFUNC_DEF("isSubsetOf", 1, js_set_isSubsetOf ), + JS_CFUNC_DEF("isSupersetOf", 1, js_set_isSupersetOf ), + JS_CFUNC_DEF("intersection", 1, js_set_intersection ), + JS_CFUNC_DEF("difference", 1, js_set_difference ), + JS_CFUNC_DEF("symmetricDifference", 1, js_set_symmetricDifference ), + JS_CFUNC_DEF("union", 1, js_set_union ), JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ), JS_ALIAS_DEF("keys", "values" ), JS_ALIAS_DEF("[Symbol.iterator]", "values" ), @@ -47621,22 +48446,24 @@ void JS_AddIntrinsicMapSet(JSContext *ctx) for(i = 0; i < 4; i++) { const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Map + i); - ctx->class_proto[JS_CLASS_MAP + i] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_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 (i < 2) { - JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs, - countof(js_map_funcs)); - } - JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[JS_CLASS_MAP + 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]); } for(i = 0; i < 2; i++) { ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] = - JS_NewObjectProto(ctx, ctx->iterator_proto); + 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]); @@ -47681,7 +48508,7 @@ typedef struct JSPromiseReactionData { JSValue handler; } JSPromiseReactionData; -JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise) + JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); if (!s) @@ -47698,7 +48525,7 @@ JSValue JS_PromiseResult(JSContext *ctx, JSValue promise) } static int js_create_resolving_functions(JSContext *ctx, JSValue *args, - JSValueConst promise); + JSValue promise); static void promise_reaction_data_free(JSRuntime *rt, JSPromiseReactionData *rd) @@ -47709,10 +48536,20 @@ static void promise_reaction_data_free(JSRuntime *rt, js_free_rt(rt, rd); } +#ifdef DUMP_PROMISE +#define promise_trace(ctx, ...) \ + do { \ + if (check_dump_flag(ctx->rt, DUMP_PROMISE)) \ + printf(__VA_ARGS__); \ + } while (0) +#else +#define promise_trace(...) +#endif + static JSValue promise_reaction_job(JSContext *ctx, int argc, - JSValueConst *argv) + JSValue *argv) { - JSValueConst handler, arg, func; + JSValue handler, arg, func; JSValue res, res2; BOOL is_reject; @@ -47720,15 +48557,14 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc, handler = argv[2]; is_reject = JS_ToBool(ctx, argv[3]); arg = argv[4]; -#ifdef DUMP_PROMISE - printf("promise_reaction_job: is_reject=%d\n", is_reject); -#endif + + promise_trace(ctx, "promise_reaction_job: is_reject=%d\n", is_reject); if (JS_IsUndefined(handler)) { if (is_reject) { - res = JS_Throw(ctx, JS_DupValue(ctx, arg)); + res = JS_Throw(ctx, js_dup(arg)); } else { - res = JS_DupValue(ctx, arg); + res = js_dup(arg); } } else { res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg); @@ -47742,7 +48578,7 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc, functions */ if (!JS_IsUndefined(func)) { res2 = JS_Call(ctx, func, JS_UNDEFINED, - 1, (JSValueConst *)&res); + 1, &res); } else { res2 = JS_UNDEFINED; } @@ -47759,21 +48595,21 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, rt->host_promise_rejection_tracker_opaque = opaque; } -static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, - JSValueConst value, BOOL is_reject) +static void fulfill_or_reject_promise(JSContext *ctx, JSValue promise, + JSValue value, BOOL is_reject) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); struct list_head *el, *el1; JSPromiseReactionData *rd; - JSValueConst args[5]; + JSValue args[5]; if (!s || s->promise_state != JS_PROMISE_PENDING) return; /* should never happen */ - set_value(ctx, &s->promise_result, JS_DupValue(ctx, value)); + set_value(ctx, &s->promise_result, js_dup(value)); s->promise_state = JS_PROMISE_FULFILLED + is_reject; -#ifdef DUMP_PROMISE - printf("fulfill_or_reject_promise: is_reject=%d\n", is_reject); -#endif + + promise_trace(ctx, "fulfill_or_reject_promise: is_reject=%d\n", is_reject); + if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { JSRuntime *rt = ctx->rt; if (rt->host_promise_rejection_tracker) { @@ -47787,7 +48623,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_NewBool(ctx, is_reject); + args[3] = js_bool(is_reject); args[4] = value; JS_EnqueueJob(ctx, promise_reaction_job, 5, args); list_del(&rd->link); @@ -47801,31 +48637,30 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, } } -static void reject_promise(JSContext *ctx, JSValueConst promise, - JSValueConst value) +static void reject_promise(JSContext *ctx, JSValue promise, + JSValue value) { fulfill_or_reject_promise(ctx, promise, value, TRUE); } static JSValue js_promise_resolve_thenable_job(JSContext *ctx, - int argc, JSValueConst *argv) + int argc, JSValue *argv) { - JSValueConst promise, thenable, then; + JSValue promise, thenable, then; JSValue args[2], res; -#ifdef DUMP_PROMISE - printf("js_promise_resolve_thenable_job\n"); -#endif + promise_trace(ctx, "js_promise_resolve_thenable_job\n"); + assert(argc == 3); promise = argv[0]; thenable = argv[1]; then = argv[2]; if (js_create_resolving_functions(ctx, args, promise) < 0) return JS_EXCEPTION; - res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args); + res = JS_Call(ctx, then, thenable, 2, args); if (JS_IsException(res)) { JSValue error = JS_GetException(ctx); - res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error); + res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error); JS_FreeValue(ctx, error); } JS_FreeValue(ctx, args[0]); @@ -47843,7 +48678,7 @@ static void js_promise_resolve_function_free_resolved(JSRuntime *rt, static int js_create_resolving_functions(JSContext *ctx, JSValue *resolving_funcs, - JSValueConst promise) + JSValue promise) { JSValue obj; @@ -47874,8 +48709,8 @@ static int js_create_resolving_functions(JSContext *ctx, } sr->ref_count++; s->presolved = sr; - s->promise = JS_DupValue(ctx, promise); - JS_SetOpaque(obj, s); + s->promise = js_dup(promise); + JS_SetOpaqueInternal(obj, s); js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1); resolving_funcs[i] = obj; } @@ -47893,7 +48728,7 @@ static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val) } } -static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, +static void js_promise_resolve_function_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data; @@ -47903,14 +48738,14 @@ static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, } static JSValue js_promise_resolve_function_call(JSContext *ctx, - JSValueConst func_obj, - JSValueConst this_val, - int argc, JSValueConst *argv, + JSValue func_obj, + JSValue this_val, + int argc, JSValue *argv, int flags) { JSObject *p = JS_VALUE_GET_OBJ(func_obj); JSPromiseFunctionData *s; - JSValueConst resolution, args[3]; + JSValue resolution, args[3]; JSValue then; BOOL is_reject; @@ -47924,9 +48759,11 @@ static JSValue js_promise_resolve_function_call(JSContext *ctx, else resolution = JS_UNDEFINED; #ifdef DUMP_PROMISE - printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject); - JS_DumpValue(ctx, resolution); - printf("\n"); + if (check_dump_flag(ctx->rt, DUMP_PROMISE)) { + printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject); + JS_DumpValue(ctx->rt, resolution); + printf("\n"); + } #endif if (is_reject || !JS_IsObject(resolution)) { goto done; @@ -47974,7 +48811,7 @@ static void js_promise_finalizer(JSRuntime *rt, JSValue val) js_free_rt(rt, s); } -static void js_promise_mark(JSRuntime *rt, JSValueConst val, +static void js_promise_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE); @@ -47995,10 +48832,10 @@ static void js_promise_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, s->promise_result, mark_func); } -static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_promise_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { - JSValueConst executor; + JSValue executor; JSValue obj; JSPromiseData *s; JSValue args[2], ret; @@ -48018,14 +48855,14 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, for(i = 0; i < 2; i++) init_list_head(&s->promise_reactions[i]); s->promise_result = JS_UNDEFINED; - JS_SetOpaque(obj, s); + JS_SetOpaqueInternal(obj, s); if (js_create_resolving_functions(ctx, args, obj)) goto fail; - ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, (JSValueConst *)args); + ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, args); if (JS_IsException(ret)) { JSValue ret2, error; error = JS_GetException(ctx); - ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error); + ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error); JS_FreeValue(ctx, error); if (JS_IsException(ret2)) goto fail1; @@ -48044,8 +48881,8 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, } static JSValue js_promise_executor(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, + JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { int i; @@ -48053,14 +48890,14 @@ static JSValue js_promise_executor(JSContext *ctx, for(i = 0; i < 2; i++) { if (!JS_IsUndefined(func_data[i])) return JS_ThrowTypeError(ctx, "resolving function already set"); - func_data[i] = JS_DupValue(ctx, argv[i]); + func_data[i] = js_dup(argv[i]); } return JS_UNDEFINED; } static JSValue js_promise_executor_new(JSContext *ctx) { - JSValueConst func_data[2]; + JSValue func_data[2]; func_data[0] = JS_UNDEFINED; func_data[1] = JS_UNDEFINED; @@ -48070,7 +48907,7 @@ static JSValue js_promise_executor_new(JSContext *ctx) static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, - JSValueConst ctor) + JSValue ctor) { JSValue executor, result_promise; JSCFunctionDataRecord *s; @@ -48082,10 +48919,10 @@ static JSValue js_new_promise_capability(JSContext *ctx, if (JS_IsUndefined(ctor)) { result_promise = js_promise_constructor(ctx, ctor, 1, - (JSValueConst *)&executor); + &executor); } else { result_promise = JS_CallConstructor(ctx, ctor, 1, - (JSValueConst *)&executor); + &executor); } if (JS_IsException(result_promise)) goto fail; @@ -48095,7 +48932,7 @@ static JSValue js_new_promise_capability(JSContext *ctx, goto fail; } for(i = 0; i < 2; i++) - resolving_funcs[i] = JS_DupValue(ctx, s->data[i]); + resolving_funcs[i] = js_dup(s->data[i]); JS_FreeValue(ctx, executor); return result_promise; fail: @@ -48109,8 +48946,8 @@ JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs) return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); } -static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_promise_resolve(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue result_promise, resolving_funcs[2], ret; BOOL is_reject = magic; @@ -48126,7 +48963,7 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, is_same = js_same_value(ctx, ctor, this_val); JS_FreeValue(ctx, ctor); if (is_same) - return JS_DupValue(ctx, argv[0]); + return js_dup(argv[0]); } result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); if (JS_IsException(result_promise)) @@ -48142,16 +48979,15 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, return result_promise; } -static JSValue js_promise_withResolvers(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_promise_withResolvers(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue result_promise, resolving_funcs[2], obj; if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); if (JS_IsException(result_promise)) - return result_promise; + return JS_EXCEPTION; obj = JS_NewObject(ctx); if (JS_IsException(obj)) { JS_FreeValue(ctx, resolving_funcs[0]); @@ -48165,8 +49001,36 @@ static JSValue js_promise_withResolvers(JSContext *ctx, return obj; } +static JSValue js_promise_try(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSValue result_promise, resolving_funcs[2], ret, ret2; + BOOL is_reject = 0; + + if (!JS_IsObject(this_val)) + return JS_ThrowTypeErrorNotAnObject(ctx); + result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); + if (JS_IsException(result_promise)) + return result_promise; + ret = JS_Call(ctx, argv[0], JS_UNDEFINED, argc - 1, argv + 1); + if (JS_IsException(ret)) { + is_reject = 1; + ret = JS_GetException(ctx); + } + ret2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, &ret); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + JS_FreeValue(ctx, ret); + if (JS_IsException(ret2)) { + JS_FreeValue(ctx, result_promise); + return ret2; + } + JS_FreeValue(ctx, ret2); + return result_promise; +} + static __exception int remainingElementsCount_add(JSContext *ctx, - JSValueConst resolve_element_env, + JSValue resolve_element_env, int addend) { JSValue val; @@ -48179,7 +49043,7 @@ static __exception int remainingElementsCount_add(JSContext *ctx, return -1; remainingElementsCount += addend; if (JS_SetPropertyUint32(ctx, resolve_element_env, 0, - JS_NewInt32(ctx, remainingElementsCount)) < 0) + js_int32(remainingElementsCount)) < 0) return -1; return (remainingElementsCount == 0); } @@ -48189,33 +49053,33 @@ static __exception int remainingElementsCount_add(JSContext *ctx, #define PROMISE_MAGIC_any 2 static JSValue js_promise_all_resolve_element(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, + JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { int resolve_type = magic & 3; int is_reject = magic & 4; 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]; + JSValue values = func_data[2]; + JSValue resolve = func_data[3]; + JSValue resolve_element_env = func_data[4]; JSValue ret, obj; int is_zero, index; - + if (JS_ToInt32(ctx, &index, func_data[1])) return JS_EXCEPTION; if (alreadyCalled) return JS_UNDEFINED; - func_data[0] = JS_NewBool(ctx, TRUE); + func_data[0] = js_bool(TRUE); if (resolve_type == PROMISE_MAGIC_allSettled) { JSValue str; - + obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; - str = JS_NewString(ctx, is_reject ? "rejected" : "fulfilled"); + str = js_new_string8(ctx, is_reject ? "rejected" : "fulfilled"); if (JS_IsException(str)) goto fail1; if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_status, @@ -48224,19 +49088,19 @@ 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_DupValue(ctx, argv[0]), + js_dup(argv[0]), JS_PROP_C_W_E) < 0) { fail1: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } } else { - obj = JS_DupValue(ctx, argv[0]); + obj = js_dup(argv[0]); } if (JS_DefinePropertyValueUint32(ctx, values, index, obj, JS_PROP_C_W_E) < 0) return JS_EXCEPTION; - + is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1); if (is_zero < 0) return JS_EXCEPTION; @@ -48246,10 +49110,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, (JSValueConst *)&error); + ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error); JS_FreeValue(ctx, error); } else { - ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values); + ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values); } if (JS_IsException(ret)) return ret; @@ -48259,17 +49123,17 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, } /* magic = 0: Promise.all 1: Promise.allSettled */ -static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_promise_all(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue result_promise, resolving_funcs[2], item, next_promise, ret; JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED; 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]; + JSValue then_args[2], resolve_element_data[5]; BOOL done; int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); - + if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); @@ -48285,7 +49149,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, fail_reject: error = JS_GetException(ctx); ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, - (JSValueConst *)&error); + &error); JS_FreeValue(ctx, error); if (JS_IsException(ret)) goto fail; @@ -48302,10 +49166,10 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto fail_reject; /* remainingElementsCount field */ if (JS_DefinePropertyValueUint32(ctx, resolve_element_env, 0, - JS_NewInt32(ctx, 1), + js_int32(1), JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) goto fail_reject; - + index = 0; for(;;) { /* XXX: conformance: should close the iterator if error on 'done' @@ -48315,16 +49179,16 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto fail_reject; if (done) break; - next_promise = JS_Call(ctx, promise_resolve, - this_val, 1, (JSValueConst *)&item); + next_promise = JS_Call(ctx, promise_resolve, + this_val, 1, &item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: JS_IteratorClose(ctx, iter, TRUE); goto fail_reject; } - resolve_element_data[0] = JS_NewBool(ctx, FALSE); - resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index); + resolve_element_data[0] = js_bool(FALSE); + resolve_element_data[1] = js_int32(index); resolve_element_data[2] = values; resolve_element_data[3] = resolving_funcs[is_promise_any]; resolve_element_data[4] = resolve_element_env; @@ -48335,7 +49199,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, next_promise); goto fail_reject1; } - + if (magic == PROMISE_MAGIC_allSettled) { reject_element = JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1, @@ -48349,9 +49213,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_DupValue(ctx, resolving_funcs[0]); + resolve_element = js_dup(resolving_funcs[0]); } else { - reject_element = JS_DupValue(ctx, resolving_funcs[1]); + reject_element = js_dup(resolving_funcs[1]); } if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) { @@ -48384,7 +49248,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, (JSValueConst *)&values); + 1, &values); if (check_exception_free(ctx, ret)) goto fail_reject; } @@ -48404,8 +49268,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto done; } -static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_promise_race(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue result_promise, resolving_funcs[2], item, next_promise, ret; JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED; @@ -48427,7 +49291,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, fail_reject: error = JS_GetException(ctx); ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, - (JSValueConst *)&error); + &error); JS_FreeValue(ctx, error); if (JS_IsException(ret)) goto fail; @@ -48446,7 +49310,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, if (done) break; next_promise = JS_Call(ctx, promise_resolve, - this_val, 1, (JSValueConst *)&item); + this_val, 1, &item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: @@ -48454,7 +49318,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, goto fail_reject; } ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2, - (JSValueConst *)resolving_funcs); + resolving_funcs); if (check_exception_free(ctx, ret)) goto fail_reject1; } @@ -48474,9 +49338,9 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, } static __exception int perform_promise_then(JSContext *ctx, - JSValueConst promise, - JSValueConst *resolve_reject, - JSValueConst *cap_resolving_funcs) + JSValue promise, + JSValue *resolve_reject, + JSValue *cap_resolving_funcs) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); JSPromiseReactionData *rd_array[2], *rd; @@ -48485,7 +49349,7 @@ static __exception int perform_promise_then(JSContext *ctx, rd_array[0] = NULL; rd_array[1] = NULL; for(i = 0; i < 2; i++) { - JSValueConst handler; + JSValue handler; rd = js_mallocz(ctx, sizeof(*rd)); if (!rd) { if (i == 1) @@ -48493,11 +49357,11 @@ static __exception int perform_promise_then(JSContext *ctx, return -1; } for(j = 0; j < 2; j++) - rd->resolving_funcs[j] = JS_DupValue(ctx, cap_resolving_funcs[j]); + rd->resolving_funcs[j] = js_dup(cap_resolving_funcs[j]); handler = resolve_reject[i]; if (!JS_IsFunction(ctx, handler)) handler = JS_UNDEFINED; - rd->handler = JS_DupValue(ctx, handler); + rd->handler = js_dup(handler); rd_array[i] = rd; } @@ -48505,7 +49369,7 @@ static __exception int perform_promise_then(JSContext *ctx, for(i = 0; i < 2; i++) list_add_tail(&rd_array[i]->link, &s->promise_reactions[i]); } else { - JSValueConst args[5]; + JSValue args[5]; if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { JSRuntime *rt = ctx->rt; if (rt->host_promise_rejection_tracker) { @@ -48518,7 +49382,7 @@ static __exception int perform_promise_then(JSContext *ctx, args[0] = rd->resolving_funcs[0]; args[1] = rd->resolving_funcs[1]; args[2] = rd->handler; - args[3] = JS_NewBool(ctx, i); + args[3] = js_bool(i); args[4] = s->promise_result; JS_EnqueueJob(ctx, promise_reaction_job, 5, args); for(i = 0; i < 2; i++) @@ -48528,8 +49392,8 @@ static __exception int perform_promise_then(JSContext *ctx, return 0; } -static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_promise_then(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue ctor, result_promise, resolving_funcs[2]; JSPromiseData *s; @@ -48547,7 +49411,7 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, if (JS_IsException(result_promise)) return result_promise; ret = perform_promise_then(ctx, this_val, argv, - (JSValueConst *)resolving_funcs); + resolving_funcs); for(i = 0; i < 2; i++) JS_FreeValue(ctx, resolving_funcs[i]); if (ret) { @@ -48557,41 +49421,41 @@ static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val, return result_promise; } -static JSValue js_promise_catch(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_promise_catch(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst args[2]; + JSValue args[2]; args[0] = JS_UNDEFINED; args[1] = argv[0]; return JS_Invoke(ctx, this_val, JS_ATOM_then, 2, args); } -static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { - return JS_DupValue(ctx, func_data[0]); + return js_dup(func_data[0]); } -static JSValue js_promise_finally_thrower(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_promise_finally_thrower(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { - return JS_Throw(ctx, JS_DupValue(ctx, func_data[0])); + return JS_Throw(ctx, js_dup(func_data[0])); } -static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_promise_then_finally_func(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { - JSValueConst ctor = func_data[0]; - JSValueConst onFinally = func_data[1]; + JSValue ctor = func_data[0]; + JSValue onFinally = func_data[1]; JSValue res, promise, ret, then_func; res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL); if (JS_IsException(res)) return res; - promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0); + promise = js_promise_resolve(ctx, ctor, 1, &res, 0); JS_FreeValue(ctx, res); if (JS_IsException(promise)) return promise; @@ -48606,26 +49470,26 @@ 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, (JSValueConst *)&then_func); + ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func); JS_FreeValue(ctx, then_func); return ret; } -static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_promise_finally(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst onFinally = argv[0]; + JSValue onFinally = argv[0]; JSValue ctor, ret; JSValue then_funcs[2]; - JSValueConst func_data[2]; + JSValue func_data[2]; int i; ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED); if (JS_IsException(ctor)) return ctor; if (!JS_IsFunction(ctx, onFinally)) { - then_funcs[0] = JS_DupValue(ctx, onFinally); - then_funcs[1] = JS_DupValue(ctx, onFinally); + then_funcs[0] = js_dup(onFinally); + then_funcs[1] = js_dup(onFinally); } else { func_data[0] = ctor; func_data[1] = onFinally; @@ -48640,7 +49504,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, (JSValueConst *)then_funcs); + ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, then_funcs); JS_FreeValue(ctx, then_funcs[0]); JS_FreeValue(ctx, then_funcs[1]); return ret; @@ -48652,6 +49516,7 @@ static const JSCFunctionListEntry js_promise_funcs[] = { JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ), JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ), JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ), + JS_CFUNC_DEF("try", 1, js_promise_try ), JS_CFUNC_DEF("race", 1, js_promise_race ), JS_CFUNC_DEF("withResolvers", 0, js_promise_withResolvers ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL), @@ -48670,20 +49535,20 @@ static const JSCFunctionListEntry js_async_function_proto_funcs[] = { }; static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, + JSValue this_val, + int argc, JSValue *argv, int magic, JSValue *func_data) { - return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), + 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]; + JSValue func_data[1]; - func_data[0] = (JSValueConst)JS_NewBool(ctx, done); + func_data[0] = js_bool(done); return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap, 1, 0, 1, func_data); } @@ -48712,7 +49577,7 @@ static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, JSValue val) } } -static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val, +static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSAsyncFromSyncIteratorData *s = @@ -48724,7 +49589,7 @@ static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val, } static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, - JSValueConst sync_iter) + JSValue sync_iter) { JSValue async_iter, next_method; JSAsyncFromSyncIteratorData *s; @@ -48743,14 +49608,14 @@ static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, JS_FreeValue(ctx, next_method); return JS_EXCEPTION; } - s->sync_iter = JS_DupValue(ctx, sync_iter); + s->sync_iter = js_dup(sync_iter); s->next_method = next_method; - JS_SetOpaque(async_iter, s); + JS_SetOpaqueInternal(async_iter, s); return async_iter; } -static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { JSValue promise, resolving_funcs[2], value, err, method; @@ -48768,7 +49633,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi } if (magic == GEN_MAGIC_NEXT) { - method = JS_DupValue(ctx, s->next_method); + method = js_dup(s->next_method); } else { method = JS_GetProperty(ctx, s->sync_iter, magic == GEN_MAGIC_RETURN ? JS_ATOM_return : @@ -48777,10 +49642,11 @@ 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_DupValue(ctx, argv[0]), TRUE); + err = js_create_iterator_result(ctx, js_dup(argv[0]), TRUE); is_reject = 0; } else { - err = JS_DupValue(ctx, argv[0]); + err = JS_MakeError(ctx, JS_TYPE_ERROR, "throw is not a method", + TRUE); is_reject = 1; } goto done_resolve; @@ -48806,7 +49672,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi is_reject = 1; done_resolve: res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, - 1, (JSValueConst *)&err); + 1, &err); JS_FreeValue(ctx, err); JS_FreeValue(ctx, res2); JS_FreeValue(ctx, resolving_funcs[0]); @@ -48818,7 +49684,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi int res; value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor, - 1, (JSValueConst *)&value, 0); + 1, &value, 0); if (JS_IsException(value_wrapper_promise)) { JS_FreeValue(ctx, value); goto reject; @@ -48834,8 +49700,8 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi resolve_reject[1] = JS_UNDEFINED; res = perform_promise_then(ctx, value_wrapper_promise, - (JSValueConst *)resolve_reject, - (JSValueConst *)resolving_funcs); + resolve_reject, + resolving_funcs); JS_FreeValue(ctx, resolve_reject[0]); JS_FreeValue(ctx, value_wrapper_promise); JS_FreeValue(ctx, resolving_funcs[0]); @@ -48910,16 +49776,20 @@ void JS_AddIntrinsicPromise(JSContext *ctx) countof(js_promise_proto_funcs)); obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1, JS_CFUNC_constructor, 0); - ctx->promise_ctor = JS_DupValue(ctx, obj1); + 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; + /* AsyncFunction */ ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); - obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor, + 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); @@ -48955,7 +49825,8 @@ void JS_AddIntrinsicPromise(JSContext *ctx) /* AsyncGeneratorFunction */ ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); - obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor, + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCFunction3(ctx, ft.generic, "AsyncGeneratorFunction", 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC_GENERATOR, @@ -49009,8 +49880,8 @@ static int hex_decode(JSContext *ctx, JSString *p, int k) { return c; } -static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int isComponent) +static JSValue js_global_decodeURI(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int isComponent) { JSValue str; StringBuffer b_s, *b = &b_s; @@ -49066,8 +49937,7 @@ static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val, } c = (c << 6) | (c1 & 0x3f); } - if (c < c_min || c > 0x10FFFF || - (c >= 0xd800 && c < 0xe000)) { + if (c < c_min || c > 0x10FFFF || is_surrogate(c)) { js_throw_URIError(ctx, "malformed UTF-8"); goto fail; } @@ -49121,8 +49991,8 @@ static int encodeURI_hex(StringBuffer *b, int c) { return string_buffer_write8(b, buf, n); } -static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, +static JSValue js_global_encodeURI(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int isComponent) { JSValue str; @@ -49142,21 +50012,21 @@ static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val, if (isURIUnescaped(c, isComponent)) { string_buffer_putc16(b, c); } else { - if (c >= 0xdc00 && c <= 0xdfff) { + if (is_lo_surrogate(c)) { js_throw_URIError(ctx, "invalid character"); goto fail; - } else if (c >= 0xd800 && c <= 0xdbff) { + } else if (is_hi_surrogate(c)) { if (k >= p->len) { js_throw_URIError(ctx, "expecting surrogate pair"); goto fail; } c1 = string_get(p, k); k++; - if (c1 < 0xdc00 || c1 > 0xdfff) { + if (!is_lo_surrogate(c1)) { js_throw_URIError(ctx, "expecting surrogate pair"); goto fail; } - c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; + c = from_surrogate(c, c1); } if (c < 0x80) { encodeURI_hex(b, c); @@ -49186,8 +50056,8 @@ fail: return JS_EXCEPTION; } -static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_global_escape(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str; StringBuffer b_s, *b = &b_s; @@ -49212,8 +50082,8 @@ static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val, return string_buffer_end(b); } -static JSValue js_global_unescape(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_global_unescape(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue str; StringBuffer b_s, *b = &b_s; @@ -49254,6 +50124,7 @@ 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 ), @@ -49262,8 +50133,9 @@ static const JSCFunctionListEntry js_global_funcs[] = { 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("NaN", NAN, 0 ), + JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc JS_PROP_UNDEFINED_DEF("undefined", 0 ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), }; /* Date */ @@ -49274,16 +50146,16 @@ static int64_t math_mod(int64_t a, int64_t b) { return m + (m < 0) * b; } -static int64_t floor_div(int64_t a, int64_t b) { +static int64_t floor_div_int64(int64_t a, int64_t b) { /* integer division rounding toward -Infinity */ int64_t m = a % b; return (a - (m + (m < 0) * b)) / b; } -static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); +static JSValue js_Date_parse(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); -static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val) +static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValue this_val) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(this_val); @@ -49294,22 +50166,22 @@ static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueCon return -1; } -static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double v) +static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValue this_val, double v) { if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { 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_NewFloat64(ctx, v); - return JS_DupValue(ctx, p->u.object_data); + p->u.object_data = js_float64(v); + return js_dup(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(y - 1969, 4) - - floor_div(y - 1901, 100) + floor_div(y - 1601, 400); + return 365 * (y - 1970) + floor_div_int64(y - 1969, 4) - + floor_div_int64(y - 1901, 100) + floor_div_int64(y - 1601, 400); } static int64_t days_in_year(int64_t y) { @@ -49319,7 +50191,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(d * 10000, 3652425) + 1970; + y = floor_div_int64(d * 10000, 3652425) + 1970; /* the initial approximation is very good, so only a few iterations are necessary */ for(;;) { @@ -49343,8 +50215,9 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; static char const day_names[] = "SunMonTueWedThuFriSat"; -static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, - double fields[9], int is_local, int force) +static __exception int get_date_fields(JSContext *ctx, JSValue obj, + 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; @@ -49357,7 +50230,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, return FALSE; /* NaN */ d = 0; /* initialize all fields to 0 */ } else { - d = dval; + d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */ if (is_local) { tz = -getTimezoneOffset(d); d += tz * 60000; @@ -49403,37 +50276,67 @@ static double time_clip(double t) { return NAN; } -/* The spec mandates the use of 'double' and it fixes the order +/* The spec mandates the use of 'double' and it specifies the order of the operations */ -static double set_date_fields(double fields[], int is_local) { - int64_t y; - double days, d, h, m1; - int i, m, md; - - m1 = fields[1]; - m = fmod(m1, 12); - if (m < 0) - m += 12; - y = (int64_t)(fields[0] + floor(m1 / 12)); - days = days_from_year(y); +static double set_date_fields(double fields[minimum_length(7)], int is_local) { + double y, m, dt, ym, mn, day, h, s, milli, time, tv; + int yi, mi, i; + int64_t days; + volatile double temp; /* enforce evaluation order */ - for(i = 0; i < m; i++) { - md = month_days[i]; + /* emulate 21.4.1.15 MakeDay ( year, month, date ) */ + y = fields[0]; + m = fields[1]; + dt = fields[2]; + ym = y + floor(m / 12); + mn = fmod(m, 12); + if (mn < 0) + mn += 12; + if (ym < -271821 || ym > 275760) + return NAN; + + yi = ym; + mi = mn; + days = days_from_year(yi); + for(i = 0; i < mi; i++) { + days += month_days[i]; if (i == 1) - md += days_in_year(y) - 365; - days += md; + days += days_in_year(yi) - 365; } - days += fields[2] - 1; - h = fields[3] * 3600000 + fields[4] * 60000 + - fields[5] * 1000 + fields[6]; - d = days * 86400000 + h; - if (is_local) - d += getTimezoneOffset(d) * 60000; - return time_clip(d); + day = days + dt - 1; + + /* emulate 21.4.1.14 MakeTime ( hour, min, sec, ms ) */ + h = fields[3]; + m = fields[4]; + s = fields[5]; + milli = fields[6]; + /* Use a volatile intermediary variable to ensure order of evaluation + * as specified in ECMA. This fixes a test262 error on + * test262/test/built-ins/Date/UTC/fp-evaluation-order.js. + * Without the volatile qualifier, the compile can generate code + * that performs the computation in a different order or with instructions + * that produce a different result such as FMA (float multiply and add). + */ + time = h * 3600000; + time += (temp = m * 60000); + time += (temp = s * 1000); + time += milli; + + /* emulate 21.4.1.16 MakeDate ( day, time ) */ + tv = (temp = day * 86400000) + time; /* prevent generation of FMA */ + if (!isfinite(tv)) + return NAN; + + /* adjust for local time and clip */ + if (is_local) { + int64_t ti = tv < INT64_MIN ? INT64_MIN : tv >= 0x1p63 ? INT64_MAX : (int64_t)tv; + tv += getTimezoneOffset(ti) * 60000; + } + return time_clip(tv); } -static JSValue get_date_field(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue get_date_field(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { // get_date_field(obj, n, is_local) double fields[9]; @@ -49450,11 +50353,11 @@ static JSValue get_date_field(JSContext *ctx, JSValueConst this_val, if (magic & 0x100) { // getYear fields[0] -= 1900; } - return JS_NewFloat64(ctx, fields[n]); + return js_number(fields[n]); } -static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue set_date_field(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { // _field(obj, first_field, end_field, args, is_local) double fields[9]; @@ -49479,9 +50382,13 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, res = FALSE; fields[first_field + i] = trunc(a); } - if (res && argc > 0) { + + if (!res) + return JS_NAN; + + if (argc > 0) d = set_date_fields(fields, is_local); - } + return JS_SetThisTimeValue(ctx, this_val, d); } @@ -49493,8 +50400,8 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, part: 1=date, 2=time 3=all XXX: should use a variant of strftime(). */ -static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue get_date_string(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { // _string(obj, fmt, part) char buf[64]; @@ -49512,7 +50419,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, if (fmt == 2) return JS_ThrowRangeError(ctx, "Date value is NaN"); else - return JS_NewString(ctx, "Invalid Date"); + return js_new_string8(ctx, "Invalid Date"); } y = fields[0]; @@ -49596,18 +50503,20 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, break; } } - return JS_NewStringLen(ctx, buf, pos); + if (!pos) { + // XXX: should throw exception? + return JS_AtomToString(ctx, JS_ATOM_empty_string); + } + return js_new_string8_len(ctx, buf, pos); } /* OS dependent: return the UTC time in ms since 1970. */ static int64_t date_now(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000); + return js__gettimeofday_us() / 1000; } -static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_date_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) { // Date(y, mon, d, h, m, s, ms) JSValue rv; @@ -49634,7 +50543,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, (JSValueConst *)&v); + dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v); JS_FreeValue(ctx, v); if (JS_IsException(dv)) return JS_EXCEPTION; @@ -49661,17 +50570,9 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target, val = (i == n) ? set_date_fields(fields, 1) : NAN; } 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_NewFloat64(ctx, val)); -#endif + JS_SetObjectData(ctx, rv, js_float64(val)); if (!JS_IsException(rv) && JS_IsUndefined(new_target)) { /* invoked as a function, return (new Date()).toString(); */ JSValue s; @@ -49682,8 +50583,8 @@ has_val: return rv; } -static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_Date_UTC(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // UTC(y, mon, d, h, m, s, ms) double fields[] = { 0, 0, 1, 0, 0, 0, 0 }; @@ -49704,312 +50605,479 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, if (i == 0 && fields[0] >= 0 && fields[0] < 100) fields[0] += 1900; } - return JS_NewFloat64(ctx, set_date_fields(fields, 0)); + return js_float64(set_date_fields(fields, 0)); } -static void string_skip_spaces(JSString *sp, int *pp) { - while (*pp < sp->len && string_get(sp, *pp) == ' ') +/* Date string parsing */ + +static BOOL string_skip_char(const uint8_t *sp, int *pp, int c) { + if (sp[*pp] == c) { *pp += 1; + return TRUE; + } else { + return FALSE; + } } -static void string_skip_non_spaces(JSString *sp, int *pp) { - while (*pp < sp->len && string_get(sp, *pp) != ' ') +/* skip spaces, update offset, return next char */ +static int string_skip_spaces(const uint8_t *sp, int *pp) { + int c; + while ((c = sp[*pp]) == ' ') *pp += 1; + return c; } -/* parse a numeric field with an optional sign if accept_sign is TRUE */ -static int string_get_digits(JSString *sp, int *pp, int64_t *pval) { - int64_t v = 0; +/* skip dashes dots and commas */ +static int string_skip_separators(const uint8_t *sp, int *pp) { + int c; + while ((c = sp[*pp]) == '-' || c == '/' || c == '.' || c == ',') + *pp += 1; + return c; +} + +/* skip a word, stop on spaces, digits and separators, update offset */ +static int string_skip_until(const uint8_t *sp, int *pp, const char *stoplist) { + int c; + while (!strchr(stoplist, c = sp[*pp])) + *pp += 1; + return c; +} + +/* parse a numeric field (max_digits = 0 -> no maximum) */ +static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval, + int min_digits, int max_digits) +{ + int v = 0; int c, p = *pp, p_start; - - if (p >= sp->len) - return -1; + p_start = p; - while (p < sp->len) { - c = string_get(sp, p); - if (!(c >= '0' && c <= '9')) { - if (p == p_start) - return -1; - else - break; - } + while ((c = sp[p]) >= '0' && c <= '9') { v = v * 10 + c - '0'; p++; + if (p - p_start == max_digits) + break; } + if (p - p_start < min_digits) + return FALSE; *pval = v; *pp = p; - return 0; + return TRUE; } -static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) { - int res, sgn, p = *pp; - - if (p >= sp->len) - return -1; +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; - sgn = string_get(sp, p); - if (sgn == '-' || sgn == '+') + c = sp[p]; + if (c == '.' || c == ',') { p++; - - res = string_get_digits(sp, &p, pval); - if (res == 0 && sgn == '-') { - if (*pval == 0) - return -1; // reject negative zero - *pval = -*pval; - } - *pp = p; - return res; -} - -/* parse a fixed width numeric field */ -static int string_get_fixed_width_digits(JSString *sp, int *pp, int n, int64_t *pval) { - int64_t v = 0; - int i, c, p = *pp; - - for(i = 0; i < n; i++) { - if (p >= sp->len) - return -1; - c = string_get(sp, p); - if (!(c >= '0' && c <= '9')) - return -1; - v = v * 10 + c - '0'; - p++; - } - *pval = v; - *pp = p; - return 0; -} - -static int string_get_milliseconds(JSString *sp, int *pp, int64_t *pval) { - /* parse milliseconds as a fractional part, round to nearest */ - /* XXX: the spec does not indicate which rounding should be used */ - int mul = 1000, ms = 0, p = *pp, c, p_start; - if (p >= sp->len) - return -1; - p_start = p; - while (p < sp->len) { - c = string_get(sp, p); - if (!(c >= '0' && c <= '9')) { - if (p == p_start) - return -1; - else + p_start = p; + while ((c = sp[p]) >= '0' && c <= '9') { + ms += (c - '0') * mul; + mul /= 10; + p++; + if (p - p_start == 9) break; } - if (mul == 1 && c >= '5') - ms += 1; - ms += (c - '0') * (mul /= 10); - p++; + if (p > p_start) { + /* only consume the separator if digits are present */ + *pval = ms; + *pp = p; + } } - *pval = ms; - *pp = p; - return 0; + return TRUE; } +static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) { + int tz = 0, sgn, hh, mm, p = *pp; -static int find_abbrev(JSString *sp, int p, const char *list, int count) { + sgn = sp[p++]; + if (sgn == '+' || sgn == '-') { + int n = p; + if (!string_get_digits(sp, &p, &hh, 1, 9)) + return FALSE; + n = p - n; + if (strict && n != 2 && n != 4) + return FALSE; + while (n > 4) { + n -= 2; + hh /= 100; + } + if (n > 2) { + mm = hh % 100; + 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 (hh > 23 || mm > 59) + return FALSE; + tz = hh * 60 + mm; + if (sgn != '+') + tz = -tz; + } else + if (sgn != 'Z') { + return FALSE; + } + *pp = p; + *tzp = tz; + return TRUE; +} + +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; + p++; + } + *pp = p; + return TRUE; +} + +static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) { int n, i; - if (p + 3 <= sp->len) { - for (n = 0; n < count; n++) { - for (i = 0; i < 3; i++) { - if (string_get(sp, p + i) != month_names[n * 3 + i]) - goto next; - } - return n; - next:; + for (n = 0; n < count; n++) { + for (i = 0;; i++) { + if (to_upper_ascii(sp[p + i]) != to_upper_ascii(list[n * 3 + i])) + break; + if (i == 2) + return n; } } return -1; } -static int string_get_month(JSString *sp, int *pp, int64_t *pval) { +static BOOL string_get_month(const uint8_t *sp, int *pp, int *pval) { int n; - string_skip_spaces(sp, pp); n = find_abbrev(sp, *pp, month_names, 12); if (n < 0) - return -1; + return FALSE; - *pval = n; + *pval = n + 1; *pp += 3; - return 0; + return TRUE; } -static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +/* parse toISOString format */ +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; + + /* 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; + if (sgn == '-') { + if (fields[0] == 0) + return FALSE; // reject -000000 + fields[0] = -fields[0]; + } + } else { + if (!string_get_digits(sp, &p, &fields[0], 4, 4)) + return FALSE; + } + if (string_skip_char(sp, &p, '-')) { + if (!string_get_digits(sp, &p, &fields[1], 2, 2)) /* month */ + return FALSE; + if (fields[1] < 1) + return FALSE; + fields[1] -= 1; + if (string_skip_char(sp, &p, '-')) { + if (!string_get_digits(sp, &p, &fields[2], 2, 2)) /* day */ + return FALSE; + if (fields[2] < 1) + return FALSE; + } + } + if (string_skip_char(sp, &p, 'T')) { + *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; + } + if (string_skip_char(sp, &p, ':')) { + if (!string_get_digits(sp, &p, &fields[5], 2, 2)) /* second */ + 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; + } + /* error if extraneous characters */ + return sp[p] == '\0'; +} + +static struct { + char name[6]; + int16_t offset; +} const js_tzabbr[] = { + { "GMT", 0 }, // Greenwich Mean Time + { "UTC", 0 }, // Coordinated Universal Time + { "UT", 0 }, // Universal Time + { "Z", 0 }, // Zulu Time + { "EDT", -4 * 60 }, // Eastern Daylight Time + { "EST", -5 * 60 }, // Eastern Standard Time + { "CDT", -5 * 60 }, // Central Daylight Time + { "CST", -6 * 60 }, // Central Standard Time + { "MDT", -6 * 60 }, // Mountain Daylight Time + { "MST", -7 * 60 }, // Mountain Standard Time + { "PDT", -7 * 60 }, // Pacific Daylight Time + { "PST", -8 * 60 }, // Pacific Standard Time + { "WET", +0 * 60 }, // Western European Time + { "WEST", +1 * 60 }, // Western European Summer Time + { "CET", +1 * 60 }, // Central European Time + { "CEST", +2 * 60 }, // Central European Summer Time + { "EET", +2 * 60 }, // Eastern European Time + { "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++) { + if (string_match(sp, pp, js_tzabbr[i].name)) { + *offset = js_tzabbr[i].offset; + return TRUE; + } + } + return FALSE; +} + +/* parse toString, toUTCString and other formats */ +static BOOL js_date_parse_otherstring(const uint8_t *sp, + int fields[minimum_length(9)], + 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; + int num_index = 0; + + /* initialize fields to the beginning of 2001-01-01 */ + fields[0] = 2001; + fields[1] = 1; + fields[2] = 1; + for (i = 3; i < 9; i++) { + fields[i] = 0; + } + *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; + } else { + p++; + if (string_get_digits(sp, &p, &val, 1, 9)) { + if (c == '-') { + if (val == 0) + return FALSE; + val = -val; + } + fields[0] = val; + has_year = TRUE; + } + } + } else + if (string_get_digits(sp, &p, &val, 1, 9)) { + if (string_skip_char(sp, &p, ':')) { + /* time part */ + fields[3] = val; + if (!string_get_digits(sp, &p, &fields[4], 1, 2)) + return FALSE; + if (string_skip_char(sp, &p, ':')) { + if (!string_get_digits(sp, &p, &fields[5], 1, 2)) + return FALSE; + string_get_milliseconds(sp, &p, &fields[6]); + } else + if (sp[p] != '\0' && sp[p] != ' ') + return FALSE; + has_time = TRUE; + } else { + if (p - p_start > 2) { + fields[0] = val; + has_year = TRUE; + } else + if (val < 1 || val > 31) { + fields[0] = val + (val < 100) * 1900 + (val < 50) * 100; + has_year = TRUE; + } else { + if (num_index == 3) + return FALSE; + num[num_index++] = val; + } + } + } else + if (string_get_month(sp, &p, &fields[1])) { + 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) + 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; + continue; + } else + if (c == '(') { /* skip parenthesized phrase */ + int level = 0; + while ((c = sp[p]) != '\0') { + p++; + level += (c == '('); + level -= (c == ')'); + if (!level) + break; + } + if (level > 0) + return FALSE; + } else + if (c == ')') { + return FALSE; + } else { + if (has_year + has_mon + has_time + num_index) + 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; + + switch (num_index) { + case 0: + if (!has_year) + return FALSE; + break; + case 1: + if (has_mon) + fields[2] = num[0]; + else + fields[1] = num[0]; + break; + case 2: + if (has_year) { + fields[1] = num[0]; + fields[2] = num[1]; + } else + if (has_mon) { + fields[0] = num[1] + (num[1] < 100) * 1900 + (num[1] < 50) * 100; + fields[2] = num[0]; + } else { + fields[1] = num[0]; + fields[2] = num[1]; + } + break; + case 3: + fields[0] = num[2] + (num[2] < 100) * 1900 + (num[2] < 50) * 100; + fields[1] = num[0]; + fields[2] = num[1]; + break; + default: + return FALSE; + } + if (fields[1] < 1 || fields[2] < 1) + return FALSE; + fields[1] -= 1; + return TRUE; +} + +static JSValue js_Date_parse(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - // parse(s) JSValue s, rv; - int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 }; - double fields1[7]; - int64_t tz, hh, mm; + int fields[9]; + double fields1[9]; double d; - int p, i, c, sgn, l; + int i, c; JSString *sp; + uint8_t buf[128]; BOOL is_local; - + rv = JS_NAN; s = JS_ToString(ctx, argv[0]); if (JS_IsException(s)) return JS_EXCEPTION; - + sp = JS_VALUE_GET_STRING(s); - p = 0; - if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) { - /* ISO format */ - /* year field can be negative */ - if (string_get_signed_digits(sp, &p, &fields[0])) - goto done; - - for (i = 1; i < 7; i++) { - if (p >= sp->len) - break; - switch(i) { - case 1: - case 2: - c = '-'; - break; - case 3: - c = 'T'; - break; - case 4: - case 5: - c = ':'; - break; - case 6: - c = '.'; - break; - } - if (string_get(sp, p) != c) - break; - p++; - if (i == 6) { - if (string_get_milliseconds(sp, &p, &fields[i])) - goto done; - } else { - if (string_get_digits(sp, &p, &fields[i])) - goto done; - } + /* convert the string as a byte array */ + for (i = 0; i < sp->len && i < (int)countof(buf) - 1; i++) { + c = string_get(sp, i); + if (c > 255) + c = (c == 0x2212) ? '-' : 'x'; + buf[i] = c; + } + buf[i] = '\0'; + 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; + /* check field maximum values */ + for (i = 1; i < 6; i++) { + if (fields[i] > field_max[i]) + valid = FALSE; } - /* no time: UTC by default */ - is_local = (i > 3); - fields[1] -= 1; - - /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */ - tz = 0; - if (p < sp->len) { - sgn = string_get(sp, p); - if (sgn == '+' || sgn == '-') { - p++; - l = sp->len - p; - if (l != 4 && l != 5) - goto done; - if (string_get_fixed_width_digits(sp, &p, 2, &hh)) - goto done; - if (l == 5) { - if (string_get(sp, p) != ':') - goto done; - p++; - } - if (string_get_fixed_width_digits(sp, &p, 2, &mm)) - goto done; - tz = hh * 60 + mm; - if (sgn == '-') - tz = -tz; - is_local = FALSE; - } else if (sgn == 'Z') { - p++; - is_local = FALSE; - } else { - goto done; - } - /* error if extraneous characters */ - if (p != sp->len) - goto done; - } - } else { - /* toString or toUTCString format */ - /* skip the day of the week */ - string_skip_non_spaces(sp, &p); - string_skip_spaces(sp, &p); - if (p >= sp->len) - goto done; - c = string_get(sp, p); - if (c >= '0' && c <= '9') { - /* day of month first */ - if (string_get_digits(sp, &p, &fields[2])) - goto done; - if (string_get_month(sp, &p, &fields[1])) - goto done; - } else { - /* month first */ - if (string_get_month(sp, &p, &fields[1])) - goto done; - string_skip_spaces(sp, &p); - if (string_get_digits(sp, &p, &fields[2])) - goto done; - } - /* year */ - string_skip_spaces(sp, &p); - if (string_get_signed_digits(sp, &p, &fields[0])) - goto done; - - /* hour, min, seconds */ - string_skip_spaces(sp, &p); - for(i = 0; i < 3; i++) { - if (i == 1 || i == 2) { - if (p >= sp->len) - goto done; - if (string_get(sp, p) != ':') - goto done; - p++; - } - if (string_get_digits(sp, &p, &fields[3 + i])) - goto done; - } - // XXX: parse optional milliseconds? - - /* parse the time zone offset if present: [+-]HHmm */ - is_local = FALSE; - tz = 0; - for (tz = 0; p < sp->len; p++) { - sgn = string_get(sp, p); - if (sgn == '+' || sgn == '-') { - p++; - if (string_get_fixed_width_digits(sp, &p, 2, &hh)) - goto done; - if (string_get_fixed_width_digits(sp, &p, 2, &mm)) - goto done; - tz = hh * 60 + mm; - if (sgn == '-') - tz = -tz; - break; - } + /* special case 24:00:00.000 */ + if (fields[3] == 24 && (fields[4] | fields[5] | fields[6])) + 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_NewFloat64(ctx, d); } } - for(i = 0; i < 7; i++) - fields1[i] = fields[i]; - d = set_date_fields(fields1, is_local) - tz * 60000; - rv = JS_NewFloat64(ctx, d); - -done: JS_FreeValue(ctx, s); return rv; } -static JSValue js_Date_now(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_Date_now(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // now() - return JS_NewInt64(ctx, date_now()); + return js_int64(date_now()); } -static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // Symbol_toPrimitive(hint) - JSValueConst obj = this_val; + JSValue obj = this_val; JSAtom hint = JS_ATOM_NULL; int hint_num; @@ -50024,9 +51092,7 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val, } switch (hint) { case JS_ATOM_number: -#ifdef CONFIG_BIGNUM case JS_ATOM_integer: -#endif hint_num = HINT_NUMBER; break; case JS_ATOM_string: @@ -50039,8 +51105,8 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val, return JS_ToPrimitive(ctx, obj, hint_num | HINT_FORCE_ORDINARY); } -static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // getTimezoneOffset() double v; @@ -50050,22 +51116,23 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val, if (isnan(v)) return JS_NAN; else - return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v))); + /* assuming -8.64e15 <= v <= -8.64e15 */ + return js_int64(getTimezoneOffset((int64_t)trunc(v))); } -static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_getTime(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // getTime() double v; if (JS_ThisTimeValue(ctx, &v, this_val)) return JS_EXCEPTION; - return JS_NewFloat64(ctx, v); + return js_float64(v); } -static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_setTime(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // setTime(v) double v; @@ -50075,27 +51142,29 @@ static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val, return JS_SetThisTimeValue(ctx, this_val, time_clip(v)); } -static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_setYear(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // setYear(y) double y; - JSValueConst args[1]; + JSValue 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; } - args[0] = JS_NewFloat64(ctx, y); + args[0] = js_float64(y); return set_date_field(ctx, this_val, 1, args, 0x011); } -static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_date_toJSON(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // toJSON(key) JSValue obj, tv, method, rv; @@ -50188,9 +51257,18 @@ static const JSCFunctionListEntry js_date_proto_funcs[] = { JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ), }; +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))); + return obj; +} + void JS_AddIntrinsicDate(JSContext *ctx) { - JSValueConst obj; + JSValue obj; /* Date */ ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx); @@ -50208,307 +51286,6 @@ void JS_AddIntrinsicEval(JSContext *ctx) ctx->eval_internal = __JS_EvalInternal; } -#ifdef CONFIG_BIGNUM - -/* Operators */ - -static void js_operator_set_finalizer(JSRuntime *rt, JSValue val) -{ - JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET); - int i, j; - JSBinaryOperatorDefEntry *ent; - - if (opset) { - for(i = 0; i < JS_OVOP_COUNT; i++) { - if (opset->self_ops[i]) - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i])); - } - for(j = 0; j < opset->left.count; j++) { - ent = &opset->left.tab[j]; - for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { - if (ent->ops[i]) - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i])); - } - } - js_free_rt(rt, opset->left.tab); - for(j = 0; j < opset->right.count; j++) { - ent = &opset->right.tab[j]; - for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { - if (ent->ops[i]) - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i])); - } - } - js_free_rt(rt, opset->right.tab); - js_free_rt(rt, opset); - } -} - -static void js_operator_set_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET); - int i, j; - JSBinaryOperatorDefEntry *ent; - - if (opset) { - for(i = 0; i < JS_OVOP_COUNT; i++) { - if (opset->self_ops[i]) - JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]), - mark_func); - } - for(j = 0; j < opset->left.count; j++) { - ent = &opset->left.tab[j]; - for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { - if (ent->ops[i]) - JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]), - mark_func); - } - } - for(j = 0; j < opset->right.count; j++) { - ent = &opset->right.tab[j]; - for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { - if (ent->ops[i]) - JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]), - mark_func); - } - } - } -} - - -/* create an OperatorSet object */ -static JSValue js_operators_create_internal(JSContext *ctx, - int argc, JSValueConst *argv, - BOOL is_primitive) -{ - JSValue opset_obj, prop, obj; - JSOperatorSetData *opset, *opset1; - JSBinaryOperatorDef *def; - JSValueConst arg; - int i, j; - JSBinaryOperatorDefEntry *new_tab; - JSBinaryOperatorDefEntry *ent; - uint32_t op_count; - - if (ctx->rt->operator_count == UINT32_MAX) { - return JS_ThrowTypeError(ctx, "too many operators"); - } - opset_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OPERATOR_SET); - if (JS_IsException(opset_obj)) - goto fail; - opset = js_mallocz(ctx, sizeof(*opset)); - if (!opset) - goto fail; - JS_SetOpaque(opset_obj, opset); - if (argc >= 1) { - arg = argv[0]; - /* self operators */ - for(i = 0; i < JS_OVOP_COUNT; i++) { - prop = JS_GetPropertyStr(ctx, arg, js_overloadable_operator_names[i]); - if (JS_IsException(prop)) - goto fail; - if (!JS_IsUndefined(prop)) { - if (check_function(ctx, prop)) { - JS_FreeValue(ctx, prop); - goto fail; - } - opset->self_ops[i] = JS_VALUE_GET_OBJ(prop); - } - } - } - /* left & right operators */ - for(j = 1; j < argc; j++) { - arg = argv[j]; - prop = JS_GetPropertyStr(ctx, arg, "left"); - if (JS_IsException(prop)) - goto fail; - def = &opset->right; - if (JS_IsUndefined(prop)) { - prop = JS_GetPropertyStr(ctx, arg, "right"); - if (JS_IsException(prop)) - goto fail; - if (JS_IsUndefined(prop)) { - JS_ThrowTypeError(ctx, "left or right property must be present"); - goto fail; - } - def = &opset->left; - } - /* get the operator set */ - obj = JS_GetProperty(ctx, prop, JS_ATOM_prototype); - JS_FreeValue(ctx, prop); - if (JS_IsException(obj)) - goto fail; - prop = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet); - JS_FreeValue(ctx, obj); - if (JS_IsException(prop)) - goto fail; - opset1 = JS_GetOpaque2(ctx, prop, JS_CLASS_OPERATOR_SET); - if (!opset1) { - JS_FreeValue(ctx, prop); - goto fail; - } - op_count = opset1->operator_counter; - JS_FreeValue(ctx, prop); - - /* we assume there are few entries */ - new_tab = js_realloc(ctx, def->tab, - (def->count + 1) * sizeof(def->tab[0])); - if (!new_tab) - goto fail; - def->tab = new_tab; - def->count++; - ent = def->tab + def->count - 1; - memset(ent, 0, sizeof(def->tab[0])); - ent->operator_index = op_count; - - for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { - prop = JS_GetPropertyStr(ctx, arg, - js_overloadable_operator_names[i]); - if (JS_IsException(prop)) - goto fail; - if (!JS_IsUndefined(prop)) { - if (check_function(ctx, prop)) { - JS_FreeValue(ctx, prop); - goto fail; - } - ent->ops[i] = JS_VALUE_GET_OBJ(prop); - } - } - } - opset->is_primitive = is_primitive; - opset->operator_counter = ctx->rt->operator_count++; - return opset_obj; - fail: - JS_FreeValue(ctx, opset_obj); - return JS_EXCEPTION; -} - -static JSValue js_operators_create(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_operators_create_internal(ctx, argc, argv, FALSE); -} - -static JSValue js_operators_updateBigIntOperators(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue opset_obj, prop; - JSOperatorSetData *opset; - const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW }; - JSOverloadableOperatorEnum op; - int i; - - opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT], - JS_ATOM_Symbol_operatorSet); - if (JS_IsException(opset_obj)) - goto fail; - opset = JS_GetOpaque2(ctx, opset_obj, JS_CLASS_OPERATOR_SET); - if (!opset) - goto fail; - for(i = 0; i < countof(ops); i++) { - op = ops[i]; - prop = JS_GetPropertyStr(ctx, argv[0], - js_overloadable_operator_names[op]); - if (JS_IsException(prop)) - goto fail; - if (!JS_IsUndefined(prop)) { - if (!JS_IsNull(prop) && check_function(ctx, prop)) { - JS_FreeValue(ctx, prop); - goto fail; - } - if (opset->self_ops[op]) - JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[op])); - if (JS_IsNull(prop)) { - opset->self_ops[op] = NULL; - } else { - opset->self_ops[op] = JS_VALUE_GET_PTR(prop); - } - } - } - JS_FreeValue(ctx, opset_obj); - return JS_UNDEFINED; - fail: - JS_FreeValue(ctx, opset_obj); - return JS_EXCEPTION; -} - -static int js_operators_set_default(JSContext *ctx, JSValueConst obj) -{ - JSValue opset_obj; - - if (!JS_IsObject(obj)) /* in case the prototype is not defined */ - return 0; - opset_obj = js_operators_create_internal(ctx, 0, NULL, TRUE); - if (JS_IsException(opset_obj)) - return -1; - /* cannot be modified by the user */ - JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_operatorSet, - opset_obj, 0); - return 0; -} - -static JSValue js_dummy_operators_ctor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) -{ - return js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT); -} - -static JSValue js_global_operators(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue func_obj, proto, opset_obj; - - func_obj = JS_UNDEFINED; - proto = JS_NewObject(ctx); - if (JS_IsException(proto)) - return JS_EXCEPTION; - opset_obj = js_operators_create_internal(ctx, argc, argv, FALSE); - if (JS_IsException(opset_obj)) - goto fail; - JS_DefinePropertyValue(ctx, proto, JS_ATOM_Symbol_operatorSet, - opset_obj, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - func_obj = JS_NewCFunction2(ctx, js_dummy_operators_ctor, "Operators", - 0, JS_CFUNC_constructor, 0); - if (JS_IsException(func_obj)) - goto fail; - JS_SetConstructor2(ctx, func_obj, proto, - 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_FreeValue(ctx, proto); - return func_obj; - fail: - JS_FreeValue(ctx, proto); - JS_FreeValue(ctx, func_obj); - return JS_EXCEPTION; -} - -static const JSCFunctionListEntry js_operators_funcs[] = { - JS_CFUNC_DEF("create", 1, js_operators_create ), - JS_CFUNC_DEF("updateBigIntOperators", 2, js_operators_updateBigIntOperators ), -}; - -/* must be called after all overloadable base types are initialized */ -void JS_AddIntrinsicOperators(JSContext *ctx) -{ - JSValue obj; - - ctx->allow_operator_overloading = TRUE; - obj = JS_NewCFunction(ctx, js_global_operators, "Operators", 1); - JS_SetPropertyFunctionList(ctx, obj, - js_operators_funcs, - countof(js_operators_funcs)); - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_Operators, - obj, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - /* add default operatorSets */ - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BOOLEAN]); - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_NUMBER]); - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_STRING]); - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_INT]); - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]); - js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]); -} -#endif /* CONFIG_BIGNUM */ - /* BigInt */ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) @@ -50525,20 +51302,13 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) case JS_TAG_BIG_INT: break; case JS_TAG_FLOAT64: -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_FLOAT: -#endif { bf_t *a, a_s; - - a = JS_ToBigFloat(ctx, &a_s, val); - if (!a) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } + + a = JS_ToBigInt1(ctx, &a_s, val); if (!bf_is_finite(a)) { JS_FreeValue(ctx, val); - val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to bigint"); + val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to BigInt"); } else { JSValue val1 = JS_NewBigInt(ctx); bf_t *r; @@ -50556,7 +51326,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) val = JS_ThrowOutOfMemory(ctx); } else if (ret & BF_ST_INEXACT) { JS_FreeValue(ctx, val1); - val = JS_ThrowRangeError(ctx, "cannot convert to bigint: not an integer"); + val = JS_ThrowRangeError(ctx, "cannot convert to BigInt: not an integer"); } else { val = JS_CompactBigInt(ctx, val1); } @@ -50565,13 +51335,6 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) bf_delete(a); } break; -#ifdef CONFIG_BIGNUM - case JS_TAG_BIG_DECIMAL: - val = JS_ToStringFree(ctx, val); - if (JS_IsException(val)) - break; - goto redo; -#endif case JS_TAG_STRING: val = JS_StringToBigIntErr(ctx, val); break; @@ -50584,37 +51347,37 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) case JS_TAG_UNDEFINED: default: JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert to bigint"); + return JS_ThrowTypeError(ctx, "cannot convert to BigInt"); } return val; } static JSValue js_bigint_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) + JSValue new_target, + int argc, JSValue *argv) { if (!JS_IsUndefined(new_target)) return JS_ThrowTypeError(ctx, "not a constructor"); - return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0])); + return JS_ToBigIntCtorFree(ctx, js_dup(argv[0])); } -static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val) +static JSValue js_thisBigIntValue(JSContext *ctx, JSValue this_val) { if (JS_IsBigInt(ctx, this_val)) - return JS_DupValue(ctx, this_val); + return js_dup(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(ctx, p->u.object_data)) - return JS_DupValue(ctx, p->u.object_data); + return js_dup(p->u.object_data); } } - return JS_ThrowTypeError(ctx, "not a bigint"); + return JS_ThrowTypeError(ctx, "not a BigInt"); } -static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_bigint_toString(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue val; int base; @@ -50638,157 +51401,25 @@ static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_bigint_valueOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { return js_thisBigIntValue(ctx, this_val); } -#ifdef CONFIG_BIGNUM -static JSValue js_bigint_div(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - bf_t a_s, b_s, *a, *b, *r, *q; - int status; - JSValue q_val, r_val; - - q_val = JS_NewBigInt(ctx); - if (JS_IsException(q_val)) - return JS_EXCEPTION; - r_val = JS_NewBigInt(ctx); - if (JS_IsException(r_val)) - goto fail; - b = NULL; - a = JS_ToBigInt(ctx, &a_s, argv[0]); - if (!a) - goto fail; - b = JS_ToBigInt(ctx, &b_s, argv[1]); - if (!b) { - JS_FreeBigInt(ctx, a, &a_s); - goto fail; - } - q = JS_GetBigInt(q_val); - r = JS_GetBigInt(r_val); - status = bf_divrem(q, r, a, b, BF_PREC_INF, BF_RNDZ, magic & 0xf); - JS_FreeBigInt(ctx, a, &a_s); - JS_FreeBigInt(ctx, b, &b_s); - if (unlikely(status)) { - throw_bf_exception(ctx, status); - goto fail; - } - q_val = JS_CompactBigInt(ctx, q_val); - if (magic & 0x10) { - JSValue ret; - ret = JS_NewArray(ctx); - if (JS_IsException(ret)) - goto fail; - JS_SetPropertyUint32(ctx, ret, 0, q_val); - JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, r_val)); - return ret; - } else { - JS_FreeValue(ctx, r_val); - return q_val; - } - fail: - JS_FreeValue(ctx, q_val); - JS_FreeValue(ctx, r_val); - return JS_EXCEPTION; -} - -static JSValue js_bigint_sqrt(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - bf_t a_s, *a, *r, *rem; - int status; - JSValue r_val, rem_val; - - r_val = JS_NewBigInt(ctx); - if (JS_IsException(r_val)) - return JS_EXCEPTION; - rem_val = JS_NewBigInt(ctx); - if (JS_IsException(rem_val)) - return JS_EXCEPTION; - r = JS_GetBigInt(r_val); - rem = JS_GetBigInt(rem_val); - - a = JS_ToBigInt(ctx, &a_s, argv[0]); - if (!a) - goto fail; - status = bf_sqrtrem(r, rem, a); - JS_FreeBigInt(ctx, a, &a_s); - if (unlikely(status & ~BF_ST_INEXACT)) { - throw_bf_exception(ctx, status); - goto fail; - } - r_val = JS_CompactBigInt(ctx, r_val); - if (magic) { - JSValue ret; - ret = JS_NewArray(ctx); - if (JS_IsException(ret)) - goto fail; - JS_SetPropertyUint32(ctx, ret, 0, r_val); - JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, rem_val)); - return ret; - } else { - JS_FreeValue(ctx, rem_val); - return r_val; - } - fail: - JS_FreeValue(ctx, r_val); - JS_FreeValue(ctx, rem_val); - return JS_EXCEPTION; -} - -static JSValue js_bigint_op1(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, - int magic) -{ - bf_t a_s, *a; - int64_t res; - - a = JS_ToBigInt(ctx, &a_s, argv[0]); - if (!a) - return JS_EXCEPTION; - switch(magic) { - case 0: /* floorLog2 */ - if (a->sign || a->expn <= 0) { - res = -1; - } else { - res = a->expn - 1; - } - break; - case 1: /* ctz */ - if (bf_is_zero(a)) { - res = -1; - } else { - res = bf_get_exp_min(a); - } - break; - default: - abort(); - } - JS_FreeBigInt(ctx, a, &a_s); - return JS_NewBigInt64(ctx, res); -} -#endif - static JSValue js_bigint_asUintN(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, int asIntN) + JSValue this_val, + int argc, JSValue *argv, int asIntN) { uint64_t bits; bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s; JSValue res; - + if (JS_ToIndex(ctx, &bits, argv[0])) return JS_EXCEPTION; res = JS_NewBigInt(ctx); if (JS_IsException(res)) return JS_EXCEPTION; - r = JS_GetBigInt(res); a = JS_ToBigInt(ctx, &a_s, argv[1]); if (!a) { JS_FreeValue(ctx, res); @@ -50818,21 +51449,6 @@ static JSValue js_bigint_asUintN(JSContext *ctx, static const JSCFunctionListEntry js_bigint_funcs[] = { JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ), JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ), -#ifdef CONFIG_BIGNUM - /* QuickJS extensions */ - JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ), - JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ), - JS_CFUNC_MAGIC_DEF("cdiv", 2, js_bigint_div, BF_RNDU ), - JS_CFUNC_MAGIC_DEF("ediv", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN ), - JS_CFUNC_MAGIC_DEF("tdivrem", 2, js_bigint_div, BF_RNDZ | 0x10 ), - JS_CFUNC_MAGIC_DEF("fdivrem", 2, js_bigint_div, BF_RNDD | 0x10 ), - JS_CFUNC_MAGIC_DEF("cdivrem", 2, js_bigint_div, BF_RNDU | 0x10 ), - JS_CFUNC_MAGIC_DEF("edivrem", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN | 0x10 ), - JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigint_sqrt, 0 ), - JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ), - JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ), - JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ), -#endif }; static const JSCFunctionListEntry js_bigint_proto_funcs[] = { @@ -50843,14 +51459,7 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = { void JS_AddIntrinsicBigInt(JSContext *ctx) { - JSRuntime *rt = ctx->rt; - JSValueConst obj1; - - rt->bigint_ops.to_string = js_bigint_to_string; - rt->bigint_ops.from_string = js_string_to_bigint; - rt->bigint_ops.unary_arith = js_unary_arith_bigint; - rt->bigint_ops.binary_arith = js_binary_arith_bigint; - rt->bigint_ops.compare = js_compare_bigfloat; + JSValue obj1; ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT], @@ -50862,1413 +51471,6 @@ void JS_AddIntrinsicBigInt(JSContext *ctx) countof(js_bigint_funcs)); } -#ifdef CONFIG_BIGNUM - -/* BigFloat */ - -static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val) -{ - if (JS_IsBigFloat(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_FLOAT) { - if (JS_IsBigFloat(p->u.object_data)) - return JS_DupValue(ctx, p->u.object_data); - } - } - return JS_ThrowTypeError(ctx, "not a bigfloat"); -} - -static JSValue js_bigfloat_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val; - int base; - JSValue ret; - - val = js_thisBigFloatValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (argc == 0 || JS_IsUndefined(argv[0])) { - base = 10; - } else { - base = js_get_radix(ctx, argv[0]); - if (base < 0) - goto fail; - } - ret = js_ftoa(ctx, val, base, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN); - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static JSValue js_bigfloat_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_thisBigFloatValue(ctx, this_val); -} - -static int bigfloat_get_rnd_mode(JSContext *ctx, JSValueConst val) -{ - int rnd_mode; - if (JS_ToInt32Sat(ctx, &rnd_mode, val)) - return -1; - if (rnd_mode < BF_RNDN || rnd_mode > BF_RNDF) { - JS_ThrowRangeError(ctx, "invalid rounding mode"); - return -1; - } - return rnd_mode; -} - -static JSValue js_bigfloat_toFixed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t f; - int rnd_mode, radix; - - val = js_thisBigFloatValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_ToInt64Sat(ctx, &f, argv[0])) - goto fail; - if (f < 0 || f > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - radix = 10; - /* XXX: swap parameter order for rounding mode and radix */ - if (argc > 1) { - rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - if (argc > 2) { - radix = js_get_radix(ctx, argv[2]); - if (radix < 0) - goto fail; - } - ret = js_ftoa(ctx, val, radix, f, rnd_mode | BF_FTOA_FORMAT_FRAC); - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static BOOL js_bigfloat_is_finite(JSContext *ctx, JSValueConst val) -{ - BOOL res; - uint32_t tag; - - tag = JS_VALUE_GET_NORM_TAG(val); - switch(tag) { - case JS_TAG_BIG_FLOAT: - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - res = bf_is_finite(&p->num); - } - break; - default: - res = FALSE; - break; - } - return res; -} - -static JSValue js_bigfloat_toExponential(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t f; - int rnd_mode, radix; - - val = js_thisBigFloatValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_ToInt64Sat(ctx, &f, argv[0])) - goto fail; - if (!js_bigfloat_is_finite(ctx, val)) { - ret = JS_ToString(ctx, val); - } else if (JS_IsUndefined(argv[0])) { - ret = js_ftoa(ctx, val, 10, 0, - BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP); - } else { - if (f < 0 || f > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - radix = 10; - if (argc > 1) { - rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - if (argc > 2) { - radix = js_get_radix(ctx, argv[2]); - if (radix < 0) - goto fail; - } - ret = js_ftoa(ctx, val, radix, f + 1, - rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP); - } - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static JSValue js_bigfloat_toPrecision(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t p; - int rnd_mode, radix; - - val = js_thisBigFloatValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_IsUndefined(argv[0])) - goto to_string; - if (JS_ToInt64Sat(ctx, &p, argv[0])) - goto fail; - if (!js_bigfloat_is_finite(ctx, val)) { - to_string: - ret = JS_ToString(ctx, this_val); - } else { - if (p < 1 || p > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - radix = 10; - if (argc > 1) { - rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - if (argc > 2) { - radix = js_get_radix(ctx, argv[2]); - if (radix < 0) - goto fail; - } - ret = js_ftoa(ctx, val, radix, p, rnd_mode | BF_FTOA_FORMAT_FIXED); - } - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static const JSCFunctionListEntry js_bigfloat_proto_funcs[] = { - JS_CFUNC_DEF("toString", 0, js_bigfloat_toString ), - JS_CFUNC_DEF("valueOf", 0, js_bigfloat_valueOf ), - JS_CFUNC_DEF("toPrecision", 1, js_bigfloat_toPrecision ), - JS_CFUNC_DEF("toFixed", 1, js_bigfloat_toFixed ), - JS_CFUNC_DEF("toExponential", 1, js_bigfloat_toExponential ), -}; - -static JSValue js_bigfloat_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSValue val; - if (!JS_IsUndefined(new_target)) - return JS_ThrowTypeError(ctx, "not a constructor"); - if (argc == 0) { - bf_t *r; - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - return val; - r = JS_GetBigFloat(val); - bf_set_zero(r, 0); - } else { - val = JS_DupValue(ctx, argv[0]); - redo: - switch(JS_VALUE_GET_NORM_TAG(val)) { - case JS_TAG_BIG_FLOAT: - break; - case JS_TAG_FLOAT64: - { - bf_t *r; - double d = JS_VALUE_GET_FLOAT64(val); - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigFloat(val); - if (bf_set_float64(r, d)) - goto fail; - } - break; - case JS_TAG_INT: - { - bf_t *r; - int32_t v = JS_VALUE_GET_INT(val); - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigFloat(val); - if (bf_set_si(r, v)) - goto fail; - } - break; - case JS_TAG_BIG_INT: - /* We keep the full precision of the integer */ - { - JSBigFloat *p = JS_VALUE_GET_PTR(val); - val = JS_MKPTR(JS_TAG_BIG_FLOAT, p); - } - break; - case JS_TAG_BIG_DECIMAL: - val = JS_ToStringFree(ctx, val); - if (JS_IsException(val)) - break; - goto redo; - case JS_TAG_STRING: - { - const char *str, *p; - size_t len; - int err; - - str = JS_ToCStringLen(ctx, &len, val); - JS_FreeValue(ctx, val); - if (!str) - return JS_EXCEPTION; - p = str; - p += skip_spaces(p); - if ((p - str) == len) { - bf_t *r; - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigFloat(val); - bf_set_zero(r, 0); - err = 0; - } else { - val = js_atof(ctx, p, &p, 0, ATOD_ACCEPT_BIN_OCT | - ATOD_TYPE_BIG_FLOAT | - ATOD_ACCEPT_PREFIX_AFTER_SIGN); - if (JS_IsException(val)) { - JS_FreeCString(ctx, str); - return JS_EXCEPTION; - } - p += skip_spaces(p); - err = ((p - str) != len); - } - JS_FreeCString(ctx, str); - if (err) { - JS_FreeValue(ctx, val); - return JS_ThrowSyntaxError(ctx, "invalid bigfloat literal"); - } - } - break; - case JS_TAG_OBJECT: - val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER); - if (JS_IsException(val)) - break; - goto redo; - case JS_TAG_NULL: - case JS_TAG_UNDEFINED: - default: - JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert to bigfloat"); - } - } - return val; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static JSValue js_bigfloat_get_const(JSContext *ctx, - JSValueConst this_val, int magic) -{ - bf_t *r; - JSValue val; - val = JS_NewBigFloat(ctx); - if (JS_IsException(val)) - return val; - r = JS_GetBigFloat(val); - switch(magic) { - case 0: /* PI */ - bf_const_pi(r, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case 1: /* LN2 */ - bf_const_log2(r, ctx->fp_env.prec, ctx->fp_env.flags); - break; - case 2: /* MIN_VALUE */ - case 3: /* MAX_VALUE */ - { - slimb_t e_range, e; - e_range = (limb_t)1 << (bf_get_exp_bits(ctx->fp_env.flags) - 1); - bf_set_ui(r, 1); - if (magic == 2) { - e = -e_range + 2; - if (ctx->fp_env.flags & BF_FLAG_SUBNORMAL) - e -= ctx->fp_env.prec - 1; - bf_mul_2exp(r, e, ctx->fp_env.prec, ctx->fp_env.flags); - } else { - bf_mul_2exp(r, ctx->fp_env.prec, ctx->fp_env.prec, - ctx->fp_env.flags); - bf_add_si(r, r, -1, ctx->fp_env.prec, ctx->fp_env.flags); - bf_mul_2exp(r, e_range - ctx->fp_env.prec, ctx->fp_env.prec, - ctx->fp_env.flags); - } - } - break; - case 4: /* EPSILON */ - bf_set_ui(r, 1); - bf_mul_2exp(r, 1 - ctx->fp_env.prec, - ctx->fp_env.prec, ctx->fp_env.flags); - break; - default: - abort(); - } - return val; -} - -static JSValue js_bigfloat_parseFloat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - bf_t *a; - const char *str; - JSValue ret; - int radix; - JSFloatEnv *fe; - - str = JS_ToCString(ctx, argv[0]); - if (!str) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &radix, argv[1])) { - fail: - JS_FreeCString(ctx, str); - return JS_EXCEPTION; - } - if (radix != 0 && (radix < 2 || radix > 36)) { - JS_ThrowRangeError(ctx, "radix must be between 2 and 36"); - goto fail; - } - fe = &ctx->fp_env; - if (argc > 2) { - fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV); - if (!fe) - goto fail; - } - ret = JS_NewBigFloat(ctx); - if (JS_IsException(ret)) - goto done; - a = JS_GetBigFloat(ret); - /* XXX: use js_atof() */ - bf_atof(a, str, NULL, radix, fe->prec, fe->flags); - done: - JS_FreeCString(ctx, str); - return ret; -} - -static JSValue js_bigfloat_isFinite(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst val = argv[0]; - JSBigFloat *p; - - if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT) - return JS_FALSE; - p = JS_VALUE_GET_PTR(val); - return JS_NewBool(ctx, bf_is_finite(&p->num)); -} - -static JSValue js_bigfloat_isNaN(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst val = argv[0]; - JSBigFloat *p; - - if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT) - return JS_FALSE; - p = JS_VALUE_GET_PTR(val); - return JS_NewBool(ctx, bf_is_nan(&p->num)); -} - -enum { - MATH_OP_ABS, - MATH_OP_FLOOR, - MATH_OP_CEIL, - MATH_OP_ROUND, - MATH_OP_TRUNC, - MATH_OP_SQRT, - MATH_OP_FPROUND, - MATH_OP_ACOS, - MATH_OP_ASIN, - MATH_OP_ATAN, - MATH_OP_ATAN2, - MATH_OP_COS, - MATH_OP_EXP, - MATH_OP_LOG, - MATH_OP_POW, - MATH_OP_SIN, - MATH_OP_TAN, - MATH_OP_FMOD, - MATH_OP_REM, - MATH_OP_SIGN, - - MATH_OP_ADD, - MATH_OP_SUB, - MATH_OP_MUL, - MATH_OP_DIV, -}; - -static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - bf_t a_s, *a, *r; - JSFloatEnv *fe; - int rnd_mode; - JSValue op1, res; - - op1 = JS_ToNumeric(ctx, argv[0]); - if (JS_IsException(op1)) - return op1; - a = JS_ToBigFloat(ctx, &a_s, op1); - if (!a) { - JS_FreeValue(ctx, op1); - return JS_EXCEPTION; - } - fe = &ctx->fp_env; - if (argc > 1) { - fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV); - if (!fe) - goto fail; - } - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) { - fail: - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, op1); - return JS_EXCEPTION; - } - r = JS_GetBigFloat(res); - switch (magic) { - case MATH_OP_ABS: - bf_set(r, a); - r->sign = 0; - break; - case MATH_OP_FLOOR: - rnd_mode = BF_RNDD; - goto rint; - case MATH_OP_CEIL: - rnd_mode = BF_RNDU; - goto rint; - case MATH_OP_ROUND: - rnd_mode = BF_RNDNA; - goto rint; - case MATH_OP_TRUNC: - rnd_mode = BF_RNDZ; - rint: - bf_set(r, a); - fe->status |= bf_rint(r, rnd_mode); - break; - case MATH_OP_SQRT: - fe->status |= bf_sqrt(r, a, fe->prec, fe->flags); - break; - case MATH_OP_FPROUND: - bf_set(r, a); - fe->status |= bf_round(r, fe->prec, fe->flags); - break; - case MATH_OP_ACOS: - fe->status |= bf_acos(r, a, fe->prec, fe->flags); - break; - case MATH_OP_ASIN: - fe->status |= bf_asin(r, a, fe->prec, fe->flags); - break; - case MATH_OP_ATAN: - fe->status |= bf_atan(r, a, fe->prec, fe->flags); - break; - case MATH_OP_COS: - fe->status |= bf_cos(r, a, fe->prec, fe->flags); - break; - case MATH_OP_EXP: - fe->status |= bf_exp(r, a, fe->prec, fe->flags); - break; - case MATH_OP_LOG: - fe->status |= bf_log(r, a, fe->prec, fe->flags); - break; - case MATH_OP_SIN: - fe->status |= bf_sin(r, a, fe->prec, fe->flags); - break; - case MATH_OP_TAN: - fe->status |= bf_tan(r, a, fe->prec, fe->flags); - break; - case MATH_OP_SIGN: - if (bf_is_nan(a) || bf_is_zero(a)) { - bf_set(r, a); - } else { - bf_set_si(r, 1 - 2 * a->sign); - } - break; - default: - abort(); - } - if (a == &a_s) - bf_delete(a); - JS_FreeValue(ctx, op1); - return res; -} - -static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - bf_t a_s, *a, b_s, *b, r_s, *r = &r_s; - JSFloatEnv *fe; - JSValue op1, op2, res; - - op1 = JS_ToNumeric(ctx, argv[0]); - if (JS_IsException(op1)) - return op1; - op2 = JS_ToNumeric(ctx, argv[1]); - if (JS_IsException(op2)) { - JS_FreeValue(ctx, op1); - return op2; - } - a = JS_ToBigFloat(ctx, &a_s, op1); - if (!a) - goto fail1; - b = JS_ToBigFloat(ctx, &b_s, op2); - if (!b) - goto fail2; - fe = &ctx->fp_env; - if (argc > 2) { - fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV); - if (!fe) - goto fail; - } - res = JS_NewBigFloat(ctx); - if (JS_IsException(res)) { - fail: - if (b == &b_s) - bf_delete(b); - fail2: - if (a == &a_s) - bf_delete(a); - fail1: - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return JS_EXCEPTION; - } - r = JS_GetBigFloat(res); - switch (magic) { - case MATH_OP_ATAN2: - fe->status |= bf_atan2(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_POW: - fe->status |= bf_pow(r, a, b, fe->prec, fe->flags | BF_POW_JS_QUIRKS); - break; - case MATH_OP_FMOD: - fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ); - break; - case MATH_OP_REM: - fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDN); - break; - case MATH_OP_ADD: - fe->status |= bf_add(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_SUB: - fe->status |= bf_sub(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_MUL: - fe->status |= bf_mul(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_DIV: - fe->status |= bf_div(r, a, b, fe->prec, fe->flags); - break; - default: - abort(); - } - if (a == &a_s) - bf_delete(a); - if (b == &b_s) - bf_delete(b); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return res; -} - -static const JSCFunctionListEntry js_bigfloat_funcs[] = { - JS_CGETSET_MAGIC_DEF("PI", js_bigfloat_get_const, NULL, 0 ), - JS_CGETSET_MAGIC_DEF("LN2", js_bigfloat_get_const, NULL, 1 ), - JS_CGETSET_MAGIC_DEF("MIN_VALUE", js_bigfloat_get_const, NULL, 2 ), - JS_CGETSET_MAGIC_DEF("MAX_VALUE", js_bigfloat_get_const, NULL, 3 ), - JS_CGETSET_MAGIC_DEF("EPSILON", js_bigfloat_get_const, NULL, 4 ), - JS_CFUNC_DEF("parseFloat", 1, js_bigfloat_parseFloat ), - JS_CFUNC_DEF("isFinite", 1, js_bigfloat_isFinite ), - JS_CFUNC_DEF("isNaN", 1, js_bigfloat_isNaN ), - JS_CFUNC_MAGIC_DEF("abs", 1, js_bigfloat_fop, MATH_OP_ABS ), - JS_CFUNC_MAGIC_DEF("fpRound", 1, js_bigfloat_fop, MATH_OP_FPROUND ), - JS_CFUNC_MAGIC_DEF("floor", 1, js_bigfloat_fop, MATH_OP_FLOOR ), - JS_CFUNC_MAGIC_DEF("ceil", 1, js_bigfloat_fop, MATH_OP_CEIL ), - JS_CFUNC_MAGIC_DEF("round", 1, js_bigfloat_fop, MATH_OP_ROUND ), - JS_CFUNC_MAGIC_DEF("trunc", 1, js_bigfloat_fop, MATH_OP_TRUNC ), - JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigfloat_fop, MATH_OP_SQRT ), - JS_CFUNC_MAGIC_DEF("acos", 1, js_bigfloat_fop, MATH_OP_ACOS ), - JS_CFUNC_MAGIC_DEF("asin", 1, js_bigfloat_fop, MATH_OP_ASIN ), - JS_CFUNC_MAGIC_DEF("atan", 1, js_bigfloat_fop, MATH_OP_ATAN ), - JS_CFUNC_MAGIC_DEF("atan2", 2, js_bigfloat_fop2, MATH_OP_ATAN2 ), - JS_CFUNC_MAGIC_DEF("cos", 1, js_bigfloat_fop, MATH_OP_COS ), - JS_CFUNC_MAGIC_DEF("exp", 1, js_bigfloat_fop, MATH_OP_EXP ), - JS_CFUNC_MAGIC_DEF("log", 1, js_bigfloat_fop, MATH_OP_LOG ), - JS_CFUNC_MAGIC_DEF("pow", 2, js_bigfloat_fop2, MATH_OP_POW ), - JS_CFUNC_MAGIC_DEF("sin", 1, js_bigfloat_fop, MATH_OP_SIN ), - JS_CFUNC_MAGIC_DEF("tan", 1, js_bigfloat_fop, MATH_OP_TAN ), - JS_CFUNC_MAGIC_DEF("sign", 1, js_bigfloat_fop, MATH_OP_SIGN ), - JS_CFUNC_MAGIC_DEF("add", 2, js_bigfloat_fop2, MATH_OP_ADD ), - JS_CFUNC_MAGIC_DEF("sub", 2, js_bigfloat_fop2, MATH_OP_SUB ), - JS_CFUNC_MAGIC_DEF("mul", 2, js_bigfloat_fop2, MATH_OP_MUL ), - JS_CFUNC_MAGIC_DEF("div", 2, js_bigfloat_fop2, MATH_OP_DIV ), - JS_CFUNC_MAGIC_DEF("fmod", 2, js_bigfloat_fop2, MATH_OP_FMOD ), - JS_CFUNC_MAGIC_DEF("remainder", 2, js_bigfloat_fop2, MATH_OP_REM ), -}; - -/* FloatEnv */ - -static JSValue js_float_env_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSValue obj; - JSFloatEnv *fe; - int64_t prec; - int flags, rndmode; - - prec = ctx->fp_env.prec; - flags = ctx->fp_env.flags; - if (!JS_IsUndefined(argv[0])) { - if (JS_ToInt64Sat(ctx, &prec, argv[0])) - return JS_EXCEPTION; - if (prec < BF_PREC_MIN || prec > BF_PREC_MAX) - return JS_ThrowRangeError(ctx, "invalid precision"); - flags = BF_RNDN; /* RNDN, max exponent size, no subnormal */ - if (argc > 1 && !JS_IsUndefined(argv[1])) { - if (JS_ToInt32Sat(ctx, &rndmode, argv[1])) - return JS_EXCEPTION; - if (rndmode < BF_RNDN || rndmode > BF_RNDF) - return JS_ThrowRangeError(ctx, "invalid rounding mode"); - flags = rndmode; - } - } - - obj = JS_NewObjectClass(ctx, JS_CLASS_FLOAT_ENV); - if (JS_IsException(obj)) - return JS_EXCEPTION; - fe = js_malloc(ctx, sizeof(*fe)); - if (!fe) - return JS_EXCEPTION; - fe->prec = prec; - fe->flags = flags; - fe->status = 0; - JS_SetOpaque(obj, fe); - return obj; -} - -static void js_float_env_finalizer(JSRuntime *rt, JSValue val) -{ - JSFloatEnv *fe = JS_GetOpaque(val, JS_CLASS_FLOAT_ENV); - js_free_rt(rt, fe); -} - -static JSValue js_float_env_get_prec(JSContext *ctx, JSValueConst this_val) -{ - return JS_NewInt64(ctx, ctx->fp_env.prec); -} - -static JSValue js_float_env_get_expBits(JSContext *ctx, JSValueConst this_val) -{ - return JS_NewInt32(ctx, bf_get_exp_bits(ctx->fp_env.flags)); -} - -static JSValue js_float_env_setPrec(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst func; - int exp_bits, flags, saved_flags; - JSValue ret; - limb_t saved_prec; - int64_t prec; - - func = argv[0]; - if (JS_ToInt64Sat(ctx, &prec, argv[1])) - return JS_EXCEPTION; - if (prec < BF_PREC_MIN || prec > BF_PREC_MAX) - return JS_ThrowRangeError(ctx, "invalid precision"); - exp_bits = BF_EXP_BITS_MAX; - - if (argc > 2 && !JS_IsUndefined(argv[2])) { - if (JS_ToInt32Sat(ctx, &exp_bits, argv[2])) - return JS_EXCEPTION; - if (exp_bits < BF_EXP_BITS_MIN || exp_bits > BF_EXP_BITS_MAX) - return JS_ThrowRangeError(ctx, "invalid number of exponent bits"); - } - - flags = BF_RNDN | BF_FLAG_SUBNORMAL | bf_set_exp_bits(exp_bits); - - saved_prec = ctx->fp_env.prec; - saved_flags = ctx->fp_env.flags; - - ctx->fp_env.prec = prec; - ctx->fp_env.flags = flags; - - ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL); - /* always restore the floating point precision */ - ctx->fp_env.prec = saved_prec; - ctx->fp_env.flags = saved_flags; - return ret; -} - -#define FE_PREC (-1) -#define FE_EXP (-2) -#define FE_RNDMODE (-3) -#define FE_SUBNORMAL (-4) - -static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_val, int magic) -{ - JSFloatEnv *fe; - fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV); - if (!fe) - return JS_EXCEPTION; - switch(magic) { - case FE_PREC: - return JS_NewInt64(ctx, fe->prec); - case FE_EXP: - return JS_NewInt32(ctx, bf_get_exp_bits(fe->flags)); - case FE_RNDMODE: - return JS_NewInt32(ctx, fe->flags & BF_RND_MASK); - case FE_SUBNORMAL: - return JS_NewBool(ctx, (fe->flags & BF_FLAG_SUBNORMAL) != 0); - default: - return JS_NewBool(ctx, (fe->status & magic) != 0); - } -} - -static JSValue js_float_env_proto_set_status(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic) -{ - JSFloatEnv *fe; - int b; - int64_t prec; - - fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV); - if (!fe) - return JS_EXCEPTION; - switch(magic) { - case FE_PREC: - if (JS_ToInt64Sat(ctx, &prec, val)) - return JS_EXCEPTION; - if (prec < BF_PREC_MIN || prec > BF_PREC_MAX) - return JS_ThrowRangeError(ctx, "invalid precision"); - fe->prec = prec; - break; - case FE_EXP: - if (JS_ToInt32Sat(ctx, &b, val)) - return JS_EXCEPTION; - if (b < BF_EXP_BITS_MIN || b > BF_EXP_BITS_MAX) - return JS_ThrowRangeError(ctx, "invalid number of exponent bits"); - fe->flags = (fe->flags & ~(BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)) | - bf_set_exp_bits(b); - break; - case FE_RNDMODE: - b = bigfloat_get_rnd_mode(ctx, val); - if (b < 0) - return JS_EXCEPTION; - fe->flags = (fe->flags & ~BF_RND_MASK) | b; - break; - case FE_SUBNORMAL: - b = JS_ToBool(ctx, val); - fe->flags = (fe->flags & ~BF_FLAG_SUBNORMAL) | (b ? BF_FLAG_SUBNORMAL: 0); - break; - default: - b = JS_ToBool(ctx, val); - fe->status = (fe->status & ~magic) & ((-b) & magic); - break; - } - return JS_UNDEFINED; -} - -static JSValue js_float_env_clearStatus(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSFloatEnv *fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV); - if (!fe) - return JS_EXCEPTION; - fe->status = 0; - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry js_float_env_funcs[] = { - JS_CGETSET_DEF("prec", js_float_env_get_prec, NULL ), - JS_CGETSET_DEF("expBits", js_float_env_get_expBits, NULL ), - JS_CFUNC_DEF("setPrec", 2, js_float_env_setPrec ), - JS_PROP_INT32_DEF("RNDN", BF_RNDN, 0 ), - JS_PROP_INT32_DEF("RNDZ", BF_RNDZ, 0 ), - JS_PROP_INT32_DEF("RNDU", BF_RNDU, 0 ), - JS_PROP_INT32_DEF("RNDD", BF_RNDD, 0 ), - JS_PROP_INT32_DEF("RNDNA", BF_RNDNA, 0 ), - JS_PROP_INT32_DEF("RNDA", BF_RNDA, 0 ), - JS_PROP_INT32_DEF("RNDF", BF_RNDF, 0 ), - JS_PROP_INT32_DEF("precMin", BF_PREC_MIN, 0 ), - JS_PROP_INT64_DEF("precMax", BF_PREC_MAX, 0 ), - JS_PROP_INT32_DEF("expBitsMin", BF_EXP_BITS_MIN, 0 ), - JS_PROP_INT32_DEF("expBitsMax", BF_EXP_BITS_MAX, 0 ), -}; - -static const JSCFunctionListEntry js_float_env_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("prec", js_float_env_proto_get_status, - js_float_env_proto_set_status, FE_PREC ), - JS_CGETSET_MAGIC_DEF("expBits", js_float_env_proto_get_status, - js_float_env_proto_set_status, FE_EXP ), - JS_CGETSET_MAGIC_DEF("rndMode", js_float_env_proto_get_status, - js_float_env_proto_set_status, FE_RNDMODE ), - JS_CGETSET_MAGIC_DEF("subnormal", js_float_env_proto_get_status, - js_float_env_proto_set_status, FE_SUBNORMAL ), - JS_CGETSET_MAGIC_DEF("invalidOperation", js_float_env_proto_get_status, - js_float_env_proto_set_status, BF_ST_INVALID_OP ), - JS_CGETSET_MAGIC_DEF("divideByZero", js_float_env_proto_get_status, - js_float_env_proto_set_status, BF_ST_DIVIDE_ZERO ), - JS_CGETSET_MAGIC_DEF("overflow", js_float_env_proto_get_status, - js_float_env_proto_set_status, BF_ST_OVERFLOW ), - JS_CGETSET_MAGIC_DEF("underflow", js_float_env_proto_get_status, - js_float_env_proto_set_status, BF_ST_UNDERFLOW ), - JS_CGETSET_MAGIC_DEF("inexact", js_float_env_proto_get_status, - js_float_env_proto_set_status, BF_ST_INEXACT ), - JS_CFUNC_DEF("clearStatus", 0, js_float_env_clearStatus ), -}; - -void JS_AddIntrinsicBigFloat(JSContext *ctx) -{ - JSRuntime *rt = ctx->rt; - JSValueConst obj1; - - rt->bigfloat_ops.to_string = js_bigfloat_to_string; - rt->bigfloat_ops.from_string = js_string_to_bigfloat; - rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat; - rt->bigfloat_ops.binary_arith = js_binary_arith_bigfloat; - rt->bigfloat_ops.compare = js_compare_bigfloat; - rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64; - rt->bigfloat_ops.mul_pow10 = js_mul_pow10; - - ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT], - js_bigfloat_proto_funcs, - countof(js_bigfloat_proto_funcs)); - obj1 = JS_NewGlobalCConstructor(ctx, "BigFloat", js_bigfloat_constructor, 1, - ctx->class_proto[JS_CLASS_BIG_FLOAT]); - JS_SetPropertyFunctionList(ctx, obj1, js_bigfloat_funcs, - countof(js_bigfloat_funcs)); - - ctx->class_proto[JS_CLASS_FLOAT_ENV] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FLOAT_ENV], - js_float_env_proto_funcs, - countof(js_float_env_proto_funcs)); - obj1 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv", - js_float_env_constructor, 1, - ctx->class_proto[JS_CLASS_FLOAT_ENV]); - JS_SetPropertyFunctionList(ctx, obj1, js_float_env_funcs, - countof(js_float_env_funcs)); -} - -/* BigDecimal */ - -static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val, - BOOL allow_null_or_undefined) -{ - redo: - switch(JS_VALUE_GET_NORM_TAG(val)) { - case JS_TAG_BIG_DECIMAL: - break; - case JS_TAG_NULL: - if (!allow_null_or_undefined) - goto fail; - /* fall thru */ - case JS_TAG_BOOL: - case JS_TAG_INT: - { - bfdec_t *r; - int32_t v = JS_VALUE_GET_INT(val); - - val = JS_NewBigDecimal(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigDecimal(val); - if (bfdec_set_si(r, v)) { - JS_FreeValue(ctx, val); - val = JS_EXCEPTION; - break; - } - } - break; - case JS_TAG_FLOAT64: - case JS_TAG_BIG_INT: - case JS_TAG_BIG_FLOAT: - val = JS_ToStringFree(ctx, val); - if (JS_IsException(val)) - break; - goto redo; - case JS_TAG_STRING: - { - const char *str, *p; - size_t len; - int err; - - str = JS_ToCStringLen(ctx, &len, val); - JS_FreeValue(ctx, val); - if (!str) - return JS_EXCEPTION; - p = str; - p += skip_spaces(p); - if ((p - str) == len) { - bfdec_t *r; - val = JS_NewBigDecimal(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigDecimal(val); - bfdec_set_zero(r, 0); - err = 0; - } else { - val = js_atof(ctx, p, &p, 0, ATOD_TYPE_BIG_DECIMAL); - if (JS_IsException(val)) { - JS_FreeCString(ctx, str); - return JS_EXCEPTION; - } - p += skip_spaces(p); - err = ((p - str) != len); - } - JS_FreeCString(ctx, str); - if (err) { - JS_FreeValue(ctx, val); - return JS_ThrowSyntaxError(ctx, "invalid bigdecimal literal"); - } - } - break; - case JS_TAG_OBJECT: - val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER); - if (JS_IsException(val)) - break; - goto redo; - case JS_TAG_UNDEFINED: - { - bfdec_t *r; - if (!allow_null_or_undefined) - goto fail; - val = JS_NewBigDecimal(ctx); - if (JS_IsException(val)) - break; - r = JS_GetBigDecimal(val); - bfdec_set_nan(r); - } - break; - default: - fail: - JS_FreeValue(ctx, val); - return JS_ThrowTypeError(ctx, "cannot convert to bigdecimal"); - } - return val; -} - -static JSValue js_bigdecimal_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSValue val; - if (!JS_IsUndefined(new_target)) - return JS_ThrowTypeError(ctx, "not a constructor"); - if (argc == 0) { - bfdec_t *r; - val = JS_NewBigDecimal(ctx); - if (JS_IsException(val)) - return val; - r = JS_GetBigDecimal(val); - bfdec_set_zero(r, 0); - } else { - val = JS_ToBigDecimalFree(ctx, JS_DupValue(ctx, argv[0]), FALSE); - } - return val; -} - -static JSValue js_thisBigDecimalValue(JSContext *ctx, JSValueConst this_val) -{ - if (JS_IsBigDecimal(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_DECIMAL) { - if (JS_IsBigDecimal(p->u.object_data)) - return JS_DupValue(ctx, p->u.object_data); - } - } - return JS_ThrowTypeError(ctx, "not a bigdecimal"); -} - -static JSValue js_bigdecimal_toString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val; - - val = js_thisBigDecimalValue(ctx, this_val); - if (JS_IsException(val)) - return val; - return JS_ToStringFree(ctx, val); -} - -static JSValue js_bigdecimal_valueOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_thisBigDecimalValue(ctx, this_val); -} - -static int js_bigdecimal_get_rnd_mode(JSContext *ctx, JSValueConst obj) -{ - const char *str; - size_t size; - int rnd_mode; - - str = JS_ToCStringLen(ctx, &size, obj); - if (!str) - return -1; - if (strlen(str) != size) - goto invalid_rounding_mode; - if (!strcmp(str, "floor")) { - rnd_mode = BF_RNDD; - } else if (!strcmp(str, "ceiling")) { - rnd_mode = BF_RNDU; - } else if (!strcmp(str, "down")) { - rnd_mode = BF_RNDZ; - } else if (!strcmp(str, "up")) { - rnd_mode = BF_RNDA; - } else if (!strcmp(str, "half-even")) { - rnd_mode = BF_RNDN; - } else if (!strcmp(str, "half-up")) { - rnd_mode = BF_RNDNA; - } else { - invalid_rounding_mode: - JS_FreeCString(ctx, str); - JS_ThrowTypeError(ctx, "invalid rounding mode"); - return -1; - } - JS_FreeCString(ctx, str); - return rnd_mode; -} - -typedef struct { - int64_t prec; - bf_flags_t flags; -} BigDecimalEnv; - -static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe, - JSValueConst obj) -{ - JSValue prop; - int64_t val; - BOOL has_prec; - int rnd_mode; - - if (!JS_IsObject(obj)) { - JS_ThrowTypeErrorNotAnObject(ctx); - return -1; - } - prop = JS_GetProperty(ctx, obj, JS_ATOM_roundingMode); - if (JS_IsException(prop)) - return -1; - rnd_mode = js_bigdecimal_get_rnd_mode(ctx, prop); - JS_FreeValue(ctx, prop); - if (rnd_mode < 0) - return -1; - fe->flags = rnd_mode; - - prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits); - if (JS_IsException(prop)) - return -1; - has_prec = FALSE; - if (!JS_IsUndefined(prop)) { - if (JS_ToInt64SatFree(ctx, &val, prop)) - return -1; - if (val < 1 || val > BF_PREC_MAX) - goto invalid_precision; - fe->prec = val; - has_prec = TRUE; - } - - prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumFractionDigits); - if (JS_IsException(prop)) - return -1; - if (!JS_IsUndefined(prop)) { - if (has_prec) { - JS_FreeValue(ctx, prop); - JS_ThrowTypeError(ctx, "cannot provide both maximumSignificantDigits and maximumFractionDigits"); - return -1; - } - if (JS_ToInt64SatFree(ctx, &val, prop)) - return -1; - if (val < 0 || val > BF_PREC_MAX) { - invalid_precision: - JS_ThrowTypeError(ctx, "invalid precision"); - return -1; - } - fe->prec = val; - fe->flags |= BF_FLAG_RADPNT_PREC; - has_prec = TRUE; - } - if (!has_prec) { - JS_ThrowTypeError(ctx, "precision must be present"); - return -1; - } - return 0; -} - - -static JSValue js_bigdecimal_fop(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - bfdec_t *a, *b, r_s, *r = &r_s; - JSValue op1, op2, res; - BigDecimalEnv fe_s, *fe = &fe_s; - int op_count, ret; - - if (magic == MATH_OP_SQRT || - magic == MATH_OP_ROUND) - op_count = 1; - else - op_count = 2; - - op1 = JS_ToNumeric(ctx, argv[0]); - if (JS_IsException(op1)) - return op1; - a = JS_ToBigDecimal(ctx, op1); - if (!a) { - JS_FreeValue(ctx, op1); - return JS_EXCEPTION; - } - if (op_count >= 2) { - op2 = JS_ToNumeric(ctx, argv[1]); - if (JS_IsException(op2)) { - JS_FreeValue(ctx, op1); - return op2; - } - b = JS_ToBigDecimal(ctx, op2); - if (!b) - goto fail; - } else { - op2 = JS_UNDEFINED; - b = NULL; - } - fe->flags = BF_RNDZ; - fe->prec = BF_PREC_INF; - if (op_count < argc) { - if (js_bigdecimal_get_env(ctx, fe, argv[op_count])) - goto fail; - } - - res = JS_NewBigDecimal(ctx); - if (JS_IsException(res)) { - fail: - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - return JS_EXCEPTION; - } - r = JS_GetBigDecimal(res); - switch (magic) { - case MATH_OP_ADD: - ret = bfdec_add(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_SUB: - ret = bfdec_sub(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_MUL: - ret = bfdec_mul(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_DIV: - ret = bfdec_div(r, a, b, fe->prec, fe->flags); - break; - case MATH_OP_FMOD: - ret = bfdec_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ); - break; - case MATH_OP_SQRT: - ret = bfdec_sqrt(r, a, fe->prec, fe->flags); - break; - case MATH_OP_ROUND: - ret = bfdec_set(r, a); - if (!(ret & BF_ST_MEM_ERROR)) - ret = bfdec_round(r, fe->prec, fe->flags); - break; - default: - abort(); - } - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - ret &= BF_ST_MEM_ERROR | BF_ST_DIVIDE_ZERO | BF_ST_INVALID_OP | - BF_ST_OVERFLOW; - if (ret != 0) { - JS_FreeValue(ctx, res); - return throw_bf_exception(ctx, ret); - } else { - return res; - } -} - -static JSValue js_bigdecimal_toFixed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t f; - int rnd_mode; - - val = js_thisBigDecimalValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_ToInt64Sat(ctx, &f, argv[0])) - goto fail; - if (f < 0 || f > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - if (argc > 1) { - rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - ret = js_bigdecimal_to_string1(ctx, val, f, rnd_mode | BF_FTOA_FORMAT_FRAC); - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static JSValue js_bigdecimal_toExponential(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t f; - int rnd_mode; - - val = js_thisBigDecimalValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_ToInt64Sat(ctx, &f, argv[0])) - goto fail; - if (JS_IsUndefined(argv[0])) { - ret = js_bigdecimal_to_string1(ctx, val, 0, - BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP); - } else { - if (f < 0 || f > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - if (argc > 1) { - rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - ret = js_bigdecimal_to_string1(ctx, val, f + 1, - rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP); - } - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static JSValue js_bigdecimal_toPrecision(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue val, ret; - int64_t p; - int rnd_mode; - - val = js_thisBigDecimalValue(ctx, this_val); - if (JS_IsException(val)) - return val; - if (JS_IsUndefined(argv[0])) { - return JS_ToStringFree(ctx, val); - } - if (JS_ToInt64Sat(ctx, &p, argv[0])) - goto fail; - if (p < 1 || p > BF_PREC_MAX) { - JS_ThrowRangeError(ctx, "invalid number of digits"); - goto fail; - } - rnd_mode = BF_RNDNA; - if (argc > 1) { - rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]); - if (rnd_mode < 0) - goto fail; - } - ret = js_bigdecimal_to_string1(ctx, val, p, - rnd_mode | BF_FTOA_FORMAT_FIXED); - JS_FreeValue(ctx, val); - return ret; - fail: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -static const JSCFunctionListEntry js_bigdecimal_proto_funcs[] = { - JS_CFUNC_DEF("toString", 0, js_bigdecimal_toString ), - JS_CFUNC_DEF("valueOf", 0, js_bigdecimal_valueOf ), - JS_CFUNC_DEF("toPrecision", 1, js_bigdecimal_toPrecision ), - JS_CFUNC_DEF("toFixed", 1, js_bigdecimal_toFixed ), - JS_CFUNC_DEF("toExponential", 1, js_bigdecimal_toExponential ), -}; - -static const JSCFunctionListEntry js_bigdecimal_funcs[] = { - JS_CFUNC_MAGIC_DEF("add", 2, js_bigdecimal_fop, MATH_OP_ADD ), - JS_CFUNC_MAGIC_DEF("sub", 2, js_bigdecimal_fop, MATH_OP_SUB ), - JS_CFUNC_MAGIC_DEF("mul", 2, js_bigdecimal_fop, MATH_OP_MUL ), - JS_CFUNC_MAGIC_DEF("div", 2, js_bigdecimal_fop, MATH_OP_DIV ), - JS_CFUNC_MAGIC_DEF("mod", 2, js_bigdecimal_fop, MATH_OP_FMOD ), - JS_CFUNC_MAGIC_DEF("round", 1, js_bigdecimal_fop, MATH_OP_ROUND ), - JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigdecimal_fop, MATH_OP_SQRT ), -}; - -void JS_AddIntrinsicBigDecimal(JSContext *ctx) -{ - JSRuntime *rt = ctx->rt; - JSValueConst obj1; - - rt->bigdecimal_ops.to_string = js_bigdecimal_to_string; - rt->bigdecimal_ops.from_string = js_string_to_bigdecimal; - rt->bigdecimal_ops.unary_arith = js_unary_arith_bigdecimal; - rt->bigdecimal_ops.binary_arith = js_binary_arith_bigdecimal; - rt->bigdecimal_ops.compare = js_compare_bigdecimal; - - ctx->class_proto[JS_CLASS_BIG_DECIMAL] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL], - js_bigdecimal_proto_funcs, - countof(js_bigdecimal_proto_funcs)); - obj1 = JS_NewGlobalCConstructor(ctx, "BigDecimal", - js_bigdecimal_constructor, 1, - ctx->class_proto[JS_CLASS_BIG_DECIMAL]); - JS_SetPropertyFunctionList(ctx, obj1, js_bigdecimal_funcs, - countof(js_bigdecimal_funcs)); -} - -void JS_EnableBignumExt(JSContext *ctx, BOOL enable) -{ - ctx->bignum_ext = enable; -} - -#endif /* CONFIG_BIGNUM */ - static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = { "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", @@ -52286,18 +51488,8 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) 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_DupValue(ctx, ctx->function_proto); + ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = js_dup(ctx->function_proto); ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx); -#if 0 - /* these are auto-initialized from js_error_proto_funcs, - but delaying might be a problem */ - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_name, - JS_AtomToString(ctx, JS_ATOM_Error), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_message, - JS_AtomToString(ctx, JS_ATOM_empty_string), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); -#endif JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR], js_error_proto_funcs, countof(js_error_proto_funcs)); @@ -52334,7 +51526,7 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) void JS_AddIntrinsicBaseObjects(JSContext *ctx) { int i; - JSValueConst obj, number_obj; + JSValue obj, number_obj; JSValue obj1; ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0); @@ -52350,7 +51542,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); JS_FreeValue(ctx, obj1); - JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1)); + JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1)); ctx->global_obj = JS_NewObject(ctx); ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL); @@ -52367,31 +51559,54 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor, "Function", 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_NORMAL); - JS_NewGlobalCConstructor2(ctx, JS_DupValue(ctx, ctx->function_ctor), "Function", + JS_NewGlobalCConstructor2(ctx, js_dup(ctx->function_ctor), "Function", ctx->function_proto); /* Error */ - obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor, - "Error", 1, JS_CFUNC_constructor_or_func_magic, -1); - JS_NewGlobalCConstructor2(ctx, obj1, + 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, (JSCFunction *)js_error_constructor, + func_obj = JS_NewCFunction3(ctx, ft.generic, native_error_name[i], n_args, - JS_CFUNC_constructor_or_func_magic, i, obj1); + JS_CFUNC_constructor_or_func_magic, i, + ctx->error_ctor); JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i], ctx->native_error_proto[i]); } - /* Iterator prototype */ - ctx->iterator_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->iterator_proto, + /* CallSite */ + _JS_AddIntrinsicCallSite(ctx); + + /* 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]); + ctx->iterator_ctor = js_dup(obj); + JS_SetPropertyFunctionList(ctx, obj, + js_iterator_funcs, + countof(js_iterator_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], @@ -52400,14 +51615,14 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1, ctx->class_proto[JS_CLASS_ARRAY]); - ctx->array_ctor = JS_DupValue(ctx, obj); + ctx->array_ctor = js_dup(obj); JS_SetPropertyFunctionList(ctx, obj, js_array_funcs, countof(js_array_funcs)); /* XXX: create auto_initializer */ { /* initialize Array.prototype[Symbol.unscopables] */ - char const unscopables[] = + static const char unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" @@ -52437,7 +51652,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) ctx->array_proto_values = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values); - ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto); + 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)); @@ -52451,7 +51666,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) /* 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_NewInt32(ctx, 0)); + 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)); @@ -52462,7 +51677,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) /* 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_NewBool(ctx, FALSE)); + JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_bool(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, @@ -52479,7 +51694,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) 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->iterator_proto); + 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)); @@ -52511,7 +51726,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) } /* ES6 Generator */ - ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto); + 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)); @@ -52534,11 +51749,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) /* global properties */ ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, - JS_DupValue(ctx, ctx->eval_obj), + js_dup(ctx->eval_obj), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, - JS_DupValue(ctx, ctx->global_obj), + js_dup(ctx->global_obj), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); } @@ -52546,13 +51761,14 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = { 0, 0, 0, 1, 1, 2, 2, - 3, 3, /* BigInt64Array, BigUint64Array */ - 2, 3 + 3, 3, // BigInt64Array, BigUint64Array + 1, 2, 3 // Float16Array, Float32Array, Float64Array }; static JSValue js_array_buffer_constructor3(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id, + JSValue new_target, + uint64_t len, uint64_t *max_len, + JSClassID class_id, uint8_t *buf, JSFreeArrayBufferDataFunc *free_func, void *opaque, BOOL alloc_flag) @@ -52560,7 +51776,15 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JSRuntime *rt = ctx->rt; JSValue obj; JSArrayBuffer *abuf = NULL; + uint64_t sab_alloc_len; + if (!alloc_flag && buf && max_len && free_func != js_array_buffer_free) { + // not observable from JS land, only through C API misuse; + // JS code cannot create externally managed buffers directly + return JS_ThrowInternalError(ctx, + "resizable ArrayBuffers not supported " + "for externally managed buffers"); + } obj = js_create_from_ctor(ctx, new_target, class_id); if (JS_IsException(obj)) return obj; @@ -52569,18 +51793,26 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JS_ThrowRangeError(ctx, "invalid array buffer length"); goto fail; } + if (max_len && *max_len > INT32_MAX) { + JS_ThrowRangeError(ctx, "invalid max array buffer length"); + goto fail; + } abuf = js_malloc(ctx, sizeof(*abuf)); if (!abuf) goto fail; abuf->byte_length = len; + abuf->max_byte_length = max_len ? *max_len : -1; if (alloc_flag) { if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER && rt->sab_funcs.sab_alloc) { + // TOOD(bnoordhuis) resizing backing memory for SABs atomically + // is hard so we cheat and allocate |maxByteLength| bytes upfront + sab_alloc_len = max_len ? *max_len : len; abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque, - max_int(len, 1)); + max_int(sab_alloc_len, 1)); if (!abuf->data) goto fail; - memset(abuf->data, 0, len); + memset(abuf->data, 0, sab_alloc_len); } else { /* the allocation must be done after the object creation */ abuf->data = js_mallocz(ctx, max_int(len, 1)); @@ -52601,7 +51833,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, abuf->free_func = free_func; if (alloc_flag && buf) memcpy(abuf->data, buf, len); - JS_SetOpaque(obj, abuf); + JS_SetOpaqueInternal(obj, abuf); return obj; fail: JS_FreeValue(ctx, obj); @@ -52615,19 +51847,20 @@ static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr) } static JSValue js_array_buffer_constructor2(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id) + JSValue new_target, + uint64_t len, uint64_t *max_len, + JSClassID class_id) { - return js_array_buffer_constructor3(ctx, new_target, 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, - JSValueConst new_target, - uint64_t len) + JSValue new_target, + uint64_t len, uint64_t *max_len) { - return js_array_buffer_constructor2(ctx, new_target, len, + return js_array_buffer_constructor2(ctx, new_target, len, max_len, JS_CLASS_ARRAY_BUFFER); } @@ -52635,39 +51868,73 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, JSFreeArrayBufferDataFunc *free_func, void *opaque, BOOL is_shared) { - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, - is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER, + 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); } +JS_BOOL JS_IsArrayBuffer(JSValue obj) { + return JS_GetClassID(obj) == JS_CLASS_ARRAY_BUFFER; +} + /* create a new ArrayBuffer of length 'len' and copy 'buf' to it */ JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len) { - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, + return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, JS_CLASS_ARRAY_BUFFER, (uint8_t *)buf, js_array_buffer_free, NULL, TRUE); } -static JSValue js_array_buffer_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) +static JSValue js_array_buffer_constructor0(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv, + JSClassID class_id) { - uint64_t len; + uint64_t len, max_len, *pmax_len = NULL; + JSValue obj, val; + int64_t i; + if (JS_ToIndex(ctx, &len, argv[0])) return JS_EXCEPTION; - return js_array_buffer_constructor1(ctx, new_target, len); + if (argc < 2) + goto next; + if (!JS_IsObject(argv[1])) + goto next; + obj = JS_ToObject(ctx, argv[1]); + if (JS_IsException(obj)) + return JS_EXCEPTION; + val = JS_GetProperty(ctx, obj, JS_ATOM_maxByteLength); + JS_FreeValue(ctx, obj); + if (JS_IsException(val)) + return JS_EXCEPTION; + if (JS_IsUndefined(val)) + goto next; + if (JS_ToInt64Free(ctx, &i, val)) + return JS_EXCEPTION; + // don't have to check i < 0 because len >= 0 + if (len > i || i > MAX_SAFE_INTEGER) + return JS_ThrowRangeError(ctx, "invalid array buffer max length"); + max_len = i; + pmax_len = &max_len; +next: + return js_array_buffer_constructor2(ctx, new_target, len, pmax_len, + class_id); +} + +static JSValue js_array_buffer_constructor(JSContext *ctx, JSValue new_target, + int argc, JSValue *argv) +{ + return js_array_buffer_constructor0(ctx, new_target, argc, argv, + JS_CLASS_ARRAY_BUFFER); } static JSValue js_shared_array_buffer_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) + JSValue new_target, + int argc, JSValue *argv) { - uint64_t len; - if (JS_ToIndex(ctx, &len, argv[0])) - return JS_EXCEPTION; - return js_array_buffer_constructor2(ctx, new_target, len, + return js_array_buffer_constructor0(ctx, new_target, argc, argv, JS_CLASS_SHARED_ARRAY_BUFFER); } @@ -52677,7 +51944,7 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) JSObject *p = JS_VALUE_GET_OBJ(val); JSArrayBuffer *abuf = p->u.array_buffer; struct list_head *el, *el1; - + if (abuf) { /* The ArrayBuffer finalizer may be called before the typed array finalizers using it, so abuf->array_list is not @@ -52685,7 +51952,7 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) list_for_each_safe(el, el1, &abuf->array_list) { JSTypedArray *ta; JSObject *p1; - + ta = list_entry(el, JSTypedArray, link); ta->link.prev = NULL; ta->link.next = NULL; @@ -52707,8 +51974,8 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) } static JSValue js_array_buffer_isView(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) + JSValue this_val, + int argc, JSValue *argv) { JSObject *p; BOOL res; @@ -52720,7 +51987,7 @@ static JSValue js_array_buffer_isView(JSContext *ctx, res = TRUE; } } - return JS_NewBool(ctx, res); + return js_bool(res); } static const JSCFunctionListEntry js_array_buffer_funcs[] = { @@ -52733,18 +52000,56 @@ static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx) return JS_ThrowTypeError(ctx, "ArrayBuffer is detached"); } +static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx) +{ + return JS_ThrowTypeError(ctx, "ArrayBuffer is detached or resized"); +} + +// #sec-get-arraybuffer.prototype.detached +static JSValue js_array_buffer_get_detached(JSContext *ctx, + JSValue 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); +} + static JSValue js_array_buffer_get_byteLength(JSContext *ctx, - JSValueConst this_val, + JSValue this_val, int class_id) { JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id); if (!abuf) return JS_EXCEPTION; /* return 0 if detached */ - return JS_NewUint32(ctx, abuf->byte_length); + return js_uint32(abuf->byte_length); } -void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) +static JSValue js_array_buffer_get_maxByteLength(JSContext *ctx, + JSValue this_val, + int class_id) +{ + JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id); + if (!abuf) + return JS_EXCEPTION; + if (array_buffer_is_resizable(abuf)) + return js_uint32(abuf->max_byte_length); + return js_uint32(abuf->byte_length); +} + +static JSValue js_array_buffer_get_resizable(JSContext *ctx, JSValue this_val, + int class_id) +{ + JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id); + if (!abuf) + return JS_EXCEPTION; + return js_bool(array_buffer_is_resizable(abuf)); +} + +void JS_DetachArrayBuffer(JSContext *ctx, JSValue obj) { JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER); struct list_head *el; @@ -52772,7 +52077,7 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) } /* get an ArrayBuffer or SharedArrayBuffer */ -static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj) +static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValue obj) { JSObject *p; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) @@ -52789,7 +52094,7 @@ static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj) /* return NULL if exception. WARNING: any JS call can detach the buffer and render the returned pointer invalid */ -uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj) +uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValue obj) { JSArrayBuffer *abuf = js_get_array_buffer(ctx, obj); if (!abuf) @@ -52805,9 +52110,148 @@ uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj) return NULL; } +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, JSValue this_val, + int argc, JSValue *argv, int magic) +{ + BOOL transfer_to_fixed_length = magic & 1; + JSArrayBuffer *abuf; + uint64_t new_len, old_len, max_len, *pmax_len; + uint8_t *bs, *new_bs; + + abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); + if (!abuf) + return JS_EXCEPTION; + if (abuf->shared) + return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer"); + if (argc < 1 || JS_IsUndefined(argv[0])) + new_len = abuf->byte_length; + else if (JS_ToIndex(ctx, &new_len, argv[0])) + return JS_EXCEPTION; + if (abuf->detached) + return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + pmax_len = NULL; + if (!transfer_to_fixed_length) { + if (array_buffer_is_resizable(abuf)) { // carry over maxByteLength + max_len = abuf->max_byte_length; + if (new_len > max_len) + return JS_ThrowTypeError(ctx, "invalid array buffer length"); + // TODO(bnoordhuis) support externally managed RABs + if (abuf->free_func == js_array_buffer_free) + pmax_len = &max_len; + } + } + /* 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); + } + /* 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, JSValue this_val, + int argc, JSValue *argv, int class_id) +{ + uint32_t size_log2, size_elem; + struct list_head *el; + JSArrayBuffer *abuf; + JSTypedArray *ta; + JSObject *p; + uint8_t *data; + int64_t len; + + abuf = JS_GetOpaque2(ctx, this_val, class_id); + if (!abuf) + return JS_EXCEPTION; + if (JS_ToInt64(ctx, &len, argv[0])) + return JS_EXCEPTION; + if (abuf->detached) + return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (!array_buffer_is_resizable(abuf)) + return JS_ThrowTypeError(ctx, "array buffer is not resizable"); + // TODO(bnoordhuis) support externally managed RABs + if (abuf->free_func != js_array_buffer_free) + return JS_ThrowTypeError(ctx, "external array buffer is not resizable"); + if (len < 0 || len > abuf->max_byte_length) { + bad_length: + return JS_ThrowRangeError(ctx, "invalid array buffer length"); + } + // SABs can only grow and we don't need to realloc because + // js_array_buffer_constructor3 commits all memory upfront; + // regular RABs are resizable both ways and realloc + if (abuf->shared) { + if (len < abuf->byte_length) + goto bad_length; + // Note this is off-spec; there's supposed to be a single atomic + // |byteLength| property that's shared across SABs but we store + // it per SAB instead. That means when thread A calls sab.grow(2) + // at time t0, and thread B calls sab.grow(1) at time t1, we don't + // throw a TypeError in thread B as the spec says we should, + // instead both threads get their own view of the backing memory, + // 2 bytes big in A, and 1 byte big in B + abuf->byte_length = len; + } else { + data = js_realloc(ctx, abuf->data, max_int(len, 1)); + if (!data) + return JS_EXCEPTION; + if (len > abuf->byte_length) + memset(&data[abuf->byte_length], 0, len - abuf->byte_length); + abuf->byte_length = len; + abuf->data = data; + } + data = abuf->data; + // update lengths of all typed arrays backed by this array buffer + list_for_each(el, &abuf->array_list) { + ta = list_entry(el, JSTypedArray, link); + p = ta->obj; + 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); + size_elem = 1 << size_log2; + if (ta->track_rab) { + if (len >= (int64_t)ta->offset + size_elem) { + p->u.array.count = (len - ta->offset) >> size_log2; + p->u.array.u.ptr = &data[ta->offset]; + } + } else { + if (len >= (int64_t)ta->offset + ta->length) { + p->u.array.count = ta->length >> size_log2; + p->u.array.u.ptr = &data[ta->offset]; + } + } + } + return JS_UNDEFINED; +} + static JSValue js_array_buffer_slice(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, int class_id) + JSValue this_val, + int argc, JSValue *argv, int class_id) { JSArrayBuffer *abuf, *new_abuf; int64_t len, start, end, new_len; @@ -52834,11 +52278,11 @@ static JSValue js_array_buffer_slice(JSContext *ctx, return ctor; if (JS_IsUndefined(ctor)) { new_obj = js_array_buffer_constructor2(ctx, JS_UNDEFINED, new_len, - class_id); + NULL, class_id); } else { JSValue args[1]; - args[0] = JS_NewInt64(ctx, new_len); - new_obj = JS_CallConstructor(ctx, ctor, 1, (JSValueConst *)args); + args[0] = js_int64(new_len); + new_obj = JS_CallConstructor(ctx, ctor, 1, args); JS_FreeValue(ctx, ctor); JS_FreeValue(ctx, args[0]); } @@ -52873,7 +52317,13 @@ static JSValue js_array_buffer_slice(JSContext *ctx, static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_ARRAY_BUFFER ), + JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_ARRAY_BUFFER ), + JS_CGETSET_MAGIC_DEF("resizable", js_array_buffer_get_resizable, NULL, JS_CLASS_ARRAY_BUFFER ), + JS_CGETSET_DEF("detached", js_array_buffer_get_detached, NULL ), + JS_CFUNC_MAGIC_DEF("resize", 1, js_array_buffer_resize, JS_CLASS_ARRAY_BUFFER ), JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ), + JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, 0 ), + JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, 1 ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ), }; @@ -52885,40 +52335,39 @@ static const JSCFunctionListEntry js_shared_array_buffer_funcs[] = { static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), + JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), + JS_CGETSET_MAGIC_DEF("growable", js_array_buffer_get_resizable, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), + JS_CFUNC_MAGIC_DEF("grow", 1, js_array_buffer_resize, JS_CLASS_SHARED_ARRAY_BUFFER ), JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ), }; -static JSObject *get_typed_array(JSContext *ctx, - JSValueConst this_val, - int is_dataview) +// 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) { - JSObject *p; - if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) - goto fail; - p = JS_VALUE_GET_OBJ(this_val); - if (is_dataview) { - if (p->class_id != JS_CLASS_DATAVIEW) - goto fail; - } else { - if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY)) { - fail: - JS_ThrowTypeError(ctx, "not a %s", is_dataview ? "DataView" : "TypedArray"); - return NULL; - } - } - return p; -} + JSArrayBuffer *abuf; + JSTypedArray *ta; + int len, size_elem; + int64_t end; -/* WARNING: 'p' must be a typed array */ -static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p) -{ - JSTypedArray *ta = p->u.typed_array; - JSArrayBuffer *abuf = ta->buffer->u.array_buffer; - /* XXX: could simplify test by ensuring that - p->u.array.u.ptr is NULL iff it is detached */ - return abuf->detached; + 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; + len = abuf->byte_length; + if (ta->offset > len) + return TRUE; + if (ta->track_rab) + return FALSE; + if (len < (int64_t)ta->offset + ta->length) + 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 @@ -52930,96 +52379,95 @@ static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p) return ta->length >> size_log2; } -static int validate_typed_array(JSContext *ctx, JSValueConst this_val) +static int validate_typed_array(JSContext *ctx, JSValue this_val) { JSObject *p; - p = get_typed_array(ctx, this_val, 0); + p = get_typed_array(ctx, this_val); if (!p) return -1; - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); return -1; } return 0; } -static JSValue js_typed_array_get_length(JSContext *ctx, - JSValueConst this_val) +static JSValue js_typed_array_get_length(JSContext *ctx, JSValue this_val) { JSObject *p; - p = get_typed_array(ctx, this_val, 0); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; - return JS_NewInt32(ctx, p->u.array.count); + return js_int32(p->u.array.count); } -static JSValue js_typed_array_get_buffer(JSContext *ctx, - JSValueConst this_val, int is_dataview) +static JSValue js_typed_array_get_buffer(JSContext *ctx, JSValue this_val) { JSObject *p; JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; ta = p->u.typed_array; - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); + return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); } -static JSValue js_typed_array_get_byteLength(JSContext *ctx, - JSValueConst this_val, - int is_dataview) +static JSValue js_typed_array_get_byteLength(JSContext *ctx, JSValue this_val) +{ + uint32_t size_log2; + JSTypedArray *ta; + JSObject *p; + + p = get_typed_array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return js_int32(0); + ta = p->u.typed_array; + if (!ta->track_rab) + return js_uint32(ta->length); + size_log2 = typed_array_size_log2(p->class_id); + return js_int64((int64_t)p->u.array.count << size_log2); +} + +static JSValue js_typed_array_get_byteOffset(JSContext *ctx, JSValue this_val) { JSObject *p; JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) { - if (is_dataview) { - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - } else { - return JS_NewInt32(ctx, 0); - } - } + if (typed_array_is_oob(p)) + return js_int32(0); ta = p->u.typed_array; - return JS_NewInt32(ctx, ta->length); + return js_uint32(ta->offset); } -static JSValue js_typed_array_get_byteOffset(JSContext *ctx, - JSValueConst this_val, - int is_dataview) +JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValue *argv, + JSTypedArrayEnum type) { - JSObject *p; - JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) { - if (is_dataview) { - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - } else { - return JS_NewInt32(ctx, 0); - } - } - ta = p->u.typed_array; - return JS_NewInt32(ctx, ta->offset); + if (type < JS_TYPED_ARRAY_UINT8C || type > JS_TYPED_ARRAY_FLOAT64) + return JS_ThrowRangeError(ctx, "invalid typed array type"); + + return js_typed_array_constructor(ctx, JS_UNDEFINED, argc, argv, + JS_CLASS_UINT8C_ARRAY + type); } /* Return the buffer associated to the typed array or an exception if it is not a typed array or if the buffer is detached. pbyte_offset, pbyte_length or pbytes_per_element can be NULL. */ -JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, +JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValue obj, size_t *pbyte_offset, size_t *pbyte_length, size_t *pbytes_per_element) { JSObject *p; JSTypedArray *ta; - p = get_typed_array(ctx, obj, FALSE); + p = get_typed_array(ctx, obj); if (!p) return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); ta = p->u.typed_array; if (pbyte_offset) *pbyte_offset = ta->offset; @@ -53028,11 +52476,39 @@ JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, if (pbytes_per_element) { *pbytes_per_element = 1 << typed_array_size_log2(p->class_id); } - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); + 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, JSValue 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; +} + static JSValue js_typed_array_get_toStringTag(JSContext *ctx, - JSValueConst this_val) + JSValue this_val) { JSObject *p; if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) @@ -53045,28 +52521,29 @@ static JSValue js_typed_array_get_toStringTag(JSContext *ctx, } static JSValue js_typed_array_set_internal(JSContext *ctx, - JSValueConst dst, - JSValueConst src, - JSValueConst off) + JSValue dst, + JSValue src, + JSValue off) { JSObject *p; JSObject *src_p; uint32_t i; - int64_t src_len, offset; + int64_t dst_len, src_len, offset; JSValue val, src_obj = JS_UNDEFINED; - p = get_typed_array(ctx, dst, 0); + p = get_typed_array(ctx, dst); if (!p) goto fail; if (JS_ToInt64Sat(ctx, &offset, off)) goto fail; if (offset < 0) goto range_error; - if (typed_array_is_detached(ctx, p)) { + if (typed_array_is_oob(p)) { detached: - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail; } + dst_len = p->u.array.count; src_obj = JS_ToObject(ctx, src); if (JS_IsException(src_obj)) goto fail; @@ -53079,11 +52556,11 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, JSArrayBuffer *src_abuf = src_ta->buffer->u.array_buffer; int shift = typed_array_size_log2(p->class_id); - if (src_abuf->detached) + if (typed_array_is_oob(src_p)) goto detached; src_len = src_p->u.array.count; - if (offset > (int64_t)(p->u.array.count - src_len)) + if (offset > dst_len - src_len) goto range_error; /* copying between typed objects */ @@ -53099,9 +52576,11 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, } /* otherwise, default behavior is slow but correct */ } else { + // can change |dst| as a side effect; per spec, + // perform the range check against its old length if (js_get_length64(ctx, &src_len, src_obj)) goto fail; - if (offset > (int64_t)(p->u.array.count - src_len)) { + if (offset > dst_len - src_len) { range_error: JS_ThrowRangeError(ctx, "invalid array length"); goto fail; @@ -53111,8 +52590,14 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, val = JS_GetPropertyUint32(ctx, src_obj, i); if (JS_IsException(val)) goto fail; - if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0) + // 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) { goto fail; + } } done: JS_FreeValue(ctx, src_obj); @@ -53122,63 +52607,95 @@ fail: return JS_EXCEPTION; } -static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_at(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; int64_t idx, len; - p = get_typed_array(ctx, this_val, 0); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = p->u.array.count; - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return JS_EXCEPTION; - } - + // note: can change p->u.array.count if (JS_ToInt64Sat(ctx, &idx, argv[0])) return JS_EXCEPTION; - len = p->u.array.count; if (idx < 0) idx = len + idx; - if (idx < 0 || idx >= len) + + if (idx < 0 || idx >= p->u.array.count) return JS_UNDEFINED; - return JS_GetPropertyInt64(ctx, this_val, idx); + + 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; } -static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_with(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, val; JSObject *p; - int64_t idx, len; + int64_t idx; + uint32_t len, oldlen, newlen; - p = get_typed_array(ctx, this_val, /*is_dataview*/0); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + oldlen = p->u.array.count; if (JS_ToInt64Sat(ctx, &idx, argv[0])) return JS_EXCEPTION; - len = p->u.array.count; - if (idx < 0) - idx = len + idx; - if (idx < 0 || idx >= len) - return JS_ThrowRangeError(ctx, "out of bound"); - 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); + 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); + p->class_id, len); if (JS_IsException(arr)) { JS_FreeValue(ctx, val); return JS_EXCEPTION; } - if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { + if (idx < len && JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { JS_FreeValue(ctx, arr); return JS_EXCEPTION; } @@ -53186,61 +52703,26 @@ static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, } static JSValue js_typed_array_set(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) + JSValue this_val, + int argc, JSValue *argv) { - JSValueConst offset = JS_UNDEFINED; + JSValue offset = JS_UNDEFINED; if (argc > 1) { offset = argv[1]; } return js_typed_array_set_internal(ctx, this_val, argv[0], offset); } -static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) +static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int magic) { if (validate_typed_array(ctx, this_val)) return JS_EXCEPTION; return js_create_array_iterator(ctx, this_val, argc, argv, magic); } -/* return < 0 if exception */ -static int js_typed_array_get_length_internal(JSContext *ctx, - JSValueConst obj) -{ - JSObject *p; - p = get_typed_array(ctx, obj, 0); - if (!p) - return -1; - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return -1; - } - return p->u.array.count; -} - -#if 0 -/* validate a typed array and return its length */ -static JSValue js_typed_array___getLength(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - BOOL ignore_detached = JS_ToBool(ctx, argv[1]); - - if (ignore_detached) { - return js_typed_array_get_length(ctx, argv[0]); - } else { - int len; - len = js_typed_array_get_length_internal(ctx, argv[0]); - if (len < 0) - return JS_EXCEPTION; - return JS_NewInt32(ctx, len); - } -} -#endif - -static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, - int argc, JSValueConst *argv) +static JSValue js_typed_array_create(JSContext *ctx, JSValue ctor, + int argc, JSValue *argv) { JSValue ret; int new_len; @@ -53250,12 +52732,12 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, if (JS_IsException(ret)) return ret; /* validate the typed array */ - new_len = js_typed_array_get_length_internal(ctx, ret); + new_len = js_typed_array_get_length_unsafe(ctx, ret); if (new_len < 0) goto fail; if (argc == 1) { /* ensure that it is large enough */ - if (JS_ToLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]))) + if (JS_ToLengthFree(ctx, &len, js_dup(argv[0]))) goto fail; if (new_len < len) { JS_ThrowTypeError(ctx, "TypedArray length is too small"); @@ -53267,26 +52749,17 @@ 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) + JSValue this_val, + int argc, JSValue *argv) { - JSValueConst obj; + JSValue obj; JSObject *p; JSValue ctor, ret; int argc1; obj = argv[0]; - p = get_typed_array(ctx, obj, 0); + p = get_typed_array(ctx, obj); if (!p) return JS_EXCEPTION; ctor = JS_SpeciesConstructor(ctx, obj, JS_UNDEFINED); @@ -53303,12 +52776,12 @@ static JSValue js_typed_array___speciesCreate(JSContext *ctx, return ret; } -static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_from(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { // from(items, mapfn = void 0, this_arg = void 0) - JSValueConst items = argv[0], mapfn, this_arg; - JSValueConst args[2]; + JSValue items = argv[0], mapfn, this_arg; + JSValue args[2]; JSValue stack[2]; JSValue iter, arr, r, v, v2; int64_t k, len; @@ -53340,7 +52813,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, arr = JS_NewArray(ctx); if (JS_IsException(arr)) goto exception; - stack[0] = JS_DupValue(ctx, items); + stack[0] = js_dup(items); if (js_for_of_start(ctx, &stack[1], FALSE)) goto exception; for (k = 0;; k++) { @@ -53359,7 +52832,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, } if (js_get_length64(ctx, &len, arr) < 0) goto exception; - v = JS_NewInt64(ctx, len); + v = js_int64(len); args[0] = v; r = js_typed_array_create(ctx, this_val, 1, args); JS_FreeValue(ctx, v); @@ -53371,7 +52844,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, goto exception; if (mapping) { args[0] = v; - args[1] = JS_NewInt32(ctx, k); + args[1] = js_int32(k); v2 = JS_Call(ctx, mapfn, this_arg, 2, args); JS_FreeValue(ctx, v); v = v2; @@ -53396,20 +52869,20 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, return r; } -static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_of(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue obj; - JSValueConst args[1]; + JSValue args[1]; int i; - args[0] = JS_NewInt32(ctx, argc); + args[0] = js_int32(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_DupValue(ctx, argv[i])) < 0) { + if (JS_SetPropertyUint32(ctx, obj, i, js_dup(argv[i])) < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -53417,15 +52890,18 @@ static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val, return obj; } -static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; - int len, to, from, final, count, shift; + int len, to, from, final, count, shift, space; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) + p = get_typed_array(ctx, this_val); + if (!p) return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = p->u.array.count; if (JS_ToInt32Clamp(ctx, &to, argv[0], 0, len, len)) return JS_EXCEPTION; @@ -53439,34 +52915,39 @@ static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + + // RAB may have been resized by evil .valueOf method + space = p->u.array.count - max_int(to, from); count = min_int(final - from, len - to); + count = min_int(count, space); if (count > 0) { - p = JS_VALUE_GET_OBJ(this_val); - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); shift = typed_array_size_log2(p->class_id); memmove(p->u.array.u.uint8_ptr + (to << shift), p->u.array.u.uint8_ptr + (from << shift), count << shift); } - return JS_DupValue(ctx, this_val); + return js_dup(this_val); } -static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_fill(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; int len, k, final, shift; uint64_t v64; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) + p = get_typed_array(ctx, this_val); + if (!p) return JS_EXCEPTION; - p = JS_VALUE_GET_OBJ(this_val); + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = p->u.array.count; if (p->class_id == JS_CLASS_UINT8C_ARRAY) { int32_t v; - if (JS_ToUint8ClampFree(ctx, &v, JS_DupValue(ctx, argv[0]))) + if (JS_ToUint8ClampFree(ctx, &v, js_dup(argv[0]))) return JS_EXCEPTION; v64 = v; } else if (p->class_id <= JS_CLASS_UINT32_ARRAY) { @@ -53474,14 +52955,17 @@ 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 { double d; if (JS_ToFloat64(ctx, &d, argv[0])) return JS_EXCEPTION; - if (p->class_id == JS_CLASS_FLOAT32_ARRAY) { + if (p->class_id == JS_CLASS_FLOAT16_ARRAY) { + v64 = tofp16(d); + } else if (p->class_id == JS_CLASS_FLOAT32_ARRAY) { union { float f; uint32_t u32; @@ -53507,9 +52991,11 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + + // RAB may have been resized by evil .valueOf method + final = min_int(final, p->u.array.count); shift = typed_array_size_log2(p->class_id); switch(shift) { case 0: @@ -53535,20 +53021,20 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, default: abort(); } - return JS_DupValue(ctx, this_val); + return js_dup(this_val); } -static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int mode) +static JSValue js_typed_array_find(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int mode) { - JSValueConst func, this_arg; - JSValueConst args[3]; + JSValue func, this_arg; + JSValue args[3]; JSValue val, index_val, res; int len, k, end; int dir; val = JS_UNDEFINED; - len = js_typed_array_get_length_internal(ctx, this_val); + len = js_typed_array_get_length_unsafe(ctx, this_val); if (len < 0) goto exception; @@ -53560,18 +53046,17 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, if (argc > 1) this_arg = argv[1]; - if (mode == special_findLast || mode == special_findLastIndex) { + k = 0; + dir = 1; + end = len; + if (mode == ArrayFindLast || mode == ArrayFindLastIndex) { k = len - 1; dir = -1; end = -1; - } else { - k = 0; - dir = 1; - end = len; } for(; k != end; k += dir) { - index_val = JS_NewInt32(ctx, k); + index_val = js_int32(k); val = JS_GetPropertyValue(ctx, this_val, index_val); if (JS_IsException(val)) goto exception; @@ -53582,7 +53067,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, if (JS_IsException(res)) goto exception; if (JS_ToBoolFree(ctx, res)) { - if (mode == special_findIndex || mode == special_findLastIndex) { + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) { JS_FreeValue(ctx, val); return index_val; } else { @@ -53591,8 +53076,8 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, val); } - if (mode == special_findIndex || mode == special_findLastIndex) - return JS_NewInt32(ctx, -1); + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) + return js_int32(-1); else return JS_UNDEFINED; @@ -53605,21 +53090,28 @@ exception: #define special_lastIndexOf 1 #define special_includes -1 -static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int special) +static JSValue js_typed_array_indexOf(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int special) { JSObject *p; int len, tag, is_int, is_bigint, k, stop, inc, res = -1; int64_t v64; double d; float f; + uint16_t hf; + BOOL oob; + + p = get_typed_array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = p->u.array.count; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - goto exception; if (len == 0) goto done; + oob = FALSE; if (special == special_lastIndexOf) { k = len - 1; if (argc > 1) { @@ -53645,23 +53137,37 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } else { k = 0; if (argc > 1) { - if (JS_ToInt32Clamp(ctx, &k, argv[1], 0, len, len)) + if (JS_ToInt32Sat(ctx, &k, argv[1])) goto exception; + if (k < 0) { + k += len; + if (k < 0) + k = 0; + } else if (k > len) { + k = len; + oob = TRUE; + } } stop = len; inc = 1; } - p = JS_VALUE_GET_OBJ(this_val); /* if the array was detached, no need to go further (but no exception is raised) */ - if (typed_array_is_detached(ctx, p)) { + if (typed_array_is_oob(p) || len > p->u.array.count) { /* "includes" scans all the properties, so "undefined" can match */ if (special == special_includes && JS_IsUndefined(argv[0]) && len > 0) - res = 0; + res = oob ? -1 : 0; goto done; } - + + // RAB may have been resized by evil .valueOf method + len = min_int(len, p->u.array.count); + if (len == 0) + goto done; + k = min_int(k, len); + stop = min_int(stop, len); + is_bigint = 0; is_int = 0; /* avoid warning */ v64 = 0; /* avoid warning */ @@ -53673,11 +53179,14 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } else if (tag == JS_TAG_FLOAT64) { d = JS_VALUE_GET_FLOAT64(argv[0]); - v64 = d; - is_int = (v64 == d); - } else if (tag == JS_TAG_BIG_INT) { - JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]); - + if (d >= INT64_MIN && d < 0x1p63) { + v64 = d; + is_int = (v64 == d); + } + } else + if (tag == JS_TAG_BIG_INT) { + JSBigInt *p1 = JS_VALUE_GET_PTR(argv[0]); + if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) { if (bf_get_int64(&v64, &p1->num, 0) != 0) goto done; @@ -53707,7 +53216,9 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, pv = p->u.array.u.uint8_ptr; v = v64; if (inc > 0) { - pp = memchr(pv + k, v, len - k); + pp = NULL; + if (pv) + pp = memchr(pv + k, v, len - k); if (pp) res = pp - pv; } else { @@ -53758,6 +53269,39 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } } break; + case JS_CLASS_FLOAT16_ARRAY: + if (is_bigint) + break; + if (isnan(d)) { + const uint16_t *pv = p->u.array.u.fp16_ptr; + /* special case: indexOf returns -1, includes finds NaN */ + if (special != special_includes) + goto done; + for (; k != stop; k += inc) { + if (isfp16nan(pv[k])) { + res = k; + break; + } + } + } else if (d == 0) { + // special case: includes also finds negative zero + const uint16_t *pv = p->u.array.u.fp16_ptr; + for (; k != stop; k += inc) { + if (isfp16zero(pv[k])) { + res = k; + break; + } + } + } else if (hf = tofp16(d), d == fromfp16(hf)) { + const uint16_t *pv = p->u.array.u.fp16_ptr; + for (; k != stop; k += inc) { + if (pv[k] == hf) { + res = k; + break; + } + } + } + break; case JS_CLASS_FLOAT32_ARRAY: if (is_bigint) break; @@ -53807,15 +53351,12 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, } break; case JS_CLASS_BIG_INT64_ARRAY: - if (is_bigint || (is_math_mode(ctx) && is_int && - v64 >= -MAX_SAFE_INTEGER && - v64 <= MAX_SAFE_INTEGER)) { + if (is_bigint) { goto scan64; } break; case JS_CLASS_BIG_UINT64_ARRAY: - if (is_bigint || (is_math_mode(ctx) && is_int && - v64 >= 0 && v64 <= MAX_SAFE_INTEGER)) { + if (is_bigint) { const uint64_t *pv; uint64_t v; scan64: @@ -53833,48 +53374,55 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, done: if (special == special_includes) - return JS_NewBool(ctx, res >= 0); + return js_bool(res >= 0); else - return JS_NewInt32(ctx, res); + return js_int32(res); exception: return JS_EXCEPTION; } -static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int toLocaleString) +static JSValue js_typed_array_join(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int toLocaleString) { JSValue sep = JS_UNDEFINED, el; StringBuffer b_s, *b = &b_s; - JSString *p = NULL; - int i, n; + JSString *s = NULL; + JSObject *p; + int i, len, oldlen, newlen; int c; - n = js_typed_array_get_length_internal(ctx, this_val); - if (n < 0) - goto exception; + p = get_typed_array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = oldlen = newlen = p->u.array.count; c = ','; /* default separator */ if (!toLocaleString && argc > 0 && !JS_IsUndefined(argv[0])) { sep = JS_ToString(ctx, argv[0]); if (JS_IsException(sep)) goto exception; - p = JS_VALUE_GET_STRING(sep); - if (p->len == 1 && !p->is_wide_char) - c = p->u.str8[0]; + s = JS_VALUE_GET_STRING(sep); + if (s->len == 1 && !s->is_wide_char) + c = s->u.str8[0]; else c = -1; + // ToString(sep) can detach or resize the arraybuffer as a side effect + newlen = p->u.array.count; + len = min_int(len, newlen); } string_buffer_init(ctx, b, 0); /* XXX: optimize with direct access */ - for(i = 0; i < n; i++) { + for(i = 0; i < len; i++) { if (i > 0) { if (c >= 0) { if (string_buffer_putc8(b, c)) goto fail; } else { - if (string_buffer_concat(b, p, 0, p->len)) + if (string_buffer_concat(b, s, 0, s->len)) goto fail; } } @@ -53890,6 +53438,19 @@ static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val, goto fail; } } + + // add extra separators in case RAB was resized by evil .valueOf method + i = max_int(1, newlen); + for(/*empty*/; i < oldlen; i++) { + if (c >= 0) { + if (string_buffer_putc8(b, c)) + goto fail; + } else { + if (string_buffer_concat(b, s, 0, s->len)) + goto fail; + } + } + JS_FreeValue(ctx, sep); return string_buffer_end(b); @@ -53900,13 +53461,13 @@ exception: return JS_EXCEPTION; } -static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_reverse(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; int len; - len = js_typed_array_get_length_internal(ctx, this_val); + len = js_typed_array_get_length_unsafe(ctx, this_val); if (len < 0) return JS_EXCEPTION; if (len > 0) { @@ -53960,20 +53521,20 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val, abort(); } } - return JS_DupValue(ctx, this_val); + return js_dup(this_val); } -static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_toReversed(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, ret; JSObject *p; - p = get_typed_array(ctx, this_val, /*is_dataview*/0); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id); + p->class_id, p->u.array.count); if (JS_IsException(arr)) return JS_EXCEPTION; ret = js_typed_array_reverse(ctx, arr, argc, argv); @@ -53981,18 +53542,21 @@ static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val, return ret; } -static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_slice(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst args[2]; + JSValue args[2]; JSValue arr, val; JSObject *p, *p1; - int n, len, start, final, count, shift; + int n, len, start, final, count, shift, space; arr = JS_UNDEFINED; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - goto exception; + p = get_typed_array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (typed_array_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + len = p->u.array.count; if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) goto exception; @@ -54003,13 +53567,8 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, } count = max_int(final - start, 0); - p = get_typed_array(ctx, this_val, 0); - if (p == NULL) - goto exception; - shift = typed_array_size_log2(p->class_id); - args[0] = this_val; - args[1] = JS_NewInt32(ctx, count); + args[1] = js_int32(count); arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); if (JS_IsException(arr)) goto exception; @@ -54019,19 +53578,26 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, || validate_typed_array(ctx, arr)) goto exception; - p1 = get_typed_array(ctx, arr, 0); + 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_get_length(ctx, p1) >= count && typed_array_get_length(ctx, p) >= start + count) { - memcpy(p1->u.array.u.uint8_ptr, - p->u.array.u.uint8_ptr + (start << shift), - count << shift); + 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); } 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_NewInt32(ctx, start + n)); + val = JS_GetPropertyValue(ctx, this_val, js_int32(start + n)); if (JS_IsException(val)) goto exception; - if (JS_SetPropertyValue(ctx, arr, JS_NewInt32(ctx, n), val, + if (JS_SetPropertyValue(ctx, arr, js_int32(n), val, JS_PROP_THROW) < 0) goto exception; } @@ -54044,44 +53610,56 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } -static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_subarray(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { - JSValueConst args[4]; + JSArrayBuffer *abuf; + JSTypedArray *ta; + JSValue args[4]; JSValue arr, byteOffset, ta_buffer; JSObject *p; int len, start, final, count, shift, offset; - p = get_typed_array(ctx, this_val, 0); + 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; - final = len; if (!JS_IsUndefined(argv[1])) { 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, 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, 0); + ta_buffer = js_typed_array_get_buffer(ctx, this_val); if (JS_IsException(ta_buffer)) goto exception; args[0] = this_val; args[1] = ta_buffer; - args[2] = JS_NewInt32(ctx, offset); - args[3] = JS_NewInt32(ctx, count); + args[2] = js_int32(offset); + args[3] = 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); JS_FreeValue(ctx, ta_buffer); return arr; - exception: return JS_EXCEPTION; } @@ -54139,6 +53717,11 @@ static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) { return (y < x) - (y > x); } +static int js_TA_cmp_float16(const void *a, const void *b, void *opaque) { + return js_cmp_doubles(fromfp16(*(const uint16_t *)a), + fromfp16(*(const uint16_t *)b)); +} + static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) { return js_cmp_doubles(*(const float *)a, *(const float *)b); } @@ -54148,27 +53731,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_NewInt32(ctx, *(const int8_t *)a); + return js_int32(*(const int8_t *)a); } static JSValue js_TA_get_uint8(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const uint8_t *)a); + return js_int32(*(const uint8_t *)a); } static JSValue js_TA_get_int16(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const int16_t *)a); + return js_int32(*(const int16_t *)a); } static JSValue js_TA_get_uint16(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const uint16_t *)a); + return js_int32(*(const uint16_t *)a); } static JSValue js_TA_get_int32(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const int32_t *)a); + return js_int32(*(const int32_t *)a); } static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) { - return JS_NewUint32(ctx, *(const uint32_t *)a); + return js_uint32(*(const uint32_t *)a); } static JSValue js_TA_get_int64(JSContext *ctx, const void *a) { @@ -54179,21 +53762,24 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) { return JS_NewBigUint64(ctx, *(uint64_t *)a); } +static JSValue js_TA_get_float16(JSContext *ctx, const void *a) { + return js_float64(fromfp16(*(const uint16_t *)a)); +} + static JSValue js_TA_get_float32(JSContext *ctx, const void *a) { - return __JS_NewFloat64(ctx, *(const float *)a); + return js_float64(*(const float *)a); } static JSValue js_TA_get_float64(JSContext *ctx, const void *a) { - return __JS_NewFloat64(ctx, *(const double *)a); + return js_float64(*(const double *)a); } struct TA_sort_context { JSContext *ctx; - int exception; /* 1 = exception, 2 = detached typed array */ - JSValueConst arr; - JSValueConst cmp; + int exception; + JSValue arr; + JSValue cmp; JSValue (*getfun)(JSContext *ctx, const void *a); - uint8_t *array_ptr; /* cannot change unless the array is detached */ int elt_size; }; @@ -54201,19 +53787,24 @@ 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; - JSValueConst argv[2]; + JSValue argv[2]; JSValue res; + JSObject *p; int cmp; + p = JS_VALUE_GET_OBJ(psc->arr); + if (typed_array_is_oob(p)) + return 0; + 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; - argv[0] = psc->getfun(ctx, psc->array_ptr + + if (a_idx >= p->u.array.count || b_idx >= p->u.array.count) + return 0; + argv[0] = psc->getfun(ctx, (char *)p->u.array.u.ptr + a_idx * (size_t)psc->elt_size); - argv[1] = psc->getfun(ctx, psc->array_ptr + + argv[1] = psc->getfun(ctx, (char *)p->u.array.u.ptr + b_idx * (size_t)(psc->elt_size)); res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv); if (JS_IsException(res)) { @@ -54236,27 +53827,28 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { /* make sort stable: compare array offsets */ cmp = (a_idx > b_idx) - (a_idx < b_idx); } - if (unlikely(typed_array_is_detached(ctx, - JS_VALUE_GET_PTR(psc->arr)))) { - psc->exception = 2; - } done: - JS_FreeValue(ctx, (JSValue)argv[0]); - JS_FreeValue(ctx, (JSValue)argv[1]); + JS_FreeValue(ctx, argv[0]); + JS_FreeValue(ctx, argv[1]); } return cmp; } -static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_sort(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSObject *p; int len; size_t elt_size; struct TA_sort_context tsc; - void *array_ptr; 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; @@ -54264,12 +53856,9 @@ 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_internal(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; @@ -54304,6 +53893,10 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, tsc.getfun = js_TA_get_uint64; cmpfun = js_TA_cmp_uint64; break; + case JS_CLASS_FLOAT16_ARRAY: + tsc.getfun = js_TA_get_float16; + cmpfun = js_TA_cmp_float16; + break; case JS_CLASS_FLOAT32_ARRAY: tsc.getfun = js_TA_get_float32; cmpfun = js_TA_cmp_float32; @@ -54315,86 +53908,87 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, default: abort(); } - array_ptr = p->u.array.u.ptr; elt_size = 1 << typed_array_size_log2(p->class_id); if (!JS_IsUndefined(tsc.cmp)) { uint32_t *array_idx; void *array_tmp; size_t i, j; - + /* XXX: a stable sort would use less memory */ array_idx = js_malloc(ctx, len * sizeof(array_idx[0])); if (!array_idx) return JS_EXCEPTION; for(i = 0; i < len; i++) array_idx[i] = i; - tsc.array_ptr = array_ptr; tsc.elt_size = elt_size; rqsort(array_idx, len, sizeof(array_idx[0]), js_TA_cmp_generic, &tsc); - if (tsc.exception) { - if (tsc.exception == 1) - goto fail; - /* detached typed array during the sort: no error */ - } else { - 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); + 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]; + } + break; + default: + abort(); + } + js_free(ctx, array_tmp); + done: js_free(ctx, array_idx); } else { - rqsort(array_ptr, len, elt_size, cmpfun, &tsc); + rqsort(p->u.array.u.ptr, len, elt_size, cmpfun, &tsc); if (tsc.exception) return JS_EXCEPTION; } } - return JS_DupValue(ctx, this_val); + return js_dup(this_val); } -static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_typed_array_toSorted(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { JSValue arr, ret; JSObject *p; - p = get_typed_array(ctx, this_val, /*is_dataview*/0); + p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id); + p->class_id, p->u.array.count); if (JS_IsException(arr)) return JS_EXCEPTION; ret = js_typed_array_sort(ctx, arr, argc, argv); @@ -54406,18 +54000,15 @@ static const JSCFunctionListEntry js_typed_array_base_funcs[] = { JS_CFUNC_DEF("from", 1, js_typed_array_from ), JS_CFUNC_DEF("of", 0, js_typed_array_of ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), - //JS_CFUNC_DEF("__getLength", 2, js_typed_array___getLength ), - //JS_CFUNC_DEF("__create", 2, js_typed_array___create ), - //JS_CFUNC_DEF("__speciesCreate", 2, js_typed_array___speciesCreate ), }; static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { JS_CGETSET_DEF("length", js_typed_array_get_length, NULL ), JS_CFUNC_DEF("at", 1, js_typed_array_at ), JS_CFUNC_DEF("with", 2, js_typed_array_with ), - JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 0 ), - JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 0 ), - JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 0 ), + JS_CGETSET_DEF("buffer", js_typed_array_get_buffer, NULL ), + JS_CGETSET_DEF("byteLength", js_typed_array_get_byteLength, NULL ), + JS_CGETSET_DEF("byteOffset", js_typed_array_get_byteOffset, NULL ), JS_CFUNC_DEF("set", 1, js_typed_array_set ), JS_CFUNC_MAGIC_DEF("values", 0, js_create_typed_array_iterator, JS_ITERATOR_KIND_VALUE ), JS_ALIAS_DEF("[Symbol.iterator]", "values" ), @@ -54433,10 +54024,10 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce | special_TA ), JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight | special_TA ), JS_CFUNC_DEF("fill", 1, js_typed_array_fill ), - JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, special_find ), - JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, special_findIndex ), - JS_CFUNC_MAGIC_DEF("findLast", 1, js_typed_array_find, special_findLast ), - JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_typed_array_find, special_findLastIndex ), + JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, ArrayFind ), + JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, ArrayFindIndex ), + JS_CFUNC_MAGIC_DEF("findLast", 1, js_typed_array_find, ArrayFindLast ), + JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_typed_array_find, ArrayFindLastIndex ), JS_CFUNC_DEF("reverse", 0, js_typed_array_reverse ), JS_CFUNC_DEF("toReversed", 0, js_typed_array_toReversed ), JS_CFUNC_DEF("slice", 2, js_typed_array_slice ), @@ -54452,15 +54043,15 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { }; static JSValue js_typed_array_base_constructor(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) + JSValue this_val, + int argc, JSValue *argv) { return JS_ThrowTypeError(ctx, "cannot be called"); } /* 'obj' must be an allocated typed array object */ -static int typed_array_init(JSContext *ctx, JSValueConst obj, - JSValue buffer, uint64_t offset, uint64_t len) +static int typed_array_init(JSContext *ctx, JSValue obj, JSValue buffer, + uint64_t offset, uint64_t len, BOOL track_rab) { JSTypedArray *ta; JSObject *p, *pbuffer; @@ -54480,6 +54071,7 @@ static int typed_array_init(JSContext *ctx, JSValueConst obj, ta->buffer = pbuffer; ta->offset = offset; ta->length = len << size_log2; + ta->track_rab = track_rab; list_add_tail(&ta->link, &abuf->array_list); p->u.typed_array = ta; p->u.array.count = len; @@ -54489,7 +54081,7 @@ static int typed_array_init(JSContext *ctx, JSValueConst obj, static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen, - JSValueConst obj, JSValueConst method) + JSValue obj, JSValue method) { JSValue arr, iter, next_method = JS_UNDEFINED, val; BOOL done; @@ -54530,8 +54122,8 @@ static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen, } static JSValue js_typed_array_constructor_obj(JSContext *ctx, - JSValueConst new_target, - JSValueConst obj, + JSValue new_target, + JSValue obj, int classid) { JSValue iter, ret, arr = JS_UNDEFINED, val, buffer; @@ -54557,14 +54149,15 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx, } else { if (js_get_length64(ctx, &len, obj)) goto fail; - arr = JS_DupValue(ctx, obj); + arr = js_dup(obj); } buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - len << size_log2); + len << size_log2, + NULL); if (JS_IsException(buffer)) goto fail; - if (typed_array_init(ctx, ret, buffer, 0, len)) + if (typed_array_init(ctx, ret, buffer, 0, len, /*track_rab*/FALSE)) goto fail; for(i = 0; i < len; i++) { @@ -54583,14 +54176,14 @@ static JSValue js_typed_array_constructor_obj(JSContext *ctx, } static JSValue js_typed_array_constructor_ta(JSContext *ctx, - JSValueConst new_target, - JSValueConst src_obj, - int classid) + JSValue new_target, + JSValue src_obj, + int classid, uint32_t len) { JSObject *p, *src_buffer; JSTypedArray *ta; JSValue obj, buffer; - uint32_t len, i; + uint32_t i; int size_log2; JSArrayBuffer *src_abuf, *abuf; @@ -54598,27 +54191,27 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, if (JS_IsException(obj)) return obj; p = JS_VALUE_GET_OBJ(src_obj); - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail; } ta = p->u.typed_array; - len = p->u.array.count; src_buffer = ta->buffer; src_abuf = src_buffer->u.array_buffer; size_log2 = typed_array_size_log2(classid); buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - (uint64_t)len << size_log2); + (uint64_t)len << size_log2, + NULL); if (JS_IsException(buffer)) goto fail; /* necessary because it could have been detached */ - if (typed_array_is_detached(ctx, p)) { + if (typed_array_is_oob(p)) { JS_FreeValue(ctx, buffer); - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail; } abuf = JS_GetOpaque(buffer, JS_CLASS_ARRAY_BUFFER); - if (typed_array_init(ctx, obj, buffer, 0, len)) + if (typed_array_init(ctx, obj, buffer, 0, len, /*track_rab*/FALSE)) goto fail; if (p->class_id == classid) { /* same type: copy the content */ @@ -54640,10 +54233,11 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, } static JSValue js_typed_array_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv, + JSValue new_target, + int argc, JSValue *argv, int classid) { + BOOL track_rab = FALSE; JSValue buffer, obj; JSArrayBuffer *abuf; int size_log2; @@ -54654,7 +54248,8 @@ static JSValue js_typed_array_constructor(JSContext *ctx, if (JS_ToIndex(ctx, &len, argv[0])) return JS_EXCEPTION; buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - len << size_log2); + len << size_log2, + NULL); if (JS_IsException(buffer)) return JS_EXCEPTION; offset = 0; @@ -54671,8 +54266,10 @@ static JSValue js_typed_array_constructor(JSContext *ctx, offset > abuf->byte_length) return JS_ThrowRangeError(ctx, "invalid offset"); if (JS_IsUndefined(argv[2])) { - if ((abuf->byte_length & ((1 << size_log2) - 1)) != 0) - goto invalid_length; + track_rab = array_buffer_is_resizable(abuf); + if (!track_rab) + if ((abuf->byte_length & ((1 << size_log2) - 1)) != 0) + goto invalid_length; len = (abuf->byte_length - offset) >> size_log2; } else { if (JS_ToIndex(ctx, &len, argv[2])) @@ -54684,11 +54281,12 @@ static JSValue js_typed_array_constructor(JSContext *ctx, return JS_ThrowRangeError(ctx, "invalid length"); } } - buffer = JS_DupValue(ctx, argv[0]); + buffer = js_dup(argv[0]); } else { 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); + return js_typed_array_constructor_ta(ctx, new_target, argv[0], + classid, p->u.array.count); } else { return js_typed_array_constructor_obj(ctx, new_target, argv[0], classid); } @@ -54700,7 +54298,7 @@ static JSValue js_typed_array_constructor(JSContext *ctx, JS_FreeValue(ctx, buffer); return JS_EXCEPTION; } - if (typed_array_init(ctx, obj, buffer, offset, len)) { + if (typed_array_init(ctx, obj, buffer, offset, len, track_rab)) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -54722,7 +54320,7 @@ static void js_typed_array_finalizer(JSRuntime *rt, JSValue val) } } -static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, +static void js_typed_array_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); @@ -54733,13 +54331,15 @@ static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, } static JSValue js_dataview_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) + JSValue new_target, + int argc, JSValue *argv) { + BOOL recompute_len = FALSE; + BOOL track_rab = FALSE; JSArrayBuffer *abuf; uint64_t offset; uint32_t len; - JSValueConst buffer; + JSValue buffer; JSValue obj; JSTypedArray *ta; JSObject *p; @@ -54765,6 +54365,9 @@ static JSValue js_dataview_constructor(JSContext *ctx, if (l > len) return JS_ThrowRangeError(ctx, "invalid byteLength"); len = l; + } else { + recompute_len = TRUE; + track_rab = array_buffer_is_resizable(abuf); } obj = js_create_from_ctor(ctx, new_target, JS_CLASS_DATAVIEW); @@ -54775,6 +54378,16 @@ static JSValue js_dataview_constructor(JSContext *ctx, JS_ThrowTypeErrorDetachedArrayBuffer(ctx); goto fail; } + // RAB could have been resized in js_create_from_ctor() + if (offset > abuf->byte_length) { + goto out_of_bound; + } else if (recompute_len) { + len = abuf->byte_length - offset; + } else if (offset + len > abuf->byte_length) { + out_of_bound: + JS_ThrowRangeError(ctx, "invalid byteOffset or byteLength"); + goto fail; + } ta = js_malloc(ctx, sizeof(*ta)); if (!ta) { fail: @@ -54783,21 +54396,99 @@ static JSValue js_dataview_constructor(JSContext *ctx, } p = JS_VALUE_GET_OBJ(obj); ta->obj = p; - ta->buffer = JS_VALUE_GET_OBJ(JS_DupValue(ctx, buffer)); + ta->buffer = JS_VALUE_GET_OBJ(js_dup(buffer)); ta->offset = offset; ta->length = len; + ta->track_rab = track_rab; list_add_tail(&ta->link, &abuf->array_list); p->u.typed_array = ta; return obj; } +// is the DataView out of bounds relative to its parent arraybuffer? +static BOOL dataview_is_oob(JSObject *p) +{ + JSArrayBuffer *abuf; + JSTypedArray *ta; + + assert(p->class_id == JS_CLASS_DATAVIEW); + ta = p->u.typed_array; + abuf = ta->buffer->u.array_buffer; + if (abuf->detached) + return TRUE; + if (ta->offset > abuf->byte_length) + return TRUE; + if (ta->track_rab) + return FALSE; + return (int64_t)ta->offset + ta->length > abuf->byte_length; +} + +static JSObject *get_dataview(JSContext *ctx, JSValue this_val) +{ + 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_DATAVIEW) { + fail: + JS_ThrowTypeError(ctx, "not a DataView"); + return NULL; + } + return p; +} + +static JSValue js_dataview_get_buffer(JSContext *ctx, JSValue this_val) +{ + JSObject *p; + JSTypedArray *ta; + p = get_dataview(ctx, this_val); + if (!p) + return JS_EXCEPTION; + ta = p->u.typed_array; + return js_dup(JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); +} + +static JSValue js_dataview_get_byteLength(JSContext *ctx, JSValue this_val) +{ + JSArrayBuffer *abuf; + JSTypedArray *ta; + JSObject *p; + + p = get_dataview(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (dataview_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + 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_uint32(ta->length); +} + +static JSValue js_dataview_get_byteOffset(JSContext *ctx, JSValue this_val) +{ + JSTypedArray *ta; + JSObject *p; + + p = get_dataview(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (dataview_is_oob(p)) + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + ta = p->u.typed_array; + return js_uint32(ta->offset); +} + static JSValue js_dataview_getValue(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int class_id) + JSValue this_obj, + int argc, JSValue *argv, int class_id) { JSTypedArray *ta; JSArrayBuffer *abuf; - int is_swap, size; + BOOL littleEndian, is_swap; + int size; uint8_t *ptr; uint32_t v; uint64_t pos; @@ -54808,44 +54499,46 @@ static JSValue js_dataview_getValue(JSContext *ctx, size = 1 << typed_array_size_log2(class_id); if (JS_ToIndex(ctx, &pos, argv[0])) return JS_EXCEPTION; - is_swap = FALSE; - if (argc > 1) - is_swap = JS_ToBool(ctx, argv[1]); -#ifndef WORDS_BIGENDIAN - is_swap ^= 1; -#endif + littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]); + is_swap = littleEndian ^ !is_be(); abuf = ta->buffer->u.array_buffer; if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + // order matters: this check should come before the next one if ((pos + size) > ta->length) return JS_ThrowRangeError(ctx, "out of bound"); + // test262 expects a TypeError for this and V8, in its infinite wisdom, + // throws a "detached array buffer" exception, but IMO that doesn't make + // sense because the buffer is not in fact detached, it's still there + if ((int64_t)ta->offset + ta->length > abuf->byte_length) + return JS_ThrowTypeError(ctx, "out of bound"); ptr = abuf->data + ta->offset + pos; switch(class_id) { case JS_CLASS_INT8_ARRAY: - return JS_NewInt32(ctx, *(int8_t *)ptr); + return js_int32(*(int8_t *)ptr); case JS_CLASS_UINT8_ARRAY: - return JS_NewInt32(ctx, *(uint8_t *)ptr); + return js_int32(*(uint8_t *)ptr); case JS_CLASS_INT16_ARRAY: v = get_u16(ptr); if (is_swap) v = bswap16(v); - return JS_NewInt32(ctx, (int16_t)v); + return js_int32((int16_t)v); case JS_CLASS_UINT16_ARRAY: v = get_u16(ptr); if (is_swap) v = bswap16(v); - return JS_NewInt32(ctx, v); + return js_int32(v); case JS_CLASS_INT32_ARRAY: v = get_u32(ptr); if (is_swap) v = bswap32(v); - return JS_NewInt32(ctx, v); + return js_int32(v); case JS_CLASS_UINT32_ARRAY: v = get_u32(ptr); if (is_swap) v = bswap32(v); - return JS_NewUint32(ctx, v); + return js_uint32(v); case JS_CLASS_BIG_INT64_ARRAY: { uint64_t v; @@ -54864,6 +54557,14 @@ static JSValue js_dataview_getValue(JSContext *ctx, return JS_NewBigUint64(ctx, v); } break; + case JS_CLASS_FLOAT16_ARRAY: + { + uint16_t v; + v = get_u16(ptr); + if (is_swap) + v = bswap16(v); + return js_float64(fromfp16(v)); + } case JS_CLASS_FLOAT32_ARRAY: { union { @@ -54874,7 +54575,7 @@ static JSValue js_dataview_getValue(JSContext *ctx, if (is_swap) v = bswap32(v); u.i = v; - return __JS_NewFloat64(ctx, u.f); + return js_float64(u.f); } case JS_CLASS_FLOAT64_ARRAY: { @@ -54885,25 +54586,27 @@ static JSValue js_dataview_getValue(JSContext *ctx, u.i = get_u64(ptr); if (is_swap) u.i = bswap64(u.i); - return __JS_NewFloat64(ctx, u.f); + return js_float64(u.f); } default: abort(); } + return JS_EXCEPTION; // pacify compiler } static JSValue js_dataview_setValue(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int class_id) + JSValue this_obj, + int argc, JSValue *argv, int class_id) { JSTypedArray *ta; JSArrayBuffer *abuf; - int is_swap, size; + BOOL littleEndian, is_swap; + int size; uint8_t *ptr; uint64_t v64; uint32_t v; uint64_t pos; - JSValueConst val; + JSValue val; ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW); if (!ta) @@ -54917,14 +54620,17 @@ static JSValue js_dataview_setValue(JSContext *ctx, if (class_id <= JS_CLASS_UINT32_ARRAY) { if (JS_ToUint32(ctx, &v, val)) return JS_EXCEPTION; - } else if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) { + } else + if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) { if (JS_ToBigInt64(ctx, (int64_t *)&v64, val)) return JS_EXCEPTION; } else { double d; if (JS_ToFloat64(ctx, &d, val)) return JS_EXCEPTION; - if (class_id == JS_CLASS_FLOAT32_ARRAY) { + if (class_id == JS_CLASS_FLOAT16_ARRAY) { + v = tofp16(d); + } else if (class_id == JS_CLASS_FLOAT32_ARRAY) { union { float f; uint32_t i; @@ -54937,17 +54643,19 @@ static JSValue js_dataview_setValue(JSContext *ctx, v64 = u.u64; } } - is_swap = FALSE; - if (argc > 2) - is_swap = JS_ToBool(ctx, argv[2]); -#ifndef WORDS_BIGENDIAN - is_swap ^= 1; -#endif + littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]); + is_swap = littleEndian ^ !is_be(); abuf = ta->buffer->u.array_buffer; if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + // order matters: this check should come before the next one if ((pos + size) > ta->length) return JS_ThrowRangeError(ctx, "out of bound"); + // test262 expects a TypeError for this and V8, in its infinite wisdom, + // throws a "detached array buffer" exception, but IMO that doesn't make + // sense because the buffer is not in fact detached, it's still there + if ((int64_t)ta->offset + ta->length > abuf->byte_length) + return JS_ThrowTypeError(ctx, "out of bound"); ptr = abuf->data + ta->offset + pos; switch(class_id) { @@ -54957,6 +54665,7 @@ static JSValue js_dataview_setValue(JSContext *ctx, break; case JS_CLASS_INT16_ARRAY: case JS_CLASS_UINT16_ARRAY: + case JS_CLASS_FLOAT16_ARRAY: if (is_swap) v = bswap16(v); put_u16(ptr, v); @@ -54982,9 +54691,9 @@ static JSValue js_dataview_setValue(JSContext *ctx, } static const JSCFunctionListEntry js_dataview_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 1 ), - JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 1 ), - JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 1 ), + JS_CGETSET_DEF("buffer", js_dataview_get_buffer, NULL ), + JS_CGETSET_DEF("byteLength", js_dataview_get_byteLength, NULL ), + JS_CGETSET_DEF("byteOffset", js_dataview_get_byteOffset, NULL ), JS_CFUNC_MAGIC_DEF("getInt8", 1, js_dataview_getValue, JS_CLASS_INT8_ARRAY ), JS_CFUNC_MAGIC_DEF("getUint8", 1, js_dataview_getValue, JS_CLASS_UINT8_ARRAY ), JS_CFUNC_MAGIC_DEF("getInt16", 1, js_dataview_getValue, JS_CLASS_INT16_ARRAY ), @@ -54993,6 +54702,7 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ), JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ), JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ), + JS_CFUNC_MAGIC_DEF("getFloat16", 1, js_dataview_getValue, JS_CLASS_FLOAT16_ARRAY ), JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ), JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ), JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ), @@ -55003,11 +54713,62 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ), JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ), JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ), + JS_CFUNC_MAGIC_DEF("setFloat16", 2, js_dataview_setValue, JS_CLASS_FLOAT16_ARRAY ), JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ), JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ), 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, + JS_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(JSValue obj) +{ + JSClassID class_id = JS_GetClassID(obj); + if (class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY) + return class_id - JS_CLASS_UINT8C_ARRAY; + else + return -1; +} + /* Atomics */ #ifdef CONFIG_ATOMICS @@ -55025,7 +54786,7 @@ typedef enum AtomicsOpEnum { static void *js_atomics_get_ptr(JSContext *ctx, JSArrayBuffer **pabuf, int *psize_log2, JSClassID *pclass_id, - JSValueConst obj, JSValueConst idx_val, + JSValue obj, JSValue idx_val, int is_waitable) { JSObject *p; @@ -55082,8 +54843,8 @@ static void *js_atomics_get_ptr(JSContext *ctx, } static JSValue js_atomics_op(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int op) + JSValue this_obj, + int argc, JSValue *argv, int op) { int size_log2; uint64_t v, a, rep_val; @@ -55111,36 +54872,35 @@ 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); } switch(op | (size_log2 << 3)) { - + #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) @@ -55150,43 +54910,42 @@ 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; @@ -55209,10 +54968,10 @@ static JSValue js_atomics_op(JSContext *ctx, goto done; case JS_CLASS_INT32_ARRAY: done: - ret = JS_NewInt32(ctx, a); + ret = js_int32(a); break; case JS_CLASS_UINT32_ARRAY: - ret = JS_NewUint32(ctx, a); + ret = js_uint32(a); break; case JS_CLASS_BIG_INT64_ARRAY: ret = JS_NewBigInt64(ctx, a); @@ -55227,8 +54986,8 @@ static JSValue js_atomics_op(JSContext *ctx, } static JSValue js_atomics_store(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) + JSValue this_obj, + int argc, JSValue *argv) { int size_log2; void *ptr; @@ -55241,7 +55000,7 @@ static JSValue js_atomics_store(JSContext *ctx, return JS_EXCEPTION; if (size_log2 == 3) { int64_t v64; - ret = JS_ToBigIntValueFree(ctx, JS_DupValue(ctx, argv[2])); + ret = JS_ToBigIntValueFree(ctx, js_dup(argv[2])); if (JS_IsException(ret)) return ret; if (JS_ToBigInt64(ctx, &v64, ret)) { @@ -55250,11 +55009,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_DupValue(ctx, argv[2])); + ret = JS_ToIntegerFree(ctx, js_dup(argv[2])); if (JS_IsException(ret)) return ret; if (JS_ToUint32(ctx, &v, ret)) { @@ -55265,13 +55024,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(); @@ -55281,36 +55040,62 @@ static JSValue js_atomics_store(JSContext *ctx, } static JSValue js_atomics_isLockFree(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) + JSValue this_obj, + int argc, JSValue *argv) { int v, ret; if (JS_ToInt32Sat(ctx, &v, argv[0])) return JS_EXCEPTION; ret = (v == 1 || v == 2 || v == 4 || v == 8); - return JS_NewBool(ctx, ret); + return js_bool(ret); } typedef struct JSAtomicsWaiter { struct list_head link; BOOL linked; - pthread_cond_t cond; + js_cond_t cond; int32_t *ptr; } JSAtomicsWaiter; -static pthread_mutex_t js_atomics_mutex = PTHREAD_MUTEX_INITIALIZER; +static js_once_t js_atomics_once = JS_ONCE_INIT; +static js_mutex_t js_atomics_mutex; static struct list_head js_atomics_waiter_list = LIST_HEAD_INIT(js_atomics_waiter_list); +// 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 +static JSValue js_atomics_pause(JSContext *ctx, JSValue this_obj, + int argc, JSValue *argv) +{ + double d; + + if (argc > 0) { + switch (JS_VALUE_GET_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)) + if (0 == modf(d, &d)) + break; + // fallthru + default: + return JS_ThrowTypeError(ctx, "not an integral number"); + case JS_TAG_UNDEFINED: + case JS_TAG_INT: + break; + } + } + return JS_UNDEFINED; +} + static JSValue js_atomics_wait(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) + JSValue this_obj, + int argc, JSValue *argv) { int64_t v; int32_t v32; void *ptr; int64_t timeout; - struct timespec ts; JSAtomicsWaiter waiter_s, *waiter; int ret, size_log2, res; double d; @@ -55322,14 +55107,14 @@ static JSValue js_atomics_wait(JSContext *ctx, if (size_log2 == 3) { if (JS_ToBigInt64(ctx, &v, argv[2])) return JS_EXCEPTION; - } else { + } else { if (JS_ToInt32(ctx, &v32, argv[2])) return JS_EXCEPTION; v = v32; } if (JS_ToFloat64(ctx, &d, argv[3])) return JS_EXCEPTION; - if (isnan(d) || d > INT64_MAX) + if (isnan(d) || d >= 0x1p63) timeout = INT64_MAX; else if (d < 0) timeout = 0; @@ -55340,44 +55125,34 @@ static JSValue js_atomics_wait(JSContext *ctx, /* XXX: inefficient if large number of waiters, should hash on 'ptr' value */ - /* XXX: use Linux futexes when available ? */ - pthread_mutex_lock(&js_atomics_mutex); + js_mutex_lock(&js_atomics_mutex); if (size_log2 == 3) { res = *(int64_t *)ptr != v; } else { res = *(int32_t *)ptr != v; } if (res) { - pthread_mutex_unlock(&js_atomics_mutex); + js_mutex_unlock(&js_atomics_mutex); return JS_AtomToString(ctx, JS_ATOM_not_equal); } waiter = &waiter_s; waiter->ptr = ptr; - pthread_cond_init(&waiter->cond, NULL); + js_cond_init(&waiter->cond); waiter->linked = TRUE; list_add_tail(&waiter->link, &js_atomics_waiter_list); if (timeout == INT64_MAX) { - pthread_cond_wait(&waiter->cond, &js_atomics_mutex); + js_cond_wait(&waiter->cond, &js_atomics_mutex); ret = 0; } else { - /* 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); + ret = js_cond_timedwait(&waiter->cond, &js_atomics_mutex, timeout * 1e6 /* to ns */); } if (waiter->linked) list_del(&waiter->link); - pthread_mutex_unlock(&js_atomics_mutex); - pthread_cond_destroy(&waiter->cond); - if (ret == ETIMEDOUT) { + js_mutex_unlock(&js_atomics_mutex); + js_cond_destroy(&waiter->cond); + if (ret == -1) { return JS_AtomToString(ctx, JS_ATOM_timed_out); } else { return JS_AtomToString(ctx, JS_ATOM_ok); @@ -55385,8 +55160,8 @@ static JSValue js_atomics_wait(JSContext *ctx, } static JSValue js_atomics_notify(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) + JSValue this_obj, + int argc, JSValue *argv) { struct list_head *el, *el1, waiter_list; int32_t count, n; @@ -55409,7 +55184,7 @@ static JSValue js_atomics_notify(JSContext *ctx, n = 0; if (abuf->shared && count > 0) { - pthread_mutex_lock(&js_atomics_mutex); + js_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); @@ -55424,11 +55199,11 @@ static JSValue js_atomics_notify(JSContext *ctx, } list_for_each(el, &waiter_list) { waiter = list_entry(el, JSAtomicsWaiter, link); - pthread_cond_signal(&waiter->cond); + js_cond_signal(&waiter->cond); } - pthread_mutex_unlock(&js_atomics_mutex); + js_mutex_unlock(&js_atomics_mutex); } - return JS_NewInt32(ctx, n); + return js_int32(n); } static const JSCFunctionListEntry js_atomics_funcs[] = { @@ -55442,6 +55217,7 @@ static const JSCFunctionListEntry js_atomics_funcs[] = { JS_CFUNC_MAGIC_DEF("load", 2, js_atomics_op, ATOMICS_OP_LOAD ), JS_CFUNC_DEF("store", 3, js_atomics_store ), JS_CFUNC_DEF("isLockFree", 1, js_atomics_isLockFree ), + JS_CFUNC_DEF("pause", 0, js_atomics_pause ), JS_CFUNC_DEF("wait", 4, js_atomics_wait ), JS_CFUNC_DEF("notify", 3, js_atomics_notify ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Atomics", JS_PROP_CONFIGURABLE ), @@ -55451,8 +55227,15 @@ 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) { + 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)); } @@ -55462,7 +55245,7 @@ void JS_AddIntrinsicAtomics(JSContext *ctx) void JS_AddIntrinsicTypedArrays(JSContext *ctx) { JSValue typed_array_base_proto, typed_array_base_func; - JSValueConst array_buffer_func, shared_array_buffer_func; + JSValue array_buffer_func, shared_array_buffer_func; int i; ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx); @@ -55507,6 +55290,8 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx) countof(js_typed_array_base_funcs)); JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto); + /* 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]; @@ -55515,17 +55300,17 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx) ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto); JS_DefinePropertyValueStr(ctx, ctx->class_proto[i], "BYTES_PER_ELEMENT", - JS_NewInt32(ctx, 1 << typed_array_size_log2(i)), + js_int32(1 << typed_array_size_log2(i)), 0); name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY); - func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_typed_array_constructor, + 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_NewInt32(ctx, 1 << typed_array_size_log2(i)), + js_int32(1 << typed_array_size_log2(i)), 0); } JS_FreeValue(ctx, typed_array_base_proto); @@ -55544,3 +55329,790 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx) JS_AddIntrinsicAtomics(ctx); #endif } + +/* Performance */ + +static double js__now_ms(void) +{ + return js__hrtime_ns() / 1e6; +} + +static JSValue js_perf_now(JSContext *ctx, JSValue this_val, int argc, JSValue *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, JSValue op1, JSValue op2) +{ + JSValue sp[2] = { js_dup(op1), js_dup(op2) }; + if (js_eq_slow(ctx, endof(sp), 0)) + return -1; + return JS_VALUE_GET_BOOL(sp[0]); +} + +JS_BOOL JS_IsStrictEqual(JSContext *ctx, JSValue op1, JSValue op2) +{ + return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_STRICT); +} + +JS_BOOL JS_IsSameValue(JSContext *ctx, JSValue op1, JSValue op2) +{ + return js_same_value(ctx, op1, op2); +} + +JS_BOOL JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2) +{ + return js_same_value_zero(ctx, op1, op2); +} + +/* WeakRef */ + +typedef struct JSWeakRefData { + JSValue target; + JSValue obj; +} JSWeakRefData; + +static JSWeakRefData js_weakref_sentinel; + +static void js_weakref_finalizer(JSRuntime *rt, JSValue val) +{ + JSWeakRefData *wrd = JS_GetOpaque(val, JS_CLASS_WEAK_REF); + if (!wrd || wrd == &js_weakref_sentinel) + return; + + /* Delete weak ref */ + JSWeakRefRecord **pwr, *wr; + + 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; + } + *pwr = wr->next_weak_ref; + js_free_rt(rt, wrd); + js_free_rt(rt, wr); +} + +static JSValue js_weakref_constructor(JSContext *ctx, JSValue new_target, int argc, JSValue *argv) +{ + if (JS_IsUndefined(new_target)) + return JS_ThrowTypeError(ctx, "constructor requires 'new'"); + JSValue arg = argv[0]; + if (!is_valid_weakref_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); + if (JS_IsException(obj)) + return JS_EXCEPTION; + JSWeakRefData *wrd = js_malloc(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); + return obj; +} + +static JSValue js_weakref_deref(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) +{ + JSWeakRefData *wrd = JS_GetOpaque2(ctx, this_val, JS_CLASS_WEAK_REF); + if (!wrd) + return JS_EXCEPTION; + if (wrd == &js_weakref_sentinel) + return JS_UNDEFINED; + return js_dup(wrd->target); +} + +static const JSCFunctionListEntry js_weakref_proto_funcs[] = { + JS_CFUNC_DEF("deref", 0, js_weakref_deref ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakRef", JS_PROP_CONFIGURABLE ), +}; + +static const JSClassShortDef js_weakref_class_def[] = { + { JS_ATOM_WeakRef, js_weakref_finalizer, NULL }, /* JS_CLASS_WEAK_REF */ +}; + +typedef struct JSFinRecEntry { + struct list_head link; + JSValue obj; + JSValue target; + JSValue held_val; + JSValue token; +} JSFinRecEntry; + +typedef struct JSFinalizationRegistryData { + struct list_head entries; + JSContext *ctx; + 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, 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_FreeValueRT(rt, fre->held_val); + JS_FreeValueRT(rt, fre->token); + js_free_rt(rt, fre); + } + JS_FreeValueRT(rt, frd->cb); + js_free_rt(rt, frd); + } +} + +static void js_finrec_mark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) +{ + JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY); + 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); + } + } +} + +static JSValue js_finrec_constructor(JSContext *ctx, JSValue new_target, int argc, JSValue *argv) +{ + if (JS_IsUndefined(new_target)) + return JS_ThrowTypeError(ctx, "constructor requires 'new'"); + JSValue cb = argv[0]; + if (!JS_IsFunction(ctx, cb)) + return JS_ThrowTypeError(ctx, "argument must be a function"); + + JSValue 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)); + if (!frd) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + init_list_head(&frd->entries); + frd->ctx = ctx; + frd->cb = js_dup(cb); + JS_SetOpaqueInternal(obj, frd); + return obj; +} + +static JSValue js_finrec_register(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) +{ + JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY); + if (!frd) + return JS_EXCEPTION; + + JSValue target = argv[0]; + JSValue held_val = argv[1]; + // The function length needs to return 2, so the 3rd argument won't be initialized. + JSValue token = argc > 2 ? argv[2] : JS_UNDEFINED; + + if (!is_valid_weakref_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)) + return JS_ThrowTypeError(ctx, "held value cannot be the target"); + if (!JS_IsUndefined(token) && !is_valid_weakref_target(token)) + return JS_ThrowTypeError(ctx, "invalid unregister token"); + + JSFinRecEntry *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); + 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, JSValue this_val, int argc, JSValue *argv) +{ + JSFinalizationRegistryData *frd = JS_GetOpaque2(ctx, this_val, JS_CLASS_FINALIZATION_REGISTRY); + if (!frd) + return JS_EXCEPTION; + + JSValue token = argv[0]; + if (!is_valid_weakref_target(token)) + return JS_ThrowTypeError(ctx, "invalid unregister token"); + + struct list_head *el, *el1; + BOOL 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); + JS_FreeValue(ctx, fre->held_val); + JS_FreeValue(ctx, fre->token); + js_free(ctx, fre); + removed = TRUE; + } + } + + return js_bool(removed); +} + +static const JSCFunctionListEntry js_finrec_proto_funcs[] = { + JS_CFUNC_DEF("register", 2, js_finrec_register ), + JS_CFUNC_DEF("unregister", 1, js_finrec_unregister ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "FinalizationRegistry", JS_PROP_CONFIGURABLE ), +}; + +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, JSValue *argv) +{ + return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); +} + +void JS_AddIntrinsicWeakRef(JSContext *ctx) +{ + JSRuntime *rt = ctx->rt; + + /* 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)); + } + 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]); + + /* 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); + 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))) { + JSValue 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(JSValue 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(JSValue target, struct JSWeakRefRecord *wr) +{ + JSWeakRefRecord **pwr = get_first_weak_ref(target); + /* Add the weak reference */ + wr->next_weak_ref = *pwr; + *pwr = wr; +} + +/* Poly IC */ + +JSInlineCache *init_ic(JSContext *ctx) +{ + JSInlineCache *ic; + ic = js_malloc(ctx, sizeof(JSInlineCache)); + if (unlikely(!ic)) + goto fail; + ic->count = 0; + ic->hash_bits = 2; + ic->capacity = 1 << ic->hash_bits; + ic->hash = js_mallocz(ctx, sizeof(ic->hash[0]) * ic->capacity); + if (unlikely(!ic->hash)) + goto fail; + ic->cache = NULL; + return ic; +fail: + js_free(ctx, ic); + return NULL; +} + +int rebuild_ic(JSContext *ctx, JSInlineCache *ic) +{ + uint32_t i, count; + JSInlineCacheHashSlot *ch; + if (ic->count == 0) + goto end; + count = 0; + ic->cache = js_mallocz(ctx, sizeof(JSInlineCacheRingSlot) * ic->count); + if (unlikely(!ic->cache)) + goto fail; + for (i = 0; i < ic->capacity; i++) { + for (ch = ic->hash[i]; ch != NULL; ch = ch->next) { + ch->index = count++; + ic->cache[ch->index].atom = JS_DupAtom(ctx, ch->atom); + ic->cache[ch->index].index = 0; + } + } +end: + return 0; +fail: + return -1; +} + +int resize_ic_hash(JSContext *ctx, JSInlineCache *ic) +{ + uint32_t new_capacity, i, h; + JSInlineCacheHashSlot *ch, *ch_next; + JSInlineCacheHashSlot **new_hash; + new_capacity = 1 << (ic->hash_bits + 1); + new_hash = js_mallocz(ctx, sizeof(ic->hash[0]) * new_capacity); + if (unlikely(!new_hash)) + goto fail; + ic->hash_bits += 1; + for (i = 0; i < ic->capacity; i++) { + for (ch = ic->hash[i]; ch != NULL; ch = ch_next) { + h = get_index_hash(ch->atom, ic->hash_bits); + ch_next = ch->next; + ch->next = new_hash[h]; + new_hash[h] = ch; + } + } + js_free(ctx, ic->hash); + ic->hash = new_hash; + ic->capacity = new_capacity; + return 0; +fail: + return -1; +} + +int free_ic(JSRuntime* rt, JSInlineCache *ic) +{ + uint32_t i; + JSInlineCacheHashSlot *ch, *ch_next; + JSShape **shape, *(*shapes)[IC_CACHE_ITEM_CAPACITY]; + if (ic->cache) { + for (i = 0; i < ic->count; i++) { + shapes = &ic->cache[i].shape; + JS_FreeAtomRT(rt, ic->cache[i].atom); + for (shape = *shapes; shape != endof(*shapes); shape++) + js_free_shape_null(rt, *shape); + } + } + for (i = 0; i < ic->capacity; i++) { + for (ch = ic->hash[i]; ch != NULL; ch = ch_next) { + ch_next = ch->next; + JS_FreeAtomRT(rt, ch->atom); + js_free_rt(rt, ch); + } + } + if (ic->count > 0) + js_free_rt(rt, ic->cache); + js_free_rt(rt, ic->hash); + js_free_rt(rt, ic); + return 0; +} + +static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu, + JSAtom atom, JSObject *object, uint32_t prop_offset) +{ + int32_t i; + uint32_t h; + JSInlineCacheHashSlot *ch; + JSInlineCacheRingSlot *cr; + JSInlineCache *ic; + JSShape *sh; + + if (!icu) + return; + ic = icu->ic; + if (!ic) + return; + sh = object->shape; + if (!sh->is_hashed) + return; + cr = NULL; + h = get_index_hash(atom, ic->hash_bits); + for (ch = ic->hash[h]; ch != NULL; ch = ch->next) { + if (ch->atom == atom) { + cr = ic->cache + ch->index; + break; + } + } + assert(cr != NULL); + i = cr->index; + do { + if (sh == cr->shape[i]) { + cr->prop_offset[i] = prop_offset; + goto end; + } + i = (i + 1) % countof(cr->shape); + } while (i != cr->index); + js_free_shape_null(ctx->rt, cr->shape[i]); + cr->shape[i] = js_dup_shape(sh); + cr->prop_offset[i] = prop_offset; +end: + icu->offset = ch->index; +} + +/* CallSite */ + +static void js_callsite_finalizer(JSRuntime *rt, JSValue 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, JSValue 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, JSValue this_val, int argc, JSValue *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, JSValue this_val, int argc, JSValue *argv) +{ + JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); + if (!csd) + return JS_EXCEPTION; + return JS_NewBool(ctx, csd->native); +} + +static JSValue js_callsite_getnumber(JSContext *ctx, JSValue this_val, int argc, JSValue *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_NewInt32(ctx, *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)); +} + +BOOL JS_DetectModule(const char *input, size_t input_len) +{ + 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_AddIntrinsicRegExp(ctx); // otherwise regexp literals don't parse + val = __JS_EvalInternal(ctx, JS_UNDEFINED, input, input_len, "", + 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; +} + +uintptr_t js_std_cmd(int cmd, ...) { + JSRuntime *rt; + 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; + default: + rv = -1; + } + va_end(ap); + + return rv; +} + +#undef malloc +#undef free +#undef realloc diff --git a/quickjs.h b/quickjs.h index 700ee61..3ffeede 100644 --- a/quickjs.h +++ b/quickjs.h @@ -3,6 +3,8 @@ * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon + * Copyright (c) 2023 Ben Noordhuis + * Copyright (c) 2023 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 @@ -27,21 +29,21 @@ #include #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))) +#define JS_EXTERN __attribute__((visibility("default"))) #else -#define js_likely(x) (x) -#define js_unlikely(x) (x) #define js_force_inline inline #define __js_printf_like(a, b) +#define JS_EXTERN /* nothing */ #endif #define JS_BOOL int @@ -53,23 +55,23 @@ 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 +/* 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. + */ -#ifndef JS_PTR64 -#define JS_NAN_BOXING +/* 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 = -11, /* first negative tag */ - JS_TAG_BIG_DECIMAL = -11, - JS_TAG_BIG_INT = -10, - JS_TAG_BIG_FLOAT = -9, + 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 */ @@ -87,52 +89,13 @@ enum { /* any larger tag is FLOAT64 if JS_NAN_BOXING */ }; -typedef struct JSRefCountHeader { - int ref_count; -} JSRefCountHeader; - #define JS_FLOAT64_NAN NAN +#define JSValueConst JSValue /* For backwards compatibility. */ -#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_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_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; -} - -#elif defined(JS_NAN_BOXING) +#if defined(JS_NAN_BOXING) && JS_NAN_BOXING typedef uint64_t JSValue; -#define JSValueConst 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) @@ -156,7 +119,7 @@ static inline double JS_VALUE_GET_FLOAT64(JSValue v) #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) -static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +static inline JSValue __JS_NewFloat64(double d) { union { double d; @@ -165,7 +128,7 @@ static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) JSValue v; u.d = d; /* normalize NaN */ - if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) + if ((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000) v = JS_NAN; else v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); @@ -191,7 +154,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) tag = JS_VALUE_GET_TAG(v); return tag == (JS_NAN >> 32); } - + #else /* !JS_NAN_BOXING */ typedef union JSValueUnion { @@ -205,8 +168,6 @@ typedef struct JSValue { int64_t tag; } JSValue; -#define JSValueConst 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) @@ -215,14 +176,42 @@ typedef struct JSValue { #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) #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 = JS_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_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } +#define JS_NAN (JSValue){ (JSValueUnion){ .float64 = JS_FLOAT64_NAN }, JS_TAG_FLOAT64 } +#endif #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) -#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } - -static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +static inline JSValue __JS_NewFloat64(double d) { JSValue v; v.tag = JS_TAG_FLOAT64; @@ -248,7 +237,6 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #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_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) /* special values */ @@ -289,8 +277,12 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #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 */ -#define JS_DEFAULT_STACK_SIZE (256 * 1024) +#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) */ @@ -300,7 +292,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #define JS_EVAL_TYPE_MASK (3 << 0) #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ -#define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' 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(). */ @@ -309,95 +301,105 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #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) +#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 JSValue JSCFunction(JSContext *ctx, JSValue this_val, int argc, JSValue *argv); +typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic); +typedef JSValue JSCFunctionData(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic, JSValue *func_data); 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); + 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; +// 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; -JSRuntime *JS_NewRuntime(void); +JS_EXTERN 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); +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 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 */ -void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); +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. */ -void JS_UpdateStackTop(JSRuntime *rt); -JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); -void JS_FreeRuntime(JSRuntime *rt); -void *JS_GetRuntimeOpaque(JSRuntime *rt); -void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); +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_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); -void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -void JS_RunGC(JSRuntime *rt); -JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj); +JS_EXTERN void JS_MarkValue(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); +JS_EXTERN void JS_RunGC(JSRuntime *rt); +JS_EXTERN JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValue 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); +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 */ -JSContext *JS_NewContextRaw(JSRuntime *rt); -void JS_AddIntrinsicBaseObjects(JSContext *ctx); -void JS_AddIntrinsicDate(JSContext *ctx); -void JS_AddIntrinsicEval(JSContext *ctx); -void JS_AddIntrinsicStringNormalize(JSContext *ctx); -void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); -void JS_AddIntrinsicRegExp(JSContext *ctx); -void JS_AddIntrinsicJSON(JSContext *ctx); -void JS_AddIntrinsicProxy(JSContext *ctx); -void JS_AddIntrinsicMapSet(JSContext *ctx); -void JS_AddIntrinsicTypedArrays(JSContext *ctx); -void JS_AddIntrinsicPromise(JSContext *ctx); -void JS_AddIntrinsicBigInt(JSContext *ctx); -void JS_AddIntrinsicBigFloat(JSContext *ctx); -void JS_AddIntrinsicBigDecimal(JSContext *ctx); -/* enable operator overloading */ -void JS_AddIntrinsicOperators(JSContext *ctx); -/* enable "use math" */ -void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable); +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); -JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); +/* for equality comparisons and sameness */ +JS_EXTERN int JS_IsEqual(JSContext *ctx, JSValue op1, JSValue op2); +JS_EXTERN JS_BOOL JS_IsStrictEqual(JSContext *ctx, JSValue op1, JSValue op2); +JS_EXTERN JS_BOOL JS_IsSameValue(JSContext *ctx, JSValue op1, JSValue op2); +/* Similar to same-value equality, but +0 and -0 are considered equal. */ +JS_EXTERN JS_BOOL JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2); -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); +/* Only used for running 262 tests. TODO(saghul) add build time flag. */ +JS_EXTERN JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); -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); +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; @@ -415,22 +417,22 @@ typedef struct JSMemoryUsage { 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); +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 -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_AtomToCString(JSContext *ctx, JSAtom atom); -JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); +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_AtomToCString(JSContext *ctx, JSAtom atom); +JS_EXTERN JSAtom JS_ValueToAtom(JSContext *ctx, JSValue val); /* object class support */ @@ -451,41 +453,41 @@ typedef struct JSClassExoticMethods { 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); + JSValue 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); + JSValue obj); /* return < 0 if exception, or TRUE/FALSE */ - int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); + int (*delete_property)(JSContext *ctx, JSValue 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 (*define_own_property)(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue 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); + int (*has_property)(JSContext *ctx, JSValue obj, JSAtom atom); + JSValue (*get_property)(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue receiver); /* return < 0 if exception or TRUE/FALSE */ - int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst value, JSValueConst receiver, int flags); + int (*set_property)(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue value, JSValue receiver, int flags); } JSClassExoticMethods; typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); -typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, +typedef void JSClassGCMark(JSRuntime *rt, JSValue 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, +typedef JSValue JSClassCall(JSContext *ctx, JSValue func_obj, + JSValue this_val, int argc, JSValue *argv, int flags); typedef struct JSClassDef { - const char *class_name; + const char *class_name; /* pure ASCII only! */ JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; /* if call != NULL, the object is a function. If (flags & @@ -499,34 +501,46 @@ typedef struct JSClassDef { JSClassExoticMethods *exotic; } JSClassDef; -JSClassID JS_NewClassID(JSClassID *pclass_id); -int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); -int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); +#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(JSValue v); +JS_EXTERN int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); +JS_EXTERN int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); /* value handling */ static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_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_t)val) { - v = JS_NewInt32(ctx, val); + if (val >= INT32_MIN && val <= INT32_MAX) { + v = JS_NewInt32(ctx, (int32_t)val); } else { - v = __JS_NewFloat64(ctx, val); + v = JS_NewFloat64(ctx, (double)val); } return v; } @@ -534,228 +548,159 @@ static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) { JSValue v; - if (val <= 0x7fffffff) { - v = JS_NewInt32(ctx, val); + if (val <= INT32_MAX) { + v = JS_NewInt32(ctx, (int32_t)val); } else { - v = __JS_NewFloat64(ctx, val); + v = JS_NewFloat64(ctx, (double)val); } return v; } -JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); -JSValue JS_NewBigUint64(JSContext *ctx, uint64_t 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 js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) -{ - JSValue v; - int32_t val; - union { - double d; - uint64_t u; - } u, t; - 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) { - v = JS_MKVAL(JS_TAG_INT, val); - } else { - v = __JS_NewFloat64(ctx, d); - } - return v; -} - -static inline JS_BOOL JS_IsNumber(JSValueConst v) +static inline JS_BOOL JS_IsNumber(JSValue 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) +static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValue v) { - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_INT; + (void)&ctx; + return JS_VALUE_GET_TAG(v) == JS_TAG_BIG_INT; } -static inline JS_BOOL JS_IsBigFloat(JSValueConst v) -{ - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_FLOAT; -} - -static inline JS_BOOL JS_IsBigDecimal(JSValueConst v) -{ - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_DECIMAL; -} - -static inline JS_BOOL JS_IsBool(JSValueConst v) +static inline JS_BOOL JS_IsBool(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; } -static inline JS_BOOL JS_IsNull(JSValueConst v) +static inline JS_BOOL JS_IsNull(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; } -static inline JS_BOOL JS_IsUndefined(JSValueConst v) +static inline JS_BOOL JS_IsUndefined(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; } -static inline JS_BOOL JS_IsException(JSValueConst v) +static inline JS_BOOL JS_IsException(JSValue v) { - return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); + return JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION; } -static inline JS_BOOL JS_IsUninitialized(JSValueConst v) +static inline JS_BOOL JS_IsUninitialized(JSValue v) { - return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); + return JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED; } -static inline JS_BOOL JS_IsString(JSValueConst v) +static inline JS_BOOL JS_IsString(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; } -static inline JS_BOOL JS_IsSymbol(JSValueConst v) +static inline JS_BOOL JS_IsSymbol(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; } -static inline JS_BOOL JS_IsObject(JSValueConst v) +static inline JS_BOOL JS_IsObject(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; } -JSValue JS_Throw(JSContext *ctx, JSValue obj); -JSValue JS_GetException(JSContext *ctx); -JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); -void JS_ResetUncatchableError(JSContext *ctx); -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 (JSValue)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 (JSValue)v; -} - -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) +JS_EXTERN JSValue JS_Throw(JSContext *ctx, JSValue obj); +JS_EXTERN JSValue JS_GetException(JSContext *ctx); +JS_EXTERN JS_BOOL JS_HasException(JSContext *ctx); +JS_EXTERN JS_BOOL JS_IsError(JSContext *ctx, JSValue val); +JS_EXTERN JS_BOOL JS_IsUncatchableError(JSContext* ctx, JSValue val); +JS_EXTERN void JS_ResetUncatchableError(JSContext *ctx); +JS_EXTERN JSValue JS_NewError(JSContext *ctx); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowPlainError(JSContext *ctx, const char *fmt, ...); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...); +JS_EXTERN JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, 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, JSValue v); +JS_EXTERN JSValue JS_DupValueRT(JSRuntime *rt, JSValue v); +JS_EXTERN int JS_ToBool(JSContext *ctx, JSValue val); /* return -1 for JS_EXCEPTION */ +JS_EXTERN int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValue val); +static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValue 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); +JS_EXTERN int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValue val); +JS_EXTERN int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValue val); +JS_EXTERN int JS_ToFloat64(JSContext *ctx, double *pres, JSValue val); /* return an exception if 'val' is a Number */ -int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +JS_EXTERN int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValue val); +JS_EXTERN int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValue val); /* same as JS_ToInt64() but allow BigInt */ -int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val); +JS_EXTERN int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValue val); -JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); -JSValue JS_NewString(JSContext *ctx, const char *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) +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)); +} +JS_EXTERN JSValue JS_NewAtomString(JSContext *ctx, const char *str); +JS_EXTERN JSValue JS_ToString(JSContext *ctx, JSValue val); +JS_EXTERN JSValue JS_ToPropertyKey(JSContext *ctx, JSValue val); +JS_EXTERN const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValue val1, JS_BOOL cesu8); +static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValue val1) { return JS_ToCStringLen2(ctx, plen, val1, 0); } -static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) +static inline const char *JS_ToCString(JSContext *ctx, JSValue val1) { return JS_ToCStringLen2(ctx, NULL, val1, 0); } -void JS_FreeCString(JSContext *ctx, const char *ptr); +JS_EXTERN 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_EXTERN JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValue proto, JSClassID class_id); +JS_EXTERN JSValue JS_NewObjectClass(JSContext *ctx, int class_id); +JS_EXTERN JSValue JS_NewObjectProto(JSContext *ctx, JSValue proto); +JS_EXTERN 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); +JS_EXTERN JS_BOOL JS_IsFunction(JSContext* ctx, JSValue val); +JS_EXTERN JS_BOOL JS_IsConstructor(JSContext* ctx, JSValue val); +JS_EXTERN JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValue func_obj, JS_BOOL val); -JSValue JS_NewArray(JSContext *ctx); -int JS_IsArray(JSContext *ctx, JSValueConst val); +JS_EXTERN JSValue JS_NewArray(JSContext *ctx); +JS_EXTERN int JS_IsArray(JSContext *ctx, JSValue val); -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); +JS_EXTERN JSValue JS_NewDate(JSContext *ctx, double epoch_ms); -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); +JS_EXTERN JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop); +JS_EXTERN JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx); +JS_EXTERN JSValue JS_GetPropertyInt64(JSContext *ctx, JSValue this_obj, + int64_t idx); +JS_EXTERN JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj, + const char *prop); + +JS_EXTERN int JS_SetProperty(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val); +JS_EXTERN int JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx, JSValue val); +JS_EXTERN int JS_SetPropertyInt64(JSContext *ctx, JSValue this_obj, + int64_t idx, JSValue val); +JS_EXTERN int JS_SetPropertyStr(JSContext *ctx, JSValue this_obj, + const char *prop, JSValue val); +JS_EXTERN int JS_HasProperty(JSContext *ctx, JSValue this_obj, JSAtom prop); +JS_EXTERN int JS_IsExtensible(JSContext *ctx, JSValue obj); +JS_EXTERN int JS_PreventExtensions(JSContext *ctx, JSValue obj); +JS_EXTERN int JS_DeleteProperty(JSContext *ctx, JSValue obj, JSAtom prop, int flags); +JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValue obj, JSValue proto_val); +JS_EXTERN JSValue JS_GetPrototype(JSContext *ctx, JSValue val); +JS_EXTERN int JS_GetLength(JSContext *ctx, JSValue obj, int64_t *pres); +JS_EXTERN int JS_SetLength(JSContext *ctx, JSValue obj, int64_t len); #define JS_GPN_STRING_MASK (1 << 0) #define JS_GPN_SYMBOL_MASK (1 << 1) @@ -765,74 +710,106 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); /* 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); -int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); +JS_EXTERN int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValue obj, int flags); +JS_EXTERN int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValue obj, JSAtom prop); +JS_EXTERN void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, + uint32_t len); -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); +JS_EXTERN JSValue JS_Call(JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_Invoke(JSContext *ctx, JSValue this_val, JSAtom atom, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_CallConstructor(JSContext *ctx, JSValue func_obj, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_CallConstructor2(JSContext *ctx, JSValue func_obj, + JSValue new_target, + int argc, JSValue *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. + */ +JS_EXTERN 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); +JS_EXTERN 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); +JS_EXTERN JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj, + const char *input, size_t input_len, + const char *filename, int eval_flags); +JS_EXTERN JSValue JS_GetGlobalObject(JSContext *ctx); +JS_EXTERN int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj); +JS_EXTERN int JS_DefineProperty(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags); +JS_EXTERN int JS_DefinePropertyValue(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyValueUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyValueStr(JSContext *ctx, JSValue this_obj, + const char *prop, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyGetSet(JSContext *ctx, JSValue 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(JSValue obj, void *opaque); +JS_EXTERN void *JS_GetOpaque(JSValue obj, JSClassID class_id); +JS_EXTERN void *JS_GetOpaque2(JSContext *ctx, JSValue obj, JSClassID class_id); +JS_EXTERN void *JS_GetAnyOpaque(JSValue 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); +JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename); +JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValue obj, + JSValue replacer, JSValue 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); -JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, - size_t *pbyte_offset, - size_t *pbyte_length, - size_t *pbytes_per_element); +JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, + JSFreeArrayBufferDataFunc *free_func, void *opaque, + JS_BOOL is_shared); +JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); +JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValue obj); +JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValue obj); +JS_EXTERN JS_BOOL JS_IsArrayBuffer(JSValue obj); +JS_EXTERN uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValue 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, JSValue *argv, + JSTypedArrayEnum array_type); +JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValue 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, + JS_BOOL is_shared); +/* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */ +JS_EXTERN int JS_GetTypedArrayType(JSValue 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; -void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, - const JSSharedArrayBufferFunctions *sf); +JS_EXTERN void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf); typedef enum JSPromiseStateEnum { JS_PROMISE_PENDING, @@ -840,23 +817,25 @@ typedef enum JSPromiseStateEnum { 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); +JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); +JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise); +JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValue promise); + +JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, JS_BOOL is_global); /* is_handled = TRUE means that the rejection is handled */ -typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, +typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValue promise, + JSValue reason, JS_BOOL is_handled, void *opaque); -void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, 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); -void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); +JS_EXTERN 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); +JS_EXTERN void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); /* set the [IsHTMLDDA] internal slot */ -void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj); +JS_EXTERN void JS_SetIsHTMLDDA(JSContext *ctx, JSValue obj); typedef struct JSModuleDef JSModuleDef; @@ -870,50 +849,57 @@ typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, /* 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); +JS_EXTERN void JS_SetModuleLoaderFunc(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc *module_loader, void *opaque); /* return the import.meta object of a module */ -JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); -JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); +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); -int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); +typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValue *argv); +JS_EXTERN int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValue *argv); -JS_BOOL JS_IsJobPending(JSRuntime *rt); -int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); +JS_EXTERN JS_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 (1 << 1) /* byte swapped output */ +#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 */ -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_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, JSValue obj, int flags); +JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValue obj, + int flags, JSSABTab *psab_tab); #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_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 */ -JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags); +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() */ -JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); +JS_EXTERN 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); +JS_EXTERN int JS_ResolveModule(JSContext *ctx, JSValue obj); /* only exported for os.Worker() */ -JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); +JS_EXTERN JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); /* only exported for os.Worker() */ -JSValue JS_LoadModule(JSContext *ctx, const char *basename, +JS_EXTERN JSValue JS_LoadModule(JSContext *ctx, const char *basename, const char *filename); /* C function definition */ @@ -935,26 +921,26 @@ typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ typedef union JSCFunctionType { JSCFunction *generic; - JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); + JSValue (*generic_magic)(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic); JSCFunction *constructor; - JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); + JSValue (*constructor_magic)(JSContext *ctx, JSValue new_target, int argc, JSValue *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); + JSValue (*getter)(JSContext *ctx, JSValue this_val); + JSValue (*setter)(JSContext *ctx, JSValue this_val, JSValue val); + JSValue (*getter_magic)(JSContext *ctx, JSValue this_val, int magic); + JSValue (*setter_magic)(JSContext *ctx, JSValue this_val, JSValue val, int magic); + JSValue (*iterator_next)(JSContext *ctx, JSValue this_val, + int argc, JSValue *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); +JS_EXTERN JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic); +JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, + int length, int magic, int data_len, + JSValue *data); static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, int length) @@ -966,15 +952,18 @@ static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *fun const char *name, int length, JSCFunctionEnum cproto, int magic) { - return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, 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); } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto); +JS_EXTERN void JS_SetConstructor(JSContext *ctx, JSValue func_obj, + JSValue proto); /* C property definition */ typedef struct JSCFunctionListEntry { - const char *name; + const char *name; /* pure ASCII or UTF-8 encoded */ uint8_t prop_flags; uint8_t def_type; int16_t magic; @@ -996,9 +985,10 @@ typedef struct JSCFunctionListEntry { const struct JSCFunctionListEntry *tab; int len; } prop_list; - const char *str; + const char *str; /* pure ASCII or UTF-8 encoded */ int32_t i32; int64_t i64; + uint64_t u64; double f64; } u; } JSCFunctionListEntry; @@ -1015,43 +1005,59 @@ typedef struct JSCFunctionListEntry { #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, .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_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 } } } +#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 } } } -void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, - const JSCFunctionListEntry *tab, - int len); +JS_EXTERN void JS_SetPropertyFunctionList(JSContext *ctx, JSValue 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); +JS_EXTERN 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); +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 */ -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); +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); -#undef js_unlikely +/* Version */ + +#define QJS_VERSION_MAJOR 0 +#define QJS_VERSION_MINOR 8 +#define QJS_VERSION_PATCH 0 +#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 +#undef __js_printf_like #ifdef __cplusplus } /* extern "C" { */ diff --git a/release.sh b/release.sh deleted file mode 100755 index 6b1b496..0000000 --- a/release.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/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 CONFIG_WIN32=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 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 - -#################################################" -# 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 - -#################################################" -# Linux binary release - -if echo $release_list | grep -w -q binary ; then - -make clean -make CONFIG_WIN32=y clean -make -j4 qjs run-test262 -make -j4 CONFIG_M32=y qjs32 run-test262-32 -strip qjs run-test262 qjs32 run-test262-32 - -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 . ) - -d="quickjs-linux-i686-${version}" -outdir="/tmp/${d}" - -rm -rf $outdir -mkdir -p $outdir - -cp qjs32 $outdir/qjs -cp run-test262-32 $outdir/run-test262 - -( 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 qjscalc.js 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 \ - libbf.c libbf.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 $outdir/examples - -cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \ - doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \ - $outdir/doc - -( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} ) - -fi diff --git a/repl.js b/repl.js index 805e7e9..d7e302e 100644 --- a/repl.js +++ b/repl.js @@ -1,7 +1,6 @@ /* * QuickJS Read Eval Print Loop - * - * Copyright (c) 2024 Sneed Group + * * Copyright (c) 2017-2020 Fabrice Bellard * Copyright (c) 2017-2020 Charlie Gordon * @@ -23,30 +22,35 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -"use strip"; - -import * as std from "std"; -import * as os from "os"; +import * as std from "qjs:std"; +import * as os from "qjs:os"; +import * as bjson from "qjs:bjson"; (function(g) { - /* add 'os' and 'std' bindings */ + /* add 'bjson', 'os' and 'std' bindings */ + g.bjson = bjson; 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 parseFloat = g.parseFloat; + var isNaN = g.isNaN; + var Infinity = g.Infinity; + var console = g.console; - /* XXX: use preprocessor ? */ - var config_numcalc = (typeof os.open === "undefined"); - var has_jscalc = (typeof Fraction === "function"); - var has_bignum = (typeof BigFloat === "function"); - var colors = { none: "\x1b[0m", black: "\x1b[30m", @@ -68,67 +72,73 @@ import * as os from "os"; bright_white: "\x1b[37;1m", }; - var styles; - if (config_numcalc) { - styles = { - 'default': 'black', + var themes = { + dark: { + 'annotation': 'cyan', + 'boolean': 'bright_white', 'comment': 'white', - 'string': 'green', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'blue', - 'function': 'gray', - 'type': 'bright_magenta', - 'identifier': 'yellow', - 'error': 'bright_red', - 'result': 'black', - 'error_msg': 'bright_red', - }; - } else { - styles = { + 'date': 'magenta', 'default': 'bright_green', - 'comment': 'white', - 'string': 'bright_cyan', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'bright_white', + 'error': 'bright_red', 'function': 'bright_yellow', - 'type': 'bright_magenta', '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', - 'result': 'bright_white', - 'error_msg': 'bright_red', - }; - } - - var history = []; - var clip_board = ""; - var prec; - var expBits; - var log2_10; - - var pstate = ""; - var prompt = ""; - var plen = 0; - var ps1; - if (config_numcalc) - ps1 = "> "; - else - ps1 = "donejs > "; - var ps2 = " ... "; + '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 = 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 pstate = ""; + var prompt = ""; + var plen = 0; + var ps1 = "qjs > "; + var ps2 = " ... "; 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; @@ -139,12 +149,12 @@ import * as os from "os"; var term_read_buf; var term_width; /* current X position of the cursor in the terminal */ - var term_cursor_x = 0; - + var term_cursor_x = 0; + function termInit() { var tab; term_fd = std.in.fileno(); - + /* get the terminal size */ term_width = 80; if (os.isatty(term_fd)) { @@ -171,14 +181,14 @@ import * as os from "os"; /* send Ctrl-C to readline */ handle_byte(3); } - + function term_read_handler() { var l, i; l = os.read(term_fd, term_read_buf.buffer, 0, term_read_buf.length); for(i = 0; i < l; i++) handle_byte(term_read_buf[i]); } - + function handle_byte(c) { if (!utf8) { handle_char(c); @@ -196,12 +206,12 @@ import * as os from "os"; handle_char(c); } } - + function is_alpha(c) { return typeof c === "string" && ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); } - + function is_digit(c) { return typeof c === "string" && (c >= '0' && c <= '9'); } @@ -233,7 +243,7 @@ import * as os from "os"; d = c.codePointAt(0); /* can be NaN if empty string */ return d >= 0xdc00 && d < 0xe000; } - + function is_balanced(a, b) { switch (a + b) { case "()": @@ -250,7 +260,7 @@ import * as os from "os"; var style = style_names[i = j]; while (++j < str.length && style_names[j] == style) continue; - std.puts(colors[styles[style] || 'default']); + std.puts(colors[styles[style] || 'none']); std.puts(str.substring(i, j)); std.puts(colors['none']); } @@ -272,7 +282,7 @@ import * as os from "os"; } else { l = Math.min(term_width - 1 - term_cursor_x, delta); print_csi(l, "C"); /* right */ - delta -= l; + delta -= l; term_cursor_x += l; } } @@ -400,7 +410,12 @@ import * as os from "os"; function backward_word() { cursor_pos = skip_word_backward(cursor_pos); - } + } + + function clear_screen() { + directives["clear"](); + return -2; + } function accept_line() { std.puts("\n"); @@ -409,7 +424,10 @@ import * as os from "os"; } 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; @@ -572,60 +590,72 @@ import * as os from "os"; function control_c() { if (last_fun === control_c) { std.puts("\n"); - std.exit(0); + exit(0); } else { std.puts("\n(Press Ctrl-C again to quit)\n"); readline_print_prompt(); } } - + function reset() { cmd = ""; cursor_pos = 0; } - function get_context_word(line, pos) { - var s = ""; - while (pos > 0 && is_word(line[pos - 1])) { + function get_context_word(line, end) { + var pos = end; + while (pos > 0 && is_word(line[pos - 1])) pos--; - s = line[pos] + s; - } - return s; + return line.slice(pos, end); } function get_context_object(line, pos) { - var obj, base, c; - if (pos <= 0 || " ~!%^&*(-+={[|:;,<>?/".indexOf(line[pos - 1]) >= 0) + if (pos <= 0) return g; - if (pos >= 2 && line[pos - 1] === ".") { + var c = line[pos - 1]; + if (pos === 1 && (c === '\\' || c === '.')) + return directives; + if ("'\"`@#)]}\\".indexOf(c) >= 0) + return void 0; + if (c === ".") { pos--; - obj = {}; switch (c = line[pos - 1]) { case '\'': case '\"': + case '`': return "a"; case ']': - return []; - case '}': - return {}; + return []; // incorrect for a[b]. case '/': return / /; default: if (is_word(c)) { - base = get_context_word(line, pos); - if (["true", "false", "null", "this"].includes(base) || !isNaN(+base)) - return eval(base); - obj = get_context_object(line, pos - base.length); + 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); if (obj === null || obj === void 0) return obj; - if (obj === g && obj[base] === void 0) - return eval(base); - else + if (typeof obj[base] !== 'undefined') 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 } - return {}; + break; } + return {}; } - return void 0; + return g; } function get_completions(line, pos) { @@ -732,7 +762,7 @@ import * as os from "os"; readline_print_prompt(); } } - + var commands = { /* command table */ "\x01": beginning_of_line, /* ^A - bol */ "\x02": backward_char, /* ^B - backward-char */ @@ -745,6 +775,7 @@ import * as os from "os"; "\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 */ @@ -752,6 +783,7 @@ import * as os from "os"; "\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 */ @@ -808,9 +840,9 @@ import * as os from "os"; cursor_pos = cmd.length; history_index = history.length; readline_cb = cb; - + prompt = pstate; - + if (mexpr) { prompt += dupstr(" ", plen - prompt.length); prompt += ps2; @@ -886,6 +918,7 @@ import * as os from "os"; os.signal(os.SIGINT, null); /* uninstall the stdin read handler */ os.setReadHandler(term_fd, null); + save_history(); return; } last_fun = this_fun; @@ -895,15 +928,12 @@ import * as os from "os"; } else { alert(); /* beep! */ } - + cursor_pos = (cursor_pos < 0) ? 0 : (cursor_pos > cmd.length) ? cmd.length : cursor_pos; update(); } - var hex_mode = false; - var eval_mode = "std"; - function number_to_string(a, radix) { var s; if (!isFinite(a)) { @@ -933,48 +963,6 @@ import * as os from "os"; } } - function bigfloat_to_string(a, radix) { - var s; - if (!BigFloat.isFinite(a)) { - /* NaN, Infinite */ - if (eval_mode !== "math") { - return "BigFloat(" + a.toString() + ")"; - } else { - return a.toString(); - } - } else { - if (a == 0) { - if (1 / a < 0) - s = "-0"; - else - s = "0"; - } else { - if (radix == 16) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - } - if (typeof a === "bigfloat" && eval_mode !== "math") { - s += "l"; - } else if (eval_mode !== "std" && s.indexOf(".") < 0 && - ((radix == 16 && s.indexOf("p") < 0) || - (radix == 10 && s.indexOf("e") < 0))) { - /* add a decimal point so that the floating point type - is visible */ - s += ".0"; - } - return s; - } - } - function bigint_to_string(a, radix) { var s; if (radix == 16) { @@ -989,266 +977,553 @@ import * as os from "os"; } else { s = a.toString(); } - if (eval_mode === "std") - s += "n"; - return s; + return s + "n"; } - - function print(a) { - var stack = []; - function print_rec(a) { - var n, i, keys, key, type, s; - - type = typeof(a); - if (type === "object") { - if (a === null) { - std.puts(a); - } else if (stack.indexOf(a) >= 0) { - std.puts("[circular]"); - } else if (has_jscalc && (a instanceof Fraction || - a instanceof Complex || - a instanceof Mod || - a instanceof Polynomial || - a instanceof PolyMod || - a instanceof RationalFunction || - a instanceof Series)) { - std.puts(a.toString()); - } else { - stack.push(a); - if (Array.isArray(a)) { - n = a.length; - std.puts("[ "); - for(i = 0; i < n; i++) { - if (i !== 0) - std.puts(", "); - if (i in a) { - print_rec(a[i]); - } else { - std.puts(""); - } - if (i > 20) { - std.puts("..."); - break; - } - } - std.puts(" ]"); - } else if (Object.__getClass(a) === "RegExp") { - std.puts(a.toString()); - } else { - keys = Object.keys(a); - n = keys.length; - std.puts("{ "); - for(i = 0; i < n; i++) { - if (i !== 0) - std.puts(", "); - key = keys[i]; - std.puts(key, ": "); - print_rec(a[key]); - } - std.puts(" }"); - } - stack.pop(a); - } - } else if (type === "string") { - s = a.__quote(); - if (s.length > 79) - s = s.substring(0, 75) + "...\""; - std.puts(s); - } else if (type === "number") { - std.puts(number_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigint") { - std.puts(bigint_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigfloat") { - std.puts(bigfloat_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigdecimal") { - std.puts(a.toString() + "m"); - } else if (type === "symbol") { - std.puts(String(a)); - } else if (type === "function") { - std.puts("function " + a.name + "()"); - } else { - std.puts(a); - } + 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; } - print_rec(a); - } - - function extract_directive(a) { - var pos; - if (a[0] !== '\\') - return ""; - for (pos = 1; pos < a.length; pos++) { - if (!is_alpha(a[pos])) + 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)); + 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); } - return a.substring(1, pos); + 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 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") { + /* return true if the string was a directive */ + function handle_directive(a) { + if (a === "?") { help(); - } else if (cmd === "load") { - var filename = expr.substring(cmd.length + 1).trim(); - if (filename.lastIndexOf(".") <= filename.lastIndexOf("/")) - filename += ".js"; - std.loadScript(filename); + return true; + } + if (a[0] !== '\\' && a[0] !== '.') return false; - } else if (cmd === "x") { - hex_mode = true; - } else if (cmd === "d") { - hex_mode = false; - } else if (cmd === "t") { - show_time = !show_time; - } else if (has_bignum && cmd === "p") { - param = expr.substring(cmd.length + 1).trim().split(" "); - if (param.length === 1 && param[0] === "") { - std.puts("BigFloat precision=" + prec + " bits (~" + - Math.floor(prec / log2_10) + - " digits), exponent size=" + expBits + " bits\n"); - } else if (param[0] === "f16") { - prec = 11; - expBits = 5; - } else if (param[0] === "f32") { - prec = 24; - expBits = 8; - } else if (param[0] === "f64") { - prec = 53; - expBits = 11; - } else if (param[0] === "f128") { - prec = 113; - expBits = 15; - } else { - prec1 = parseInt(param[0]); - if (param.length >= 2) - expBits1 = parseInt(param[1]); - else - expBits1 = BigFloatEnv.expBitsMax; - if (Number.isNaN(prec1) || - prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - 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 (Number.isNaN(expBits1) || - expBits1 < BigFloatEnv.expBitsMin || - expBits1 > BigFloatEnv.expBitsMax) { - std.puts("Invalid exponent bits\n"); - return false; - } - prec = prec1; - expBits = expBits1; } - return false; - } else if (has_bignum && cmd === "digits") { - param = expr.substring(cmd.length + 1).trim(); - prec1 = Math.ceil(parseFloat(param) * log2_10); - if (prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - return false; - } - prec = prec1; - expBits = BigFloatEnv.expBitsMax; - return false; - } else if (has_bignum && cmd === "mode") { - param = expr.substring(cmd.length + 1).trim(); - if (param === "") { - std.puts("Running mode=" + eval_mode + "\n"); - } else if (param === "std" || param === "math") { - eval_mode = param; - } else { - std.puts("Invalid mode\n"); - } - return false; - } else if (cmd === "clear") { - std.puts("\x1b[H\x1b[J"); - } else if (cmd === "q") { - std.exit(0); - } else if (has_jscalc && cmd === "a") { - algebraicMode = true; - } else if (has_jscalc && cmd === "n") { - algebraicMode = false; + } + if (fun && partial < 2) { + fun(a.substring(pos).trim()); } else { - std.puts("Unknown directive: " + cmd + "\n"); - return false; + std.puts(`Unknown directive: ${cmd}\n`); } return true; } - if (config_numcalc) { - /* called by the GUI */ - g.execCmd = function (cmd) { - switch(cmd) { - case "dec": - hex_mode = false; - break; - case "hex": - hex_mode = true; - break; - case "num": - algebraicMode = false; - break; - case "alg": - algebraicMode = true; - break; - } - } - } - function help() { - 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"); - if (has_jscalc) { - std.puts("\\a " + sel(algebraicMode) + "algebraic mode\n" + - "\\n " + sel(!algebraicMode) + "numeric mode\n"); - } - if (has_bignum) { - std.puts("\\p [m [e]] set the BigFloat precision to 'm' bits\n" + - "\\digits n set the BigFloat precision to 'ceil(n*log2(10))' bits\n"); - if (!has_jscalc) { - std.puts("\\mode [std|math] change the running mode (current = " + eval_mode + ")\n"); - } - } - if (!config_numcalc) { - std.puts("\\q exit\n"); + 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 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() { - if (!config_numcalc) { - if (has_jscalc) - std.puts('QJSCalc (DoneJS Edition) - Type "\\h" for help\n'); - else - std.puts('QuickJS (DoneJS Edition) - Type "\\h" for help\n'); - } - if (has_bignum) { - log2_10 = Math.log(10) / Math.log(2); - prec = 113; - expBits = 15; - if (has_jscalc) { - eval_mode = "math"; - /* XXX: numeric mode should always be the default ? */ - g.algebraicMode = config_numcalc; - } - } - + std.puts('QuickJS-ng - Type ".help" for help\n'); cmd_readline_start(); } function cmd_readline_start() { readline_start(dupstr(" ", level), readline_handle_cmd); } - + function readline_handle_cmd(expr) { if (!handle_cmd(expr)) { cmd_readline_start(); @@ -1257,29 +1532,15 @@ import * as os from "os"; /* return true if async termination */ function handle_cmd(expr) { - var colorstate, cmd; - - if (expr === null) { - expr = ""; + if (!expr) return false; - } - 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); - } - if (expr === "") - return false; - - if (mexpr) + if (mexpr) { expr = mexpr + '\n' + expr; - colorstate = colorize_js(expr); + } else { + if (handle_directive(expr)) + return false; + } + var colorstate = colorize_js(expr); pstate = colorstate[0]; level = colorstate[1]; if (pstate) { @@ -1287,43 +1548,27 @@ import * as os from "os"; return false; } mexpr = ""; - - if (has_bignum) { - /* XXX: async is not supported in this case */ - BigFloatEnv.setPrec(eval_and_print_start.bind(null, expr, false), - prec, expBits); - } else { - eval_and_print_start(expr, true); - } + + eval_and_print(expr); + return true; } - function eval_and_print_start(expr, is_async) { + function eval_and_print(expr) { var result; - - try { - if (eval_mode === "math") - expr = '"use math"; void 0;' + expr; - eval_start_time = os.now(); - /* eval as a script */ - result = std.evalScript(expr, { backtrace_barrier: true, async: is_async }); - if (is_async) { - /* result is a promise */ - result.then(print_eval_result, print_eval_error); - } else { - print_eval_result(result); - } - } catch (error) { - print_eval_error(error); - } + + 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); } function print_eval_result(result) { + result = result.value; eval_time = os.now() - eval_start_time; - std.puts(colors[styles.result]); print(result); - std.puts("\n"); - std.puts(colors.none); /* set the last result */ g._ = result; @@ -1331,25 +1576,34 @@ import * as os from "os"; } function print_eval_error(error) { - std.puts(colors[styles.error_msg]); + if (show_colors) { + std.puts(colors[styles.error]); + } if (error instanceof Error) { - console.log(error); + std.puts(error); + std.puts('\n'); if (error.stack) { std.puts(error.stack); } } else { std.puts("Throw: "); - console.log(error); + std.puts(error); + std.puts('\n'); } - std.puts(colors.none); - + + if (show_colors) { + 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(); } @@ -1410,7 +1664,7 @@ import * as os from "os"; } function parse_regex() { - style = 'regex'; + style = 'regexp'; push_state('/'); while (i < n) { c = str[i++]; @@ -1448,6 +1702,8 @@ import * as os from "os"; 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++; } @@ -1473,10 +1729,19 @@ import * as os from "os"; while (i < n && is_word(str[i])) i++; - var w = '|' + str.substring(start, i) + '|'; + var s = str.substring(start, i); + var w = '|' + s + '|'; 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; @@ -1570,7 +1835,7 @@ import * as os from "os"; can_regex = 0; break; } - if (is_word(c) || c == '$') { + if (is_word(c)) { parse_identifier(); break; } @@ -1584,8 +1849,43 @@ import * as os from "os"; 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/run-test262.c b/run-test262.c index bf905bd..8261abb 100644 --- a/run-test262.c +++ b/run-test262.c @@ -1,6 +1,6 @@ /* * ECMA Test 262 Runner for QuickJS - * + * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon * @@ -29,28 +29,59 @@ #include #include #include -#include #include #include + +#ifdef _WIN32 +#include +#include +typedef HANDLE js_thread_t; +#else #include -#include +#include +#include +typedef pthread_t js_thread_t; +#endif #include "cutils.h" #include "list.h" +#include "quickjs.h" +#include "quickjs-c-atomics.h" #include "quickjs-libc.h" -/* enable test262 thread support to test SharedArrayBuffer and Atomics */ -#define CONFIG_AGENT - #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 + +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; + 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; @@ -63,14 +94,15 @@ 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 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; @@ -79,15 +111,21 @@ char *harness_skip_features; char *error_filename; char *error_file; FILE *error_out; -char *report_filename; int update_errors; -int test_count, test_failed, test_index, test_skipped, test_excluded; -int new_errors, changed_errors, fixed_errors; -int async_done; +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; 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; @@ -134,6 +172,15 @@ 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; @@ -260,16 +307,12 @@ void namelist_sort(namelist_t *lp) } lp->count = count; } - lp->sorted = 1; } -int namelist_find(namelist_t *lp, const char *name) +int namelist_find(const 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); @@ -311,7 +354,7 @@ void namelist_load(namelist_t *lp, const char *filename) char *base_name; FILE *f; - f = fopen(filename, "rb"); + f = fopen(filename, "r"); if (!f) { perror_exit(1, filename); } @@ -321,7 +364,7 @@ void namelist_load(namelist_t *lp, const char *filename) char *p = str_strip(buf); if (*p == '#' || *p == ';' || *p == '\0') continue; /* line comment */ - + namelist_add(lp, base_name, p); } free(base_name); @@ -352,47 +395,99 @@ void namelist_free(namelist_t *lp) lp->size = 0; } -static int add_test_file(const char *filename, const struct stat *ptr, int flag) +static int add_test_file(const char *filename) { namelist_t *lp = &test_list; - if (has_suffix(filename, ".js") && !has_suffix(filename, "_FIXTURE.js")) + if (js__has_suffix(filename, ".js") && !js__has_suffix(filename, "_FIXTURE.js")) namelist_add(lp, NULL, filename); return 0; } +static void find_test_files(const char *path); + +static void consider_test_file(const char *path, const char *name, int is_dir) +{ + char s[1024]; + + if (str_equal(name, ".") || str_equal(name, "..")) + return; + snprintf(s, sizeof(s), "%s/%s", 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; - ftw(path, add_test_file, 100); + find_test_files(path); qsort(lp->array + start, lp->count - start, sizeof(*lp->array), namelist_cmp_indirect); } -static JSValue js_print(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +static JSValue js_print_262(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); int i; const char *str; - if (outfile) { - for (i = 0; i < argc; i++) { + for (i = 0; i < argc; i++) { + str = JS_ToCString(ctx, argv[i]); + if (!str) + return JS_EXCEPTION; + if (!strcmp(str, "Test262:AsyncTestComplete")) { + tls->async_done++; + } else if (js__strstart(str, "Test262:AsyncTestFailure", NULL)) { + tls->async_done = 2; /* force an error */ + } + if (outfile) { if (i != 0) fputc(' ', outfile); - str = JS_ToCString(ctx, argv[i]); - 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 */ - } fputs(str, outfile); - JS_FreeCString(ctx, str); } - fputc('\n', outfile); + if (verbose > 1) + printf("%s%s", &" "[i < 1], str); + JS_FreeCString(ctx, str); } + if (outfile) + fputc('\n', outfile); + if (verbose > 1) + printf("\n"); return JS_UNDEFINED; } @@ -403,7 +498,7 @@ static JSValue js_detachArrayBuffer(JSContext *ctx, JSValue this_val, return JS_UNDEFINED; } -static JSValue js_evalScript(JSContext *ctx, JSValue this_val, +static JSValue js_evalScript_262(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { const char *str; @@ -417,13 +512,79 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, return ret; } -#ifdef CONFIG_AGENT +static void start_thread(js_thread_t *thrd, void *(*start)(void *), void *arg) +{ + // musl libc gives threads 80 kb stacks, much smaller than + // JS_DEFAULT_STACK_SIZE (1 MB) + static const unsigned stacksize = 2 << 20; // 2 MB, glibc default +#ifdef _WIN32 + HANDLE h, cp; -#include + cp = GetCurrentProcess(); + h = (HANDLE)_beginthread((void (*)(void *))(void *)start, stacksize, arg); + if (!h) + fatal(1, "_beginthread error"); + // _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. + if (!DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS)) + fatal(1, "DuplicateHandle error"); +#else + pthread_attr_t attr; + + if (pthread_attr_init(&attr)) + fatal(1, "pthread_attr_init"); + if (pthread_attr_setstacksize(&attr, stacksize)) + fatal(1, "pthread_attr_setstacksize"); + if (pthread_create(thrd, &attr, start, arg)) + fatal(1, "pthread_create error"); + pthread_attr_destroy(&attr); +#endif +} + +static void join_thread(js_thread_t thrd) +{ +#ifdef _WIN32 + if (WaitForSingleObject(thrd, INFINITE)) + fatal(1, "WaitForSingleObject error"); + CloseHandle(thrd); +#else + if (pthread_join(thrd, NULL)) + fatal(1, "pthread_join error"); +#endif +} + +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 +} + +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; +} typedef struct { struct list_head link; - pthread_t tid; + js_thread_t tid; char *script; JSValue broadcast_func; BOOL broadcast_pending; @@ -431,6 +592,7 @@ typedef struct { uint8_t *broadcast_sab_buf; size_t broadcast_sab_size; int32_t broadcast_val; + ThreadLocalStorage *tls; } Test262Agent; typedef struct { @@ -441,27 +603,22 @@ typedef struct { static JSValue add_helpers1(JSContext *ctx); static void add_helpers(JSContext *ctx); -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) { - Test262Agent *agent = arg; + ThreadLocalStorage *tls; + Test262Agent *agent; 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); @@ -470,7 +627,7 @@ static void *agent_start(void *arg) JS_SetContextOpaque(ctx, agent); JS_SetRuntimeInfo(rt, "agent"); JS_SetCanBlock(rt, TRUE); - + add_helpers(ctx); ret_val = JS_Eval(ctx, agent->script, strlen(agent->script), "", JS_EVAL_TYPE_GLOBAL); @@ -479,7 +636,7 @@ static void *agent_start(void *arg) if (JS_IsException(ret_val)) js_std_dump_error(ctx); JS_FreeValue(ctx, ret_val); - + for(;;) { JSContext *ctx1; ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); @@ -491,23 +648,23 @@ static void *agent_start(void *arg) break; } else { JSValue args[2]; - - pthread_mutex_lock(&agent_mutex); - while (!agent->broadcast_pending) { - pthread_cond_wait(&agent_cond, &agent_mutex); - } - - agent->broadcast_pending = FALSE; - pthread_cond_signal(&agent_cond); - pthread_mutex_unlock(&agent_mutex); + js_mutex_lock(&tls->agent_mutex); + while (!agent->broadcast_pending) { + js_cond_wait(&tls->agent_cond, &tls->agent_mutex); + } + + agent->broadcast_pending = FALSE; + js_cond_signal(&tls->agent_cond); + + js_mutex_unlock(&tls->agent_mutex); args[0] = JS_NewArrayBuffer(ctx, agent->broadcast_sab_buf, agent->broadcast_sab_size, NULL, NULL, TRUE); args[1] = JS_NewInt32(ctx, agent->broadcast_val); ret_val = JS_Call(ctx, agent->broadcast_func, JS_UNDEFINED, - 2, (JSValueConst *)args); + 2, args); JS_FreeValue(ctx, args[0]); JS_FreeValue(ctx, args[1]); if (JS_IsException(ret_val)) @@ -528,12 +685,13 @@ static void *agent_start(void *arg) 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; if (JS_GetContextOpaque(ctx) != NULL) return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); - + script = JS_ToCString(ctx, argv[0]); if (!script) return JS_EXCEPTION; @@ -542,26 +700,28 @@ static JSValue js_agent_start(JSContext *ctx, JSValue 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, &agent_list); - pthread_create(&agent->tid, NULL, agent_start, agent); + list_add_tail(&agent->link, &tls->agent_list); + start_thread(&agent->tid, agent_start, agent); 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, &agent_list) { + + list_for_each_safe(el, el1, &tls->agent_list) { agent = list_entry(el, Test262Agent, link); - pthread_join(agent->tid, NULL); + join_thread(agent->tid); JS_FreeValue(ctx, agent->broadcast_sab); list_del(&agent->link); free(agent); } } - + static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { @@ -572,11 +732,11 @@ static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val, return JS_UNDEFINED; } -static BOOL is_broadcast_pending(void) +static BOOL is_broadcast_pending(ThreadLocalStorage *tls) { struct list_head *el; Test262Agent *agent; - list_for_each(el, &agent_list) { + list_for_each(el, &tls->agent_list) { agent = list_entry(el, Test262Agent, link); if (agent->broadcast_pending) return TRUE; @@ -587,26 +747,27 @@ static BOOL is_broadcast_pending(void) static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { - JSValueConst sab = argv[0]; + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); + JSValue sab = argv[0]; struct list_head *el; Test262Agent *agent; uint8_t *buf; size_t buf_size; int32_t val; - + if (JS_GetContextOpaque(ctx) != NULL) return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); - + buf = JS_GetArrayBuffer(ctx, &buf_size, sab); if (!buf) return JS_EXCEPTION; if (JS_ToInt32(ctx, &val, argv[1])) return JS_EXCEPTION; - + /* broadcast the values and wait until all agents have started calling their callbacks */ - pthread_mutex_lock(&agent_mutex); - list_for_each(el, &agent_list) { + js_mutex_lock(&tls->agent_mutex); + list_for_each(el, &tls->agent_list) { agent = list_entry(el, Test262Agent, link); agent->broadcast_pending = TRUE; /* the shared array buffer is used by the thread, so increment @@ -616,12 +777,12 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, agent->broadcast_sab_size = buf_size; agent->broadcast_val = val; } - pthread_cond_broadcast(&agent_cond); + js_cond_broadcast(&tls->agent_cond); - while (is_broadcast_pending()) { - pthread_cond_wait(&agent_cond, &agent_mutex); + while (is_broadcast_pending(tls)) { + js_cond_wait(&tls->agent_cond, &tls->agent_mutex); } - pthread_mutex_unlock(&agent_mutex); + js_mutex_unlock(&tls->agent_mutex); return JS_UNDEFINED; } @@ -644,15 +805,23 @@ static JSValue js_agent_sleep(JSContext *ctx, JSValue this_val, 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, JSValue this_val, @@ -664,17 +833,18 @@ static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val, 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; - pthread_mutex_lock(&report_mutex); - if (list_empty(&report_list)) { + js_mutex_lock(&tls->report_mutex); + if (list_empty(&tls->report_list)) { rep = NULL; } else { - rep = list_entry(report_list.next, AgentReport, link); + rep = list_entry(tls->report_list.next, AgentReport, link); list_del(&rep->link); } - pthread_mutex_unlock(&report_mutex); + js_mutex_unlock(&tls->report_mutex); if (rep) { ret = JS_NewString(ctx, rep->str); free(rep->str); @@ -688,6 +858,7 @@ static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val, 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; @@ -697,10 +868,10 @@ static JSValue js_agent_report(JSContext *ctx, JSValue this_val, rep = malloc(sizeof(*rep)); rep->str = strdup(str); JS_FreeCString(ctx, str); - - pthread_mutex_lock(&report_mutex); - list_add_tail(&rep->link, &report_list); - pthread_mutex_unlock(&report_mutex); + + js_mutex_lock(&tls->report_mutex); + list_add_tail(&rep->link, &tls->report_list); + js_mutex_unlock(&tls->report_mutex); return JS_UNDEFINED; } @@ -717,7 +888,7 @@ static const JSCFunctionListEntry js_agent_funcs[] = { JS_CFUNC_DEF("sleep", 1, js_agent_sleep ), JS_CFUNC_DEF("monotonicNow", 0, js_agent_monotonicNow ), }; - + static JSValue js_new_agent(JSContext *ctx) { JSValue agent; @@ -726,14 +897,13 @@ static JSValue js_new_agent(JSContext *ctx) countof(js_agent_funcs)); return agent; } -#endif static JSValue js_createRealm(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSContext *ctx1; JSValue ret; - + ctx1 = JS_NewContext(JS_GetRuntime(ctx)); if (!ctx1) return JS_ThrowOutOfMemory(ctx); @@ -753,11 +923,11 @@ static JSValue add_helpers1(JSContext *ctx) { JSValue global_obj; JSValue obj262, obj; - + global_obj = JS_GetGlobalObject(ctx); JS_SetPropertyStr(ctx, global_obj, "print", - JS_NewCFunction(ctx, js_print, "print", 1)); + JS_NewCFunction(ctx, js_print_262, "print", 1)); /* $262 special object used by the tests */ obj262 = JS_NewObject(ctx); @@ -765,14 +935,12 @@ static JSValue add_helpers1(JSContext *ctx) JS_NewCFunction(ctx, js_detachArrayBuffer, "detachArrayBuffer", 1)); JS_SetPropertyStr(ctx, obj262, "evalScript", - JS_NewCFunction(ctx, js_evalScript, + JS_NewCFunction(ctx, js_evalScript_262, "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)); @@ -784,7 +952,7 @@ static JSValue add_helpers1(JSContext *ctx) JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj); JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262)); - + JS_FreeValue(ctx, global_obj); return obj262; } @@ -813,14 +981,27 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, uint8_t *buf; JSModuleDef *m; JSValue func_val; - + char *filename, *slash, path[1024]; + + // interpret import("bar.js") from path/to/foo.js as + // import("path/to/bar.js") but leave import("./bar.js") untouched + filename = opaque; + if (!strchr(module_name, '/')) { + slash = strrchr(filename, '/'); + if (slash) { + snprintf(path, sizeof(path), "%.*s/%s", + (int) (slash - filename), filename, module_name); + module_name = path; + } + } + 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); @@ -881,7 +1062,7 @@ void update_exclude_dirs(void) /* split directpries from exclude_list */ for (count = i = 0; i < ep->count; i++) { name = ep->array[i]; - if (has_suffix(name, "/")) { + if (js__has_suffix(name, "/")) { namelist_add(dp, NULL, name); free(name); } else { @@ -910,7 +1091,7 @@ void update_exclude_dirs(void) lp->count = count; } -void load_config(const char *filename) +void load_config(const char *filename, const char *ignore) { char buf[1024]; FILE *f; @@ -924,19 +1105,19 @@ void load_config(const char *filename) } section = SECTION_NONE; int lineno = 0; - f = fopen(filename, "rb"); + f = fopen(filename, "r"); if (!f) { perror_exit(1, filename); } base_name = get_basename(filename); - + while (fgets(buf, sizeof(buf), f) != NULL) { char *p, *q; lineno++; p = str_strip(buf); if (*p == '#' || *p == ';' || *p == '\0') continue; /* line comment */ - + if (*p == "[]"[0]) { /* new section */ p++; @@ -965,8 +1146,12 @@ void load_config(const char *filename) printf("%s:%d: syntax error\n", filename, lineno); continue; } - if (str_equal(p, "style")) { - new_style = str_equal(q, "new"); + if (strstr(ignore, p)) { + printf("%s:%d: ignoring %s=%s\n", filename, lineno, p, q); + continue; + } + if (str_equal(p, "local")) { + local = str_equal(q, "yes"); continue; } if (str_equal(p, "testdir")) { @@ -1002,7 +1187,7 @@ void load_config(const char *filename) test_mode = TEST_STRICT; else if (str_equal(q, "all") || str_equal(q, "both")) test_mode = TEST_ALL; - else + else fatal(2, "unknown test mode: %s", q); continue; } @@ -1025,7 +1210,8 @@ void load_config(const char *filename) continue; } if (str_equal(p, "verbose")) { - verbose = str_equal(q, "yes"); + int count = str_count(q, "yes"); + verbose = max_int(verbose, count); continue; } if (str_equal(p, "errorfile")) { @@ -1038,15 +1224,11 @@ void load_config(const char *filename) 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")) + if (!q || str_equal(q, "yes") || (!CC_IS_TCC && str_equal(q, "!tcc"))) str_append(&harness_features, " ", p); else str_append(&harness_skip_features, " ", p); @@ -1083,7 +1265,7 @@ char *find_error(const char *filename, int *pline, int is_strict) q++; } /* check strict mode indicator */ - if (!strstart(q, "strict mode: ", &q) != !is_strict) + if (!js__strstart(q, "strict mode: ", &q) != !is_strict) continue; r = q = skip_prefix(q, "unexpected error: "); r += strcspn(r, "\n"); @@ -1143,7 +1325,7 @@ int longest_match(const char *str, const char *find, int pos, int *ppos, int lin int len, maxlen; maxlen = 0; - + if (*find) { const char *p; for (p = str + pos; *p; p++) { @@ -1169,14 +1351,16 @@ 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, FILE *outfile, int eval_flags, - int is_async) + const char *error_type, int eval_flags, int is_async, + int *msec) { + 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; const char *error_name; - + int start, duration; + pos = skip_comments(buf, 1, &pos_line); error_line = pos_line; has_error_line = FALSE; @@ -1185,8 +1369,9 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, /* a module evaluation returns a promise */ ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0); - async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ - + tls->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)) { @@ -1205,7 +1390,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, } else if (ret == 0) { if (is_async) { /* test if the test called $DONE() once */ - if (async_done != 1) { + if (tls->async_done != 1) { res_val = JS_ThrowTypeError(ctx, "$DONE() not called"); } else { res_val = JS_UNDEFINED; @@ -1226,20 +1411,17 @@ 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); - /* 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); - } + js_print_262(ctx, JS_NULL, 1, &exception_val); if (is_error) { JSValue name, stack; const char *stack_str; - + name = JS_GetPropertyStr(ctx, exception_val, "name"); error_name = JS_ToCString(ctx, name); stack = JS_GetPropertyStr(ctx, exception_val, "stack"); @@ -1248,10 +1430,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, if (stack_str) { 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] == ':') { @@ -1269,13 +1448,17 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, if (error_type) { char *error_class; const char *msg; - + msg = JS_ToCString(ctx, exception_val); - error_class = strdup_len(msg, strcspn(msg, ":")); - if (!str_equal(error_class, error_type)) + if (msg == NULL) { ret = -1; - free(error_class); - JS_FreeCString(ctx, msg); + } else { + error_class = strdup_len(msg, strcspn(msg, ":")); + if (!str_equal(error_class, error_type)) + ret = -1; + free(error_class); + JS_FreeCString(ctx, msg); + } } } else { ret = -1; @@ -1293,6 +1476,7 @@ 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); @@ -1302,14 +1486,15 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, if (ret == 0) { if (msg && s && (str_equal(s, "expected error") || - strstart(s, "unexpected error type:", NULL) || + js__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); - fixed_errors++; + atomic_inc(&fixed_errors); + is_unexpected_error = FALSE; } } else { if (!s) { // not yet reported @@ -1320,7 +1505,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); } - new_errors++; + atomic_inc(&new_errors); } } } else { // should not have error @@ -1339,22 +1524,45 @@ 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); - changed_errors++; + atomic_inc(&changed_errors); } else { - new_errors++; + atomic_inc(&new_errors); } } } else { if (s) { printf("%s:%d: %sOK, fixed error: %s\n", filename, s_line, strict_mode, s); - fixed_errors++; + atomic_inc(&fixed_errors); + is_unexpected_error = FALSE; } } } + if (is_unexpected_error && verbose > 1) { + 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) { + JSValue val = js_std_loop(ctx); + if (JS_IsException(val)) { + js_std_dump_error1(ctx, val); + ret = -1; + } + JS_FreeValue(ctx, val); + } + JS_FreeCString(ctx, error_name); JS_FreeValue(ctx, exception_val); JS_FreeValue(ctx, res_val); @@ -1367,14 +1575,15 @@ 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, stderr, - eval_flags, FALSE)) { + if (eval_buf(ctx, buf, buf_len, filename, FALSE, FALSE, NULL, + eval_flags, FALSE, &msec)) { warning("error evaluating %s", filename); goto fail; } @@ -1388,15 +1597,15 @@ fail: return 1; } -char *extract_desc(const char *buf, char style) +char *extract_desc(const char *buf) { const char *p, *desc_start; char *desc; int len; - + p = buf; while (*p != '\0') { - if (p[0] == '/' && p[1] == '*' && p[2] == style && p[3] != '/') { + if (p[0] == '/' && p[1] == '*' && p[2] == '-' && p[3] != '/') { p += 3; desc_start = p; while (*p != '\0' && (p[0] != '*' || p[1] != '/')) @@ -1473,9 +1682,12 @@ 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) { @@ -1515,22 +1727,38 @@ void update_stats(JSRuntime *rt, const char *filename) { update(fast_array_elements); } #undef update + js_mutex_unlock(&stats_mutex); } -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) +JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx; + + 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"); + } + 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, int *msec) { JSRuntime *rt; JSContext *ctx; int i, ret; - + rt = JS_NewRuntime(); if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); - } - ctx = JS_NewContext(rt); + } + JS_SetRuntimeOpaque(rt, tls); + js_std_init_handlers(rt); + ctx = JS_NewCustomContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); fatal(1, "JS_NewContext failure"); @@ -1538,44 +1766,46 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip, JS_SetRuntimeInfo(rt, filename); JS_SetCanBlock(rt, can_block); - + /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL); - + JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); + add_helpers(ctx); for (i = 0; i < ip->count; i++) { - if (eval_file(ctx, harness, ip->array[i], - JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_STRIP)) { + 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, outfile, eval_flags, is_async); + error_type, eval_flags, is_async, msec); 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); - test_count++; - if (ret) { - test_failed++; - if (outfile) { - /* do not output a failure number to minimize diff */ - fprintf(outfile, " FAILED\n"); - } - } + atomic_inc(&test_count); + if (ret) + atomic_inc(&test_failed); return ret; } -int run_test(const char *filename, int index) +int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) { char harnessbuf[1024]; char *harness; @@ -1585,9 +1815,10 @@ int run_test(const char *filename, int index) 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 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; error_type = NULL; @@ -1595,151 +1826,95 @@ int run_test(const char *filename, int index) harness = harness_dir; - 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; + if (!harness) { + p = strstr(filename, "test/"); + if (p) { + snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", + (int)(p - filename), filename, "harness"); } + 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); - } - 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, "module")) { - is_module = TRUE; - skip |= skip_module; - } - else if (str_equal(option, "CanBlockIsFalse")) { - can_block = FALSE; - } - free(option); - } - } - p = find_tag(desc, "negative:", &state); - if (p) { - /* XXX: should extract the phase */ - char *q = find_tag(p, "type:", &state); - if (q) { - while (isspace(*q)) - q++; - error_type = strdup_len(q, strcspn(q, " \n")); - } - is_negative = TRUE; - } - 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); - } - } - free(desc); - } - 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), ""); - } - harness = harnessbuf; - } - - 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); - } - - /* 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); + /* 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); + } + } + 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, "module")) { + is_module = TRUE; + skip |= skip_module; + } + else if (str_equal(option, "CanBlockIsFalse")) { + can_block = FALSE; + } + free(option); + } + } + 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")); + } + is_negative = TRUE; + } + 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); + } + } + free(desc); } + 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 @@ -1778,32 +1953,27 @@ int run_test(const char *filename, int index) } if (skip || use_strict + use_nostrict == 0) { - test_skipped++; + atomic_inc(&test_skipped); ret = -2; } else { - clock_t clocks; - + if (local && detect_module) { + is_module = JS_DetectModule(buf, buf_len); + } 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(filename, harness, ip, buf, buf_len, + ret = run_test_buf(tls, filename, harness, ip, buf, buf_len, error_type, eval_flags, is_negative, is_async, - can_block); + can_block, msec); } if (use_strict) { - ret |= run_test_buf(filename, harness, ip, buf, buf_len, + ret |= run_test_buf(tls, filename, harness, ip, buf, buf_len, error_type, eval_flags | JS_EVAL_FLAG_STRICT, - 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)); + is_negative, is_async, can_block, msec); } } namelist_free(&include_list); @@ -1814,7 +1984,8 @@ int run_test(const char *filename, int index) } /* run a test when called by test262-harness+eshost */ -int run_test262_harness_test(const char *filename, BOOL is_module) +int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, + BOOL is_module) { JSRuntime *rt; JSContext *ctx; @@ -1823,13 +1994,14 @@ int run_test262_harness_test(const char *filename, BOOL is_module) int eval_flags, ret_code, ret; JSValue res_val; BOOL can_block; - - outfile = stdout; /* for js_print */ + + outfile = stdout; /* for js_print_262 */ 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); @@ -1839,10 +2011,10 @@ int run_test262_harness_test(const char *filename, BOOL is_module) can_block = TRUE; JS_SetCanBlock(rt, can_block); - + /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL); - + JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); + add_helpers(ctx); buf = load_file(filename, &buf_len); @@ -1873,22 +2045,20 @@ int run_test262_harness_test(const char *filename, BOOL is_module) } 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; @@ -1896,72 +2066,76 @@ int run_test262_harness_test(const char *filename, BOOL is_module) clock_t last_clock; -void show_progress(int force) { - clock_t t = clock(); - if (force || !last_clock || (t - last_clock) > CLOCKS_PER_SEC / 20) { - last_clock = t; +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\033[K\r", - test_failed, test_count, test_skipped); + fprintf(stderr, "%d/%d/%d \r", + atomic_load(&test_failed), + atomic_load(&test_count), + atomic_load(&test_skipped)); fflush(stderr); } + js_mutex_unlock(&progress_mutex); + return NULL; } -static int slow_test_threshold; +enum { INCLUDE, EXCLUDE, SKIP }; -void run_test_dir_list(namelist_t *lp, int start_index, int stop_index) +int include_exclude_or_skip(int i) // naming is hard... { - int i; + 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; +} - 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++; +void *run_test_dir_list(void *arg) +{ + ThreadLocalStorage tls_s, *tls = &tls_s; + const char *p; + int i, msec; + + init_thread_local_storage(tls); + + 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); } - show_progress(TRUE); + return NULL; } void help(void) { - printf("run-test262 version " CONFIG_VERSION "\n" + printf("run-test262 version %s\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" "-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" - "-r file set the report file name (default=none)\n" - "-x file exclude tests listed in 'file'\n"); + "-x file exclude tests listed in 'file'\n", + JS_GetVersion()); exit(1); } @@ -1975,18 +2149,40 @@ char *get_opt_arg(const char *option, char *arg) int main(int argc, char **argv) { - int optind, start_index, stop_index; + ThreadLocalStorage tls_s, *tls = &tls_s; + int i, optind; BOOL is_dir_list; BOOL only_check_errors = FALSE; const char *filename; + const char *ignore = ""; BOOL is_test262_harness = FALSE; BOOL is_module = FALSE; -#if !defined(_WIN32) + js_std_set_worker_new_context_func(JS_NewCustomContext); + + init_thread_local_storage(tls); + js_mutex_init(&stats_mutex); + +#ifndef _WIN32 /* 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)) + optind++; + if (strstr("-d -f", arg)) + ignore = "testdir"; // run only the tests from -d or -f + } + /* cannot use getopt because we want to pass the command line to the script */ optind = 1; @@ -2000,18 +2196,16 @@ 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, "-u")) { update_errors++; - } else if (str_equal(arg, "-v")) { - verbose++; + } else if (arg == strstr(arg, "-v")) { + verbose += str_count(arg, "v"); } else if (str_equal(arg, "-c")) { - load_config(get_opt_arg(arg, argv[optind++])); + load_config(get_opt_arg(arg, argv[optind++]), ignore); } else if (str_equal(arg, "-d")) { enumerate_tests(get_opt_arg(arg, argv[optind++])); } else if (str_equal(arg, "-e")) { @@ -2020,12 +2214,12 @@ int main(int argc, char **argv) namelist_load(&exclude_list, get_opt_arg(arg, argv[optind++])); } else if (str_equal(arg, "-f")) { 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; } 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; } else if (str_equal(arg, "--module")) { @@ -2035,14 +2229,17 @@ int main(int argc, char **argv) break; } } - + if (optind >= argc && !test_list.count) help(); if (is_test262_harness) { - return run_test262_harness_test(argv[optind], is_module); + return run_test262_harness_test(tls, 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); @@ -2063,7 +2260,7 @@ int main(int argc, char **argv) update_exclude_dirs(); if (is_dir_list) { - if (optind < argc && !isdigit(argv[optind][0])) { + if (optind < argc && !isdigit((unsigned char)argv[optind][0])) { filename = argv[optind++]; namelist_load(&test_list, filename); } @@ -2075,26 +2272,36 @@ int main(int argc, char **argv) stop_index = atoi(argv[optind++]); } } - 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); + // 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; } } - run_test_dir_list(&test_list, start_index, stop_index); - - if (outfile && outfile != stdout) { - fclose(outfile); - outfile = NULL; - } + js_cond_init(&progress_cond); + js_mutex_init(&progress_mutex); + start_thread(&progress_thread, show_progress, NULL); + for (i = 0; i < nthreads; i++) + start_thread(&threads[i], run_test_dir_list, (void *)(uintptr_t)i); + for (i = 0; i < nthreads; i++) + join_thread(threads[i]); + js_mutex_lock(&progress_mutex); + js_cond_signal(&progress_cond); + js_mutex_unlock(&progress_mutex); + join_thread(progress_thread); + js_mutex_destroy(&progress_mutex); + js_cond_destroy(&progress_cond); } else { - outfile = stdout; while (optind < argc) { - run_test(argv[optind++], -1); + int msec = 0; + run_test(tls, argv[optind++], &msec); } } @@ -2139,7 +2346,12 @@ int main(int argc, char **argv) free(harness_dir); free(harness_features); free(harness_exclude); + free(harness_skip_features); free(error_file); + free(error_filename); + free(stats_min_filename); + free(stats_max_filename); - return 0; + /* Signal that the error file is out of date. */ + return new_errors || changed_errors || fixed_errors; } diff --git a/standalone.js b/standalone.js new file mode 100644 index 0000000..912e524 --- /dev/null +++ b/standalone.js @@ -0,0 +1,129 @@ +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 ?? 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 = 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/test.js b/test.js deleted file mode 100644 index 1be0311..0000000 --- a/test.js +++ /dev/null @@ -1,5 +0,0 @@ -function test() { -breakFunction(); -console.warn("lol it works!"); -} -test() diff --git a/test262-fast.conf b/test262-fast.conf new file mode 100644 index 0000000..ef36cee --- /dev/null +++ b/test262-fast.conf @@ -0,0 +1,132 @@ +[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/test262.conf b/test262.conf index fd9862e..16d8733 100644 --- a/test262.conf +++ b/test262.conf @@ -1,9 +1,6 @@ [config] # general settings for test262 ES6 version -# framework style: old, new -style=new - # handle tests tagged as [noStrict]: yes, no, skip nostrict=yes @@ -37,9 +34,6 @@ 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 @@ -61,15 +55,16 @@ Array.fromAsync=skip Array.prototype.at Array.prototype.flat Array.prototype.flatMap -Array.prototype.flatten Array.prototype.includes Array.prototype.values ArrayBuffer -arraybuffer-transfer=skip +arraybuffer-transfer arrow-function async-functions async-iteration -Atomics +# atomics are broken in recent versions of tcc +Atomics=!tcc +Atomics.pause=!tcc Atomics.waitAsync=skip BigInt caller @@ -83,7 +78,6 @@ class-static-block class-static-fields-private class-static-fields-public class-static-methods-private -cleanupSome=skip coalesce-expression computed-property-names const @@ -103,11 +97,13 @@ destructuring-assignment destructuring-binding dynamic-import error-cause +Error.isError +explicit-resource-management=skip exponentiation export-star-as-namespace-from-module -FinalizationGroup=skip +FinalizationRegistry FinalizationRegistry.prototype.cleanupSome=skip -FinalizationRegistry=skip +Float16Array Float32Array Float64Array for-in-order @@ -122,8 +118,25 @@ 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=skip +iterator-helpers json-modules=skip json-parse-with-source=skip json-superset @@ -131,6 +144,7 @@ legacy-regexp=skip let logical-assignment-operators Map +Math.sumPrecise new.target numeric-separator-literal object-rest @@ -141,6 +155,7 @@ Object.is optional-catch-binding optional-chaining Promise +promise-try promise-with-resolvers Promise.allSettled Promise.any @@ -155,15 +170,19 @@ 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=skip -resizable-arraybuffer=skip +regexp-v-flag +RegExp.escape +resizable-arraybuffer rest-parameters Set -set-methods=skip +set-methods ShadowRealm=skip SharedArrayBuffer +source-phase-imports-module-source=skip +source-phase-imports=skip string-trimming String.fromCodePoint String.prototype.at @@ -191,7 +210,7 @@ Symbol.split Symbol.toPrimitive Symbol.toStringTag Symbol.unscopables -symbols-as-weakmap-keys=skip +symbols-as-weakmap-keys tail-call-optimization=skip template Temporal=skip @@ -202,9 +221,10 @@ u180e Uint16Array Uint32Array Uint8Array +uint8array-base64=skip Uint8ClampedArray WeakMap -WeakRef=skip +WeakRef WeakSet well-formed-json-stringify @@ -223,5 +243,147 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js #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 + [tests] # list test files or use config.testdir diff --git a/test262_errors.txt b/test262_errors.txt index edf5372..85eb1cf 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -1,8 +1,84 @@ -test262/test/annexB/language/eval-code/direct/script-decl-lex-collision-in-sloppy-mode.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all -test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: Test262Error: Expected a DummyError but got a TypeError -test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError -test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: Test262Error: Expected a DummyError but got a TypeError -test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError +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/AsyncFromSyncIteratorPrototype/throw/throw-undefined-get-return-undefined.js:64: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-get-return-undefined.js:64: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-poisoned-return.js:68: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-poisoned-return.js:68: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-not-object.js:72: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-not-object.js:72: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: strict mode: TypeError: $DONE() not called +test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true +test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: strict mode: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true +test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: TypeError: cannot read property 'call' of undefined +test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: strict mode: TypeError: cannot read property 'call' of undefined +test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: TypeError: out-of-bound index in typed array +test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: strict mode: TypeError: out-of-bound index in typed array +test262/test/built-ins/Object/defineProperty/coerced-P-shrink.js:16: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/built-ins/Object/defineProperty/coerced-P-shrink.js:16: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/built-ins/Object/defineProperty/typedarray-backed-by-resizable-buffer.js:18: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +test262/test/built-ins/Object/defineProperty/typedarray-backed-by-resizable-buffer.js:18: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all +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/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/global-code/script-decl-lex-var-declared-via-eval-sloppy.js:13: Test262Error: variable Expected a SyntaxError to be thrown but no exception was thrown at all +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/async-module-does-not-block-sibling-modules.js:13: SyntaxError: Could not find export 'check' in module 'test262/test/language/module-code/top-level-await/async-module-sync_FIXTURE.js' +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/test262o.conf b/test262o.conf deleted file mode 100644 index 669dead..0000000 --- a/test262o.conf +++ /dev/null @@ -1,410 +0,0 @@ -[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 - -[tests] -# list test files or use config.testdir diff --git a/tests.conf b/tests.conf new file mode 100644 index 0000000..0a3808e --- /dev/null +++ b/tests.conf @@ -0,0 +1,9 @@ +[config] +local=yes +verbose=yes +testdir=tests + +[exclude] +tests/fixture_cyclic_import.js +tests/microbench.js +tests/test_worker_module.js diff --git a/tests/assert.js b/tests/assert.js new file mode 100644 index 0000000..c8240c8 --- /dev/null +++ b/tests/assert.js @@ -0,0 +1,49 @@ +export function assert(actual, expected, message) { + if (arguments.length === 1) + 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 (typeof actual === 'object') { + if (actual !== null && expected !== null + && actual.constructor === expected.constructor + && actual.toString() === expected.toString()) + return; + } + } + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +export function assertThrows(err, func) +{ + var ex; + ex = false; + try { + func(); + } catch(e) { + ex = true; + assert(e instanceof err); + } + assert(ex, true, "exception expected"); +} + +export function assertArrayEquals(a, b) +{ + if (!Array.isArray(a) || !Array.isArray(b)) + return assert(false); + + assert(a.length, b.length); + + a.forEach((value, idx) => { + assert(b[idx], value); + }); +} diff --git a/tests/bjson.c b/tests/bjson.c deleted file mode 100644 index 8e52741..0000000 --- a/tests/bjson.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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/tests/bug633/0.js b/tests/bug633/0.js new file mode 100644 index 0000000..155d3a4 --- /dev/null +++ b/tests/bug633/0.js @@ -0,0 +1,7 @@ +/*--- +flags: [qjs:no-detect-module] +negative: + phase: parse + type: SyntaxError +---*/ +const undefined = 42 // SyntaxError at global scope diff --git a/tests/bug633/1.js b/tests/bug633/1.js new file mode 100644 index 0000000..1aa83ba --- /dev/null +++ b/tests/bug633/1.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module, module] +---*/ +const undefined = 42 // not a SyntaxError at toplevel module scope diff --git a/tests/bug633/2.js b/tests/bug633/2.js new file mode 100644 index 0000000..70a3301 --- /dev/null +++ b/tests/bug633/2.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module] +---*/ +{ const undefined = 42 } // not a SyntaxError, not at global scope diff --git a/tests/bug633/3.js b/tests/bug633/3.js new file mode 100644 index 0000000..2bfa1ce --- /dev/null +++ b/tests/bug633/3.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module] +---*/ +;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope diff --git a/tests/bug645/0.js b/tests/bug645/0.js new file mode 100644 index 0000000..00bdac8 --- /dev/null +++ b/tests/bug645/0.js @@ -0,0 +1,4 @@ +"use strict"; + +const u8 = new Uint8Array(1); +u8[100] = 123; // Should not throw. diff --git a/tests/bug645/1.js b/tests/bug645/1.js new file mode 100644 index 0000000..8031be2 --- /dev/null +++ b/tests/bug645/1.js @@ -0,0 +1,9 @@ +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/tests/bug645/2.js b/tests/bug645/2.js new file mode 100644 index 0000000..3076efa --- /dev/null +++ b/tests/bug645/2.js @@ -0,0 +1,7 @@ +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/tests/bug648.js b/tests/bug648.js new file mode 100644 index 0000000..cb0a7d3 --- /dev/null +++ b/tests/bug648.js @@ -0,0 +1,13 @@ +/*--- +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/tests/bug652.js b/tests/bug652.js new file mode 100644 index 0000000..27dea3b --- /dev/null +++ b/tests/bug652.js @@ -0,0 +1,4 @@ +import { assert } from "./assert.js" +const ref = new WeakRef({}) +const val = ref.deref() // should not throw +assert(val, undefined) diff --git a/tests/bug741.js b/tests/bug741.js new file mode 100644 index 0000000..3947f71 --- /dev/null +++ b/tests/bug741.js @@ -0,0 +1,19 @@ +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/tests/bug775.js b/tests/bug775.js new file mode 100644 index 0000000..4cb9387 --- /dev/null +++ b/tests/bug775.js @@ -0,0 +1,7 @@ +/*--- +negative: + phase: runtime + type: RangeError +---*/ +function f() { f() } // was problematic under ASan +f() diff --git a/tests/bug776.js b/tests/bug776.js new file mode 100644 index 0000000..4b092c2 --- /dev/null +++ b/tests/bug776.js @@ -0,0 +1,7 @@ +/*--- +negative: + phase: runtime + type: RangeError +---*/ +function f() { f.apply(null) } // was problematic under ASan +f() diff --git a/tests/detect_module/0.js b/tests/detect_module/0.js new file mode 100644 index 0000000..18a9109 --- /dev/null +++ b/tests/detect_module/0.js @@ -0,0 +1 @@ +await undefined diff --git a/tests/detect_module/1.js b/tests/detect_module/1.js new file mode 100644 index 0000000..0212282 --- /dev/null +++ b/tests/detect_module/1.js @@ -0,0 +1,2 @@ +const p = Promise.resolve(42) +await p diff --git a/tests/detect_module/2.js b/tests/detect_module/2.js new file mode 100644 index 0000000..0b1d1f7 --- /dev/null +++ b/tests/detect_module/2.js @@ -0,0 +1 @@ +await = 42 // parsed as classic script diff --git a/tests/detect_module/3.js b/tests/detect_module/3.js new file mode 100644 index 0000000..5b175e9 --- /dev/null +++ b/tests/detect_module/3.js @@ -0,0 +1,8 @@ +/*--- +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/tests/detect_module/4.js b/tests/detect_module/4.js new file mode 100644 index 0000000..5713f31 --- /dev/null +++ b/tests/detect_module/4.js @@ -0,0 +1,3 @@ +// imports should classify it as a module, even when not at the top +os.now() +import * as os from "qjs:os" diff --git a/tests/fixture_cyclic_import.js b/tests/fixture_cyclic_import.js new file mode 100644 index 0000000..bac80d8 --- /dev/null +++ b/tests/fixture_cyclic_import.js @@ -0,0 +1,2 @@ +import * as a from "./test_cyclic_import.js" +export function f(x) { return 2 * a.g(x) } diff --git a/tests/function_source.js b/tests/function_source.js new file mode 100644 index 0000000..640420a --- /dev/null +++ b/tests/function_source.js @@ -0,0 +1,14 @@ +"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/tests/microbench.js b/tests/microbench.js index c1b57bb..5560c24 100644 --- a/tests/microbench.js +++ b/tests/microbench.js @@ -22,8 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import * as std from "std"; -import * as os from "os"; +import * as std from "qjs:std"; +import * as os from "qjs:os"; function pad(str, n) { str += ""; @@ -61,7 +61,7 @@ function toPrec(n, prec) { s = s.substring(0, i) + "." + s.substring(i); return s; } - + var ref_data; var log_data; @@ -94,12 +94,11 @@ function log_line() { console.log(s); } -var clocks_per_sec = 1000; -var max_iterations = 10; -var clock_threshold = 100; /* favoring short measuring spans */ +var clocks_per_sec = 1000000; +var max_iterations = 100; +var clock_threshold = 2000; /* favoring short measuring spans */ var min_n_argument = 1; -//var get_clock = Date.now; -var get_clock = os.now; +var get_clock = os.cputime ?? os.now; function log_one(text, n, ti) { var ref; @@ -551,29 +550,6 @@ function float_arith(n) return n * 1000; } -function bigfloat_arith(n) -{ - var i, j, sum, a, incr, a0; - global_res = 0; - a0 = BigFloat("0.1"); - incr = BigFloat("1.1"); - for(j = 0; j < n; j++) { - sum = 0; - a = a0; - for(i = 0; i < 1000; i++) { - sum += a * a; - a += incr; - } - global_res += sum; - } - return n * 1000; -} - -function float256_arith(n) -{ - return BigFloatEnv.setPrec(bigfloat_arith.bind(null, n), 237, 19); -} - function bigint_arith(n, bits) { var i, j, sum, a, incr, a0, sum0; @@ -678,6 +654,30 @@ function math_min(n) return n * 1000; } +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++) + r = /the quick brown fox/.exec(s) + global_res = r; + } + return n * 10000; +} + +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++) + r = /the quick brown ᶠᵒˣ/.exec(s) + global_res = r; + } + return n * 10000; +} + /* incremental string contruction as local var */ function string_build1(n) { @@ -876,9 +876,23 @@ function int_to_string(n) var s, r, j; r = 0; for(j = 0; j < n; j++) { - s = (j + 1).toString(); + s = (j % 10) + ''; + s = (j % 100) + ''; + s = (j) + ''; } - return n; + return n * 3; +} + +function int_toString(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10).toString(); + s = (j % 100).toString(); + s = (j).toString(); + } + return n * 3; } function float_to_string(n) @@ -886,9 +900,59 @@ function float_to_string(n) var s, r, j; r = 0; for(j = 0; j < n; j++) { - s = (j + 0.1).toString(); + s = (j % 10 + 0.1) + ''; + s = (j + 0.1) + ''; + s = (j * 12345678 + 0.1) + ''; } - return n; + return n * 3; +} + +function float_toString(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toString(); + s = (j + 0.1).toString(); + s = (j * 12345678 + 0.1).toString(); + } + return n * 3; +} + +function float_toFixed(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toFixed(j % 16); + s = (j + 0.1).toFixed(j % 16); + s = (j * 12345678 + 0.1).toFixed(j % 16); + } + return n * 3; +} + +function float_toPrecision(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toPrecision(j % 16 + 1); + s = (j + 0.1).toPrecision(j % 16 + 1); + s = (j * 12345678 + 0.1).toPrecision(j % 16 + 1); + } + return n * 3; +} + +function float_toExponential(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toExponential(j % 16); + s = (j + 0.1).toExponential(j % 16); + s = (j * 12345678 + 0.1).toExponential(j % 16); + } + return n * 3; } function string_to_int(n) @@ -975,29 +1039,32 @@ function main(argc, argv, g) array_for_in, array_for_of, math_min, + regexp_ascii, + regexp_utf16, string_build1, string_build2, //string_build3, //string_build4, sort_bench, int_to_string, + int_toString, float_to_string, + float_toString, + float_toFixed, + float_toPrecision, + float_toExponential, string_to_int, string_to_float, ]; var tests = []; - var i, j, n, f, name; - + var i, j, n, f, name, found; + if (typeof BigInt == "function") { /* BigInt test */ test_list.push(bigint64_arith); test_list.push(bigint256_arith); } - if (typeof BigFloat == "function") { - /* BigFloat test */ - test_list.push(float256_arith); - } - + for (i = 1; i < argc;) { name = argv[i++]; if (name == "-a") { @@ -1017,14 +1084,14 @@ function main(argc, argv, g) sort_bench.array_size = +argv[i++]; continue; } - for (j = 0; j < test_list.length; j++) { + for (j = 0, found = false; j < test_list.length; j++) { f = test_list[j]; - if (name === f.name) { + if (f.name.startsWith(name)) { tests.push(f); - break; + found = true; } } - if (j == test_list.length) { + if (!found) { console.log("unknown benchmark: " + name); return 1; } @@ -1047,11 +1114,14 @@ function main(argc, argv, g) log_line("total", "", total[2], total[3], total_score * 100 / total_scale); else log_line("total", "", total[2]); - + if (tests == test_list) save_result("microbench-new.txt", log_data); } -if (!scriptArgs) +if (typeof scriptArgs === "undefined") { scriptArgs = []; + if (typeof process.argv === "object") + scriptArgs = process.argv.slice(1); +} main(scriptArgs.length, scriptArgs, this); diff --git a/tests/test262.patch b/tests/test262.patch deleted file mode 100644 index 6576bdc..0000000 --- a/tests/test262.patch +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js -index 9c1217351e..3c24755558 100644 ---- a/harness/atomicsHelper.js -+++ b/harness/atomicsHelper.js -@@ -227,10 +227,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: 20, -+ small: 20, -+ long: 100, -+ huge: 1000, - }; - - /** -diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js -index be7039fda0..7b38abf8df 100644 ---- a/harness/regExpUtils.js -+++ b/harness/regExpUtils.js -@@ -6,24 +6,27 @@ description: | - defines: [buildString, testPropertyEscapes, 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({ loneCodePoints, ranges }) { -- const CHUNK_SIZE = 10000; -- let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints); -- for (let i = 0; i < ranges.length; i++) { -- const range = ranges[i]; -- const start = range[0]; -- const end = range[1]; -- const codePoints = []; -- for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { -- codePoints[length++] = codePoint; -- if (length === CHUNK_SIZE) { -- result += Reflect.apply(String.fromCodePoint, null, codePoints); -- codePoints.length = length = 0; -- } -+ let result = String.fromCodePoint.apply(null, loneCodePoints); -+ for (const [start, end] of ranges) { -+ result += codePointRange(start, end + 1); - } -- result += Reflect.apply(String.fromCodePoint, null, codePoints); -- } -- return result; -+ return result; - } - - function testPropertyEscapes(regex, string, expression) { diff --git a/tests/test_bigint.js b/tests/test_bigint.js new file mode 100644 index 0000000..5fd1f91 --- /dev/null +++ b/tests/test_bigint.js @@ -0,0 +1,105 @@ +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"); +} + +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/tests/test_bignum.js b/tests/test_bignum.js deleted file mode 100644 index f4f72a0..0000000 --- a/tests/test_bignum.js +++ /dev/null @@ -1,326 +0,0 @@ -"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_divrem(div1, a, b, q) -{ - var div, divrem, t; - div = BigInt[div1]; - divrem = BigInt[div1 + "rem"]; - assert(div(a, b) == q); - t = divrem(a, b); - assert(t[0] == q); - assert(a == b * q + t[1]); -} - -function test_idiv1(div, a, b, r) -{ - test_divrem(div, a, b, r[0]); - test_divrem(div, -a, b, r[1]); - test_divrem(div, a, -b, r[2]); - test_divrem(div, -a, -b, r[3]); -} - -/* QuickJS BigInt extensions */ -function test_bigint_ext() -{ - var r; - assert(BigInt.floorLog2(0n) === -1n); - assert(BigInt.floorLog2(7n) === 2n); - - assert(BigInt.sqrt(0xffffffc000000000000000n) === 17592185913343n); - r = BigInt.sqrtrem(0xffffffc000000000000000n); - assert(r[0] === 17592185913343n); - assert(r[1] === 35167191957503n); - - test_idiv1("tdiv", 3n, 2n, [1n, -1n, -1n, 1n]); - test_idiv1("fdiv", 3n, 2n, [1n, -2n, -2n, 1n]); - test_idiv1("cdiv", 3n, 2n, [2n, -1n, -1n, 2n]); - test_idiv1("ediv", 3n, 2n, [1n, -2n, -1n, 2n]); -} - -function test_bigfloat() -{ - var e, a, b, sqrt2; - - assert(typeof 1n === "bigint"); - assert(typeof 1l === "bigfloat"); - assert(1 == 1.0l); - assert(1 !== 1.0l); - - test_less(2l, 3l); - test_eq(3l, 3l); - - test_less(2, 3l); - test_eq(3, 3l); - - test_less(2.1, 3l); - test_eq(Math.sqrt(9), 3l); - - test_less(2n, 3l); - test_eq(3n, 3l); - - e = new BigFloatEnv(128); - assert(e.prec == 128); - a = BigFloat.sqrt(2l, e); - assert(a === BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e)); - assert(e.inexact === true); - assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcc908b2fb1366ea95l); - - b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128); - assert(a === b); - - assert(BigFloat.isNaN(BigFloat(NaN))); - assert(BigFloat.isFinite(1l)); - assert(!BigFloat.isFinite(1l/0l)); - - assert(BigFloat.abs(-3l) === 3l); - assert(BigFloat.sign(-3l) === -1l); - - assert(BigFloat.exp(0.2l) === 1.2214027581601698339210719946396742l); - assert(BigFloat.log(3l) === 1.0986122886681096913952452369225256l); - assert(BigFloat.pow(2.1l, 1.6l) === 3.277561666451861947162828744873745l); - - assert(BigFloat.sin(-1l) === -0.841470984807896506652502321630299l); - assert(BigFloat.cos(1l) === 0.5403023058681397174009366074429766l); - assert(BigFloat.tan(0.1l) === 0.10033467208545054505808004578111154l); - - assert(BigFloat.asin(0.3l) === 0.30469265401539750797200296122752915l); - assert(BigFloat.acos(0.4l) === 1.1592794807274085998465837940224159l); - assert(BigFloat.atan(0.7l) === 0.610725964389208616543758876490236l); - assert(BigFloat.atan2(7.1l, -5.1l) === 2.1937053809751415549388104628759813l); - - assert(BigFloat.floor(2.5l) === 2l); - assert(BigFloat.ceil(2.5l) === 3l); - assert(BigFloat.trunc(-2.5l) === -2l); - assert(BigFloat.round(2.5l) === 3l); - - assert(BigFloat.fmod(3l,2l) === 1l); - assert(BigFloat.remainder(3l,2l) === -1l); - - /* string conversion */ - assert((1234.125l).toString(), "1234.125"); - assert((1234.125l).toFixed(2), "1234.13"); - assert((1234.125l).toFixed(2, "down"), "1234.12"); - assert((1234.125l).toExponential(), "1.234125e+3"); - assert((1234.125l).toExponential(5), "1.23413e+3"); - assert((1234.125l).toExponential(5, BigFloatEnv.RNDZ), "1.23412e+3"); - assert((1234.125l).toPrecision(6), "1234.13"); - assert((1234.125l).toPrecision(6, BigFloatEnv.RNDZ), "1234.12"); - - /* string conversion with binary base */ - assert((0x123.438l).toString(16), "123.438"); - assert((0x323.438l).toString(16), "323.438"); - assert((0x723.438l).toString(16), "723.438"); - assert((0xf23.438l).toString(16), "f23.438"); - assert((0x123.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "123.44"); - assert((0x323.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "323.44"); - assert((0x723.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "723.44"); - assert((0xf23.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "f23.44"); - assert((0x0.0000438l).toFixed(6, BigFloatEnv.RNDNA, 16), "0.000044"); - assert((0x1230000000l).toFixed(1, BigFloatEnv.RNDNA, 16), "1230000000.0"); - assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "123.44"); - assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDZ, 16), "123.43"); - assert((0x323.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "323.44"); - assert((0x723.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "723.44"); - assert((-0xf23.438l).toPrecision(5, BigFloatEnv.RNDD, 16), "-f23.44"); - assert((0x123.438l).toExponential(4, BigFloatEnv.RNDNA, 16), "1.2344p+8"); -} - -function test_bigdecimal() -{ - assert(1m === 1m); - assert(1m !== 2m); - test_less(1m, 2m); - test_eq(2m, 2m); - - test_less(1, 2m); - test_eq(2, 2m); - - test_less(1.1, 2m); - test_eq(Math.sqrt(4), 2m); - - test_less(2n, 3m); - test_eq(3n, 3m); - - assert(BigDecimal("1234.1") === 1234.1m); - assert(BigDecimal(" 1234.1") === 1234.1m); - assert(BigDecimal(" 1234.1 ") === 1234.1m); - - assert(BigDecimal(0.1) === 0.1m); - assert(BigDecimal(123) === 123m); - assert(BigDecimal(true) === 1m); - - assert(123m + 1m === 124m); - assert(123m - 1m === 122m); - - assert(3.2m * 3m === 9.6m); - assert(10m / 2m === 5m); - assertThrows(RangeError, () => { 10m / 3m } ); - - assert(10m % 3m === 1m); - assert(-10m % 3m === -1m); - - assert(1234.5m ** 3m === 1881365963.625m); - assertThrows(RangeError, () => { 2m ** 3.1m } ); - assertThrows(RangeError, () => { 2m ** -3m } ); - - assert(BigDecimal.sqrt(2m, - { roundingMode: "half-even", - maximumSignificantDigits: 4 }) === 1.414m); - assert(BigDecimal.sqrt(101m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 10.050m); - assert(BigDecimal.sqrt(0.002m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 0.045m); - - assert(BigDecimal.round(3.14159m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 3.142m); - - assert(BigDecimal.add(3.14159m, 0.31212m, - { roundingMode: "half-even", - maximumFractionDigits: 2 }) === 3.45m); - assert(BigDecimal.sub(3.14159m, 0.31212m, - { roundingMode: "down", - maximumFractionDigits: 2 }) === 2.82m); - assert(BigDecimal.mul(3.14159m, 0.31212m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 0.981m); - assert(BigDecimal.mod(3.14159m, 0.31211m, - { roundingMode: "half-even", - maximumFractionDigits: 4 }) === 0.0205m); - assert(BigDecimal.div(20m, 3m, - { roundingMode: "half-even", - maximumSignificantDigits: 3 }) === 6.67m); - assert(BigDecimal.div(20m, 3m, - { roundingMode: "half-even", - maximumFractionDigits: 50 }) === - 6.66666666666666666666666666666666666666666666666667m); - - /* string conversion */ - assert((1234.125m).toString(), "1234.125"); - assert((1234.125m).toFixed(2), "1234.13"); - assert((1234.125m).toFixed(2, "down"), "1234.12"); - assert((1234.125m).toExponential(), "1.234125e+3"); - assert((1234.125m).toExponential(5), "1.23413e+3"); - assert((1234.125m).toExponential(5, "down"), "1.23412e+3"); - assert((1234.125m).toPrecision(6), "1234.13"); - assert((1234.125m).toPrecision(6, "down"), "1234.12"); - assert((-1234.125m).toPrecision(6, "floor"), "-1234.13"); -} - -test_bigint1(); -test_bigint2(); -test_bigint_ext(); -test_bigfloat(); -test_bigdecimal(); diff --git a/tests/test_bjson.js b/tests/test_bjson.js index fcbb8e6..db4a962 100644 --- a/tests/test_bjson.js +++ b/tests/test_bjson.js @@ -1,20 +1,44 @@ -import * as bjson from "./bjson.so"; +import * as std from "qjs:std"; +import * as bjson from "qjs:bjson"; +import { assert } from "./assert.js"; -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 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 toHex(a) @@ -34,7 +58,7 @@ function toHex(a) function isArrayLike(a) { - return Array.isArray(a) || + return Array.isArray(a) || (a instanceof Uint8ClampedArray) || (a instanceof Uint8Array) || (a instanceof Uint16Array) || @@ -42,6 +66,7 @@ function isArrayLike(a) (a instanceof Int8Array) || (a instanceof Int16Array) || (a instanceof Int32Array) || + (a instanceof Float16Array) || (a instanceof Float32Array) || (a instanceof Float64Array); } @@ -85,9 +110,8 @@ function toStr(a) case "undefined": return "undefined"; case "string": - return a.__quote(); + return JSON.stringify(a); case "number": - case "bigfloat": if (a == 0 && 1 / a < 0) return "-0"; else @@ -115,6 +139,41 @@ function bjson_test(a) } } +function bjson_test_arraybuffer() +{ + var buf, array_buffer; + + array_buffer = new ArrayBuffer(4); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, false); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, false); + + array_buffer = new ArrayBuffer(4, {maxByteLength: 4}); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, true); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, true); + + array_buffer = new ArrayBuffer(4, {maxByteLength: 8}); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 8); + assert(array_buffer.resizable, true); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 8); + assert(array_buffer.resizable, true); +} + /* test multiple references to an object including circular references */ function bjson_test_reference() @@ -130,9 +189,9 @@ function bjson_test_reference() array[i].idx = i; array[i].typed_array = new Uint8Array(array_buffer, i, 1); } - buf = bjson.write(array, true); + buf = bjson.write(array, bjson.WRITE_OBJ_REFERENCE); - array = bjson.read(buf, 0, buf.byteLength, true); + array = bjson.read(buf, 0, buf.byteLength, bjson.READ_OBJ_REFERENCE); /* check the result */ for(i = 0; i < n; i++) { @@ -144,10 +203,106 @@ 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 = [ + "EBAAAAAABGA=", + "EObm5oIt", + "EAARABMGBgYGBgYGBgYGBv////8QABEALxH/vy8R/78=", + ]; + for (var input of corpus) { + var buf = base64decode(input); + try { + bjson.read(buf, 0, buf.byteLength); + } catch (e) { + // okay, ignore + } + } +} + function bjson_test_all() { var obj; - + bjson_test({x:1, y:2, if:3}); bjson_test([1, 2, 3]); bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); @@ -155,26 +310,13 @@ function bjson_test_all() bjson_test([BigInt("1"), -BigInt("0x123456789"), BigInt("0x123456789abcdef123456789abcdef")]); } - if (typeof BigFloat !== "undefined") { - BigFloatEnv.setPrec(function () { - bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), - BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), - 0.0 / BigFloat("0"), BigFloat.MAX_VALUE, - BigFloat.MIN_VALUE]); - }, 113, 15); - } - if (typeof BigDecimal !== "undefined") { - bjson_test([BigDecimal("0"), - BigDecimal("0.8"), BigDecimal("123321312321321e100"), - BigDecimal("-1233213123213214332333223332e100"), - BigDecimal("1.233e-1000")]); - } bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]); bjson_test(new Int32Array([123123, 222111, -32222])); + bjson_test(new Float16Array([1024, 1024.5])); bjson_test(new Float64Array([123123, 222111.5])); - + /* tested with a circular reference */ obj = {}; obj.x = obj; @@ -185,7 +327,14 @@ function bjson_test_all() assert(e instanceof TypeError); } + 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/tests/test_builtin.js b/tests/test_builtin.js index e256066..c6ea5bb 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -1,42 +1,116 @@ -"use strict"; +import * as os from "qjs:os"; +import { assert, assertThrows } from "./assert.js"; -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 assert_throws(expected_error, func) +// Keep this at the top; it tests source positions. +function test_exception_source_pos() { - var err = false; + var e; + try { - func(); - } catch(e) { - err = true; - if (!(e instanceof expected_error)) { - throw Error("unexpected exception type"); - } - } - if (!err) { - throw Error("expected exception"); + throw new Error(""); // line 10, column 19 + } catch(_e) { + e = _e; } + + assert(e.stack.includes("test_builtin.js:10:19")); } -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} +// 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"); +} -/*----------------*/ +// 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; + } + + Error.prepareStackTrace = undefined; + + 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()); +} + +// Keep this at the top; it tests source positions. +function test_exception_stack_size_limit() +{ + var e; + + Error.stackTraceLimit = 1; + Error.prepareStackTrace = (_, frames) => { + // Just return the array to check. + return frames; + }; + + try { + throw new Error(""); // line 67, column 19 + } catch(_e) { + e = _e; + } + + 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')); +} + +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) { @@ -57,7 +131,7 @@ function test_function() } var r, g; - + r = my_func.call(null, 1, 2); assert(r, 3, "call"); @@ -67,13 +141,13 @@ function test_function() r = (function () { return 1; }).apply(null, undefined); assert(r, 1); - assert_throws(TypeError, (function() { + assertThrows(TypeError, (function() { Reflect.apply((function () { return 1; }), null, undefined); })); - + r = new Function("a", "b", "return a + b;"); assert(r(2,3), 5, "function"); - + g = f.bind(1, 2); assert(g.length, 1); assert(g.name, "bound f"); @@ -103,7 +177,7 @@ function test() assert(a.z, 4, "get"); a.z = 5; assert(a.z_val, 5, "set"); - + a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; assert(a.z, 4, "get"); a.z = 5; @@ -132,6 +206,8 @@ 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() @@ -207,7 +283,7 @@ function test_string() assert(a.charAt(1), "b"); assert(a.charAt(-1), ""); assert(a.charAt(3), ""); - + a = "abcd"; assert(a.substring(1, 3), "bc", "substring"); a = String.fromCharCode(0x20ac); @@ -216,7 +292,7 @@ function test_string() assert(a, "\u20ac", "unicode"); assert(a, "\u{20ac}", "unicode"); assert("a", "\x61", "unicode"); - + a = "\u{10ffff}"; assert(a.length, 2, "unicode"); assert(a, "\u{dbff}\u{dfff}", "unicode"); @@ -311,6 +387,10 @@ function test_math() assert(Math.floor(a), 1); assert(Math.ceil(a), 2); assert(Math.imul(0x12345678, 123), -1088058456); + assert(Math.imul(0xB505, 0xB504), 2147441940); + assert(Math.imul(0xB505, 0xB505), -2147479015); + assert(Math.imul((-2)**31, (-2)**31), 0); + assert(Math.imul(2**31-1, 2**31-1), 1); assert(Math.fround(0.1), 0.10000000149011612); assert(Math.hypot() == 0); assert(Math.hypot(-2) == 2); @@ -327,6 +407,10 @@ function test_number() assert(+" 123 ", 123); assert(+"0b111", 7); assert(+"0o123", 83); + assert(parseFloat("2147483647"), 2147483647); + assert(parseFloat("2147483648"), 2147483648); + assert(parseFloat("-2147483647"), -2147483647); + assert(parseFloat("-2147483648"), -2147483648); assert(parseFloat("0x1234"), 0); assert(parseFloat("Infinity"), Infinity); assert(parseFloat("-Infinity"), -Infinity); @@ -336,12 +420,17 @@ function test_number() assert(Number.isNaN(Number("-"))); assert(Number.isNaN(Number("\x00a"))); + assert((1-2**-53).toString(12), "0.bbbbbbbbbbbbbba"); + assert((1000000000000000128).toString(), "1000000000000000100"); + assert((1000000000000000128).toFixed(0), "1000000000000000128"); assert((25).toExponential(0), "3e+1"); assert((-25).toExponential(0), "-3e+1"); assert((2.5).toPrecision(1), "3"); assert((-2.5).toPrecision(1), "-3"); assert((1.125).toFixed(2), "1.13"); assert((-1.125).toFixed(2), "-1.13"); + assert((0.5).toFixed(0), "1"); + assert((-0.5).toFixed(0), "-1"); } function test_eval2() @@ -358,6 +447,20 @@ 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() @@ -379,7 +482,7 @@ function test_eval() assert(eval("if (0) 2; else 3;"), 3); assert(f.call(1, "this"), 1); - + a = 2; assert(eval("a"), 2); @@ -399,7 +502,7 @@ function test_eval() function test_typed_array() { - var buffer, a, i, str; + var buffer, a, i, str, b; a = new Uint8Array(4); assert(a.length, 4); @@ -424,7 +527,7 @@ function test_typed_array() a[2] = 0.5; a[3] = 1233.5; assert(a.toString(), "0,2,0,255"); - + buffer = new ArrayBuffer(16); assert(buffer.byteLength, 16); a = new Uint32Array(buffer, 12, 1); @@ -434,9 +537,12 @@ function test_typed_array() a = new Uint16Array(buffer, 2); a[0] = -1; + a = new Float16Array(buffer, 8, 1); + a[0] = 1; + a = new Float32Array(buffer, 8, 1); a[0] = 1; - + a = new Uint8Array(buffer); str = a.toString(); @@ -452,6 +558,17 @@ 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"); } function test_json() @@ -481,26 +598,113 @@ function test_json() function test_date() { - var d = new Date(1506098258091), a, s; + // Date Time String format is YYYY-MM-DDTHH:mm:ss.sssZ + // accepted date formats are: YYYY, YYYY-MM and YYYY-MM-DD + // accepted time formats are: THH:mm, THH:mm:ss, THH:mm:ss.sss + // expanded years are represented with 6 digits prefixed by + or - + // -000000 is invalid. + // A string containing out-of-bounds or nonconforming elements + // is not a valid instance of this format. + // 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("2000"), 946684800000); + 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-01T00:00Z"), 946684800000); + assert(Date.parse("2000-01-01T00:00:00Z"), 946684800000); + assert(Date.parse("2000-01-01T00:00:00.1Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.10Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.100Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.1000Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00+00:00"), 946684800000); + //assert(Date.parse("2000-01-01T00:00:00+00:30"), 946686600000); + var d = new Date("2000T00:00"); // Jan 1st 2000, 0:00:00 local time + assert(typeof d === 'object' && d.toString() != 'Invalid Date'); + assert((new Date('Jan 1 2000')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00:00')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00:00 GMT+0100')).toISOString(), + '1999-12-31T23:00:00.000Z'); + assert((new Date('Jan 1 2000 00:00:00 GMT+0200')).toISOString(), + '1999-12-31T22:00:00.000Z'); + assert((new Date('Sat Jan 1 2000')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00:00')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0100')).toISOString(), + '1999-12-31T23:00:00.000Z'); + assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0200')).toISOString(), + '1999-12-31T22:00:00.000Z'); + + var d = new Date(1506098258091); assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); d.setUTCHours(18, 10, 11); assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); - a = Date.parse(d.toISOString()); + var a = Date.parse(d.toISOString()); assert((new Date(a)).toISOString(), d.toISOString()); - s = new Date("2020-01-01T01:01:01.1Z").toISOString(); - assert(s == "2020-01-01T01:01:01.100Z"); - s = new Date("2020-01-01T01:01:01.12Z").toISOString(); - assert(s == "2020-01-01T01:01:01.120Z"); - s = new Date("2020-01-01T01:01:01.123Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.1234Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.12345Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.1235Z").toISOString(); - assert(s == "2020-01-01T01:01:01.124Z"); - s = new Date("2020-01-01T01:01:01.9999Z").toISOString(); - assert(s == "2020-01-01T01:01:02.000Z"); + + assert((new Date("2020-01-01T01:01:01.123Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + /* implementation defined behavior */ + assert((new Date("2020-01-01T01:01:01.1Z")).toISOString(), + "2020-01-01T01:01:01.100Z"); + assert((new Date("2020-01-01T01:01:01.12Z")).toISOString(), + "2020-01-01T01:01:01.120Z"); + assert((new Date("2020-01-01T01:01:01.1234Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.12345Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.1235Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.9999Z")).toISOString(), + "2020-01-01T01:01:01.999Z"); + + assert(Date.UTC(2017), 1483228800000); + assert(Date.UTC(2017, 9), 1506816000000); + assert(Date.UTC(2017, 9, 22), 1508630400000); + assert(Date.UTC(2017, 9, 22, 18), 1508695200000); + assert(Date.UTC(2017, 9, 22, 18, 10), 1508695800000); + assert(Date.UTC(2017, 9, 22, 18, 10, 11), 1508695811000); + assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91), 1508695811091); + + assert(Date.UTC(NaN), NaN); + assert(Date.UTC(2017, NaN), NaN); + assert(Date.UTC(2017, 9, NaN), NaN); + assert(Date.UTC(2017, 9, 22, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, 10, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, 10, 11, NaN), NaN); + 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)) { + // 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'); + assert(Date.UTC(1970, 0, 213503982336, 0, 0, 0, -18446744073709552000), 34447360, + 'precision in MakeDate'); + } + //assert(Date.UTC(2017 - 1e9, 9 + 12e9), 1506816000000); // node fails this + assert(Date.UTC(2017, 9, 22 - 1e10, 18 + 24e10), 1508695200000); + 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() @@ -525,7 +729,7 @@ function test_regexp() a = /(\.(?!com|org)|\/)/.exec("ah.com"); assert(a, null); - + a = /(?=(a+))/.exec("baaabac"); assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); @@ -538,9 +742,25 @@ function test_regexp() assert(/{1a}/.toString(), "/{1a}/"); a = /a{1+/.exec("a{11"); - assert(a, ["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"); /* test zero length matches */ + a = /()*?a/.exec(","); + assert(a, null); a = /(?:(?=(abc)))a/.exec("abc"); assert(a, ["a", "abc"]); a = /(?:(?=(abc)))?a/.exec("abc"); @@ -549,6 +769,8 @@ 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"]); } function test_symbol() @@ -587,6 +809,16 @@ 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 = new Map(); tab = []; for(i = 0; i < n; i++) { @@ -602,7 +834,7 @@ function test_map() } i = 0; - a.forEach(function (v, o) { + a.forEach(function (v, o) { assert(o, tab[i++][0]); assert(a.has(o)); assert(a.delete(o)); @@ -614,10 +846,20 @@ function test_map() function test_weak_map() { - var a, i, n, tab, o, v, n2; + var a, e, 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 }; @@ -625,7 +867,7 @@ function test_weak_map() a.set(o, v); } o = null; - + n2 = n >> 1; for(i = 0; i < n2; i++) { a.delete(tab[i][0]); @@ -636,6 +878,22 @@ function test_weak_map() /* the WeakMap should be empty here */ } +function test_weak_set() +{ + 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"); + } +} + function test_generator() { function *f() { @@ -695,6 +953,111 @@ function test_generator() assert(v.value === 6 && v.done === true); } +function test_proxy_iter() +{ + 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"); +} + +/* CVE-2023-31922 */ +function test_proxy_is_array() +{ + 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; + } + } +} + +function test_finalization_registry() +{ + { + let expected = {}; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + queueMicrotask(() => { + assert(actual, expected); + }); + } + { + let expected = 42; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + queueMicrotask(() => { + assert(actual, expected); + }); + } +} + +function test_cur_pc() +{ + 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; }); +} + test(); test_function(); test_enum(); @@ -710,4 +1073,15 @@ test_regexp(); test_symbol(); test_map(); test_weak_map(); +test_weak_set(); test_generator(); +test_proxy_iter(); +test_proxy_is_array(); +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(); diff --git a/tests/test_closure.js b/tests/test_closure.js index aa1d17e..4d63879 100644 --- a/tests/test_closure.js +++ b/tests/test_closure.js @@ -1,3 +1,5 @@ +// 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; @@ -15,9 +17,6 @@ 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 = ""; @@ -54,7 +53,7 @@ function test_closure1() function f2() { var val = 1; - + function set(a) { val = a; } @@ -63,7 +62,7 @@ function test_closure1() } return { "set": set, "get": get }; } - + var obj = f2(); obj.set(10); var r; @@ -135,9 +134,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() { @@ -145,7 +144,7 @@ function test_arrow_function() } }; o2.__proto__ = o1; - assert(o2.f() === o2); + assert(o2.f(), o2); } function test_with() @@ -153,20 +152,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(); @@ -182,7 +181,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 = []; @@ -193,7 +192,7 @@ function test_eval_closure() f(); } for(let i = 0; i < 3; i++) { - assert(tab[i]() === i); + assert(tab[i](), i); } } diff --git a/tests/test_conv.c b/tests/test_conv.c new file mode 100644 index 0000000..db4e58d --- /dev/null +++ b/tests/test_conv.c @@ -0,0 +1,1755 @@ +/* + * Benchmark integer conversion variants + * + * Copyright (c) 2024 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 + +#ifdef _WIN32 +#include +#endif + +//#define USE_SINGLE_CASE 1 // special case single digit numbers +#define USE_SPECIAL_RADIX_10 1 // special case single digit numbers +#define USE_SINGLE_CASE_FAST 1 // special case single digit numbers + +#define TEST_SNPRINTF 1 // use snprintf for specific bases (for reference) +#define TEST_NAIVE 1 // naive digit loop and copy loops +#define TEST_REVERSE 1 // naive digit loop and reverse digit string +#define TEST_DIGIT_PAIRS 1 // generate 2 decimal digits at a time +#define TEST_DIGIT_1PASS 1 // generate left to right decimal digits +#define TEST_LENGTH_LOOP 1 // compute length before digit loop using loop +#define TEST_LENGTH_EXPR 1 // compute length before digit loop using expression +#define TEST_SHIFTBUF 1 // generate up to 7 byte chunks in a register +#define TEST_BLOCKMOV 1 // move all digits together +#define TEST_DIV_TABLE 1 // use multiplier table instead of radix divisions +#define TEST_DISPATCH 1 // use dispatch table to optimal 64-bit radix converters + +#if (defined(__GNUC__) && !defined(__clang__)) +#undef TEST_NAIVE // 32-bit gcc overoptimizes this code +#undef TEST_DIGIT_PAIRS +#endif + +/* definitions from cutils.h */ + +#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define minimum_length(n) static n +#else +#define minimum_length(n) n +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +# define likely(x) (x) +#else +# define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef countof +#define countof(a) (sizeof(a) / sizeof((a)[0])) +#endif + +static inline uint8_t is_be(void) { + union { + uint16_t a; + uint8_t b; + } u = { 0x100 }; + return u.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 +} +// prototypes for final functions +extern char const digits36[36]; +size_t u32toa(char buf[minimum_length(11)], uint32_t n); +size_t i32toa(char buf[minimum_length(12)], int32_t n); +size_t u64toa(char buf[minimum_length(21)], uint64_t n); +size_t i64toa(char buf[minimum_length(22)], int64_t n); +size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base); +size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned base); +size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base); +size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned base); + +/*---- integer to string conversions ----*/ + +/* All conversion functions: + - require a destination array `buf` of sufficient length + - write the string representation at the beginning of `buf` + - null terminate the string + - return the string length + */ + +/* 2 <= base <= 36 */ +char const digits36[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' +}; + +/*---- variants ----*/ + +#define define_i32toa(v) \ +size_t i32toa_##v(char buf[minimum_length(12)], int32_t n) \ +{ \ + if (likely(n >= 0)) \ + return u32toa_##v(buf, n); \ + buf[0] = '-'; \ + return 1 + u32toa_##v(buf + 1, -(uint32_t)n); \ +} + +#define define_i64toa(v) \ +size_t i64toa_##v(char buf[minimum_length(22)], int64_t n) \ +{ \ + if (likely(n >= 0)) \ + return u64toa_##v(buf, n); \ + buf[0] = '-'; \ + return 1 + u64toa_##v(buf + 1, -(uint64_t)n); \ +} + +#ifdef TEST_SHIFTBUF + +#define gen_digit(buf, c) if (is_be()) \ + buf = (buf >> 8) | ((uint64_t)(c) << ((sizeof(buf) - 1) * 8)); \ + else \ + buf = (buf << 8) | (c) + +size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n) +{ + size_t len = 1; + uint64_t buf = 0; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + gen_digit(buf, '0' + quo); + len++; + } + gen_digit(buf, '0' + n); + memcpy(dest, &buf, sizeof buf); + return len; +} + +size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len) +{ + size_t i; + dest += len; + dest[7] = '\0'; + for (i = 7; i-- > 1;) { + uint32_t quo = n % 10; + n /= 10; + dest[i] = (char)('0' + quo); + } + dest[i] = (char)('0' + n); + return len + 7; +} + +size_t u32toa_shift(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE_FAST /* 10% */ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif +#define TEN_POW_7 10000000 + if (n >= TEN_POW_7) { + uint32_t quo = n / TEN_POW_7; + n %= TEN_POW_7; + size_t len = u7toa_shift(buf, quo); + return u07toa_shift(buf, n, len); + } + return u7toa_shift(buf, n); +} + +size_t u64toa_shift(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_shift(buf, n); + + size_t len; + if (n >= TEN_POW_7) { + uint64_t n1 = n / TEN_POW_7; + n %= TEN_POW_7; + if (n1 >= TEN_POW_7) { + uint32_t quo = n1 / TEN_POW_7; + n1 %= TEN_POW_7; + len = u7toa_shift(buf, quo); + len = u07toa_shift(buf, n1, len); + } else { + len = u7toa_shift(buf, n1); + } + return u07toa_shift(buf, n, len); + } + return u7toa_shift(buf, n); +} + +define_i32toa(shift) +define_i64toa(shift) + +#endif /* TEST_SHIFTBUF */ + +#if defined(TEST_DIGIT_PAIRS) || defined(TEST_DIGIT_1PASS) +static char const digits100[] = + "00010203040506070809" + "10111213141516171819" + "20212223242526272829" + "30313233343536373839" + "40414243444546474849" + "50515253545556575859" + "60616263646566676869" + "70717273747576777879" + "80818283848586878889" + "90919293949596979899"; +#endif + +#ifdef TEST_DIGIT_PAIRS +size_t u32toa_pair(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif + char *p = buf; + char *q = buf + 10; + while (n >= 100) { + uint32_t quo = n % 100; + n /= 100; + *--q = digits100[2 * quo + 1]; + *--q = digits100[2 * quo]; + } + *p = digits100[2 * n]; + p += *p != '0'; + *p++ = digits100[2 * n + 1]; + while (q < buf + 10) { + *p++ = *q++; + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +size_t u64toa_pair(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_pair(buf, n); + + char *p = buf; + char *q = buf + 20; + while (n >= 100) { + uint32_t quo = n % 100; + n /= 100; + *--q = digits100[2 * quo + 1]; + *--q = digits100[2 * quo]; + } + *p = digits100[2 * n]; + p += *p != '0'; + *p++ = digits100[2 * n + 1]; + while (q < buf + 20) { + *p++ = *q++; + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +define_i32toa(pair) +define_i64toa(pair) + +#endif /* TEST_DIGIT_PAIRS */ + +#if TEST_DIGIT_1PASS +static char *u4toa(char p[minimum_length(4)], uint32_t n) +{ + const char *digits = digits100; + if (n >= 100) { + uint32_t n1 = n / 100; + n -= n1 * 100; + *p = digits[2 * n1]; + p += digits[2 * n1] != '0'; + *p++ = digits[2 * n1 + 1]; + *p++ = digits[2 * n]; + *p++ = digits[2 * n + 1]; + return p; + } else { + *p = digits[2 * n]; + p += digits[2 * n] != '0'; + *p++ = digits[2 * n + 1]; + return p; + } +} + +static char *u04toa(char p[minimum_length(4)], uint32_t n) +{ + const char *digits = digits100; + uint32_t n1 = n / 100; + n -= n1 * 100; + *p++ = digits[2 * n1]; + *p++ = digits[2 * n1 + 1]; + *p++ = digits[2 * n]; + *p++ = digits[2 * n + 1]; + return p; +} + +static char *u8toa(char p[minimum_length(8)], uint32_t n) +{ + if (n >= 10000) { + uint32_t n1 = n / 10000; + n -= n1 * 10000; + p = u4toa(p, n1); + return u04toa(p, n); + } + return u4toa(p, n); +} + +static char *u08toa(char p[minimum_length(8)], uint32_t n) +{ + uint32_t n1 = n / 10000; + n -= n1 * 10000; + p = u04toa(p, n1); + return u04toa(p, n); +} + +size_t u32toa_pair_1pass(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE /* 6% */ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif + char *p = buf; + /* division by known base uses multiplication */ + if (n >= 100000000) { + uint32_t n1 = n / 100000000; + n -= n1 * 100000000; + /* 1 <= n1 <= 42 */ + *p = digits100[2 * n1]; + p += *p != '0'; + *p++ = digits100[2 * n1 + 1]; + p = u08toa(p, n); + } else { + p = u8toa(p, n); + } + *p = '\0'; + return p - buf; +} + +size_t u64toa_pair_1pass(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_pair_1pass(buf, n); + + char *p = buf; + + /* division by known base uses multiplication */ + if (n >= 100000000) { + uint64_t n1 = n / 100000000; + n -= n1 * 100000000; + if (n1 >= 100000000) { + uint32_t n2 = n1 / 100000000; + n1 -= n2 * 100000000; + // 1 <= n2 <= 1844 + p = u4toa(p, n2); + p = u08toa(p, n1); + p = u08toa(p, n); + } else { + p = u8toa(p, n1); + p = u08toa(p, n); + } + } else { + p = u8toa(p, n); + } + *p = '\0'; + return p - buf; +} + +define_i32toa(pair_1pass) +define_i64toa(pair_1pass) + +#endif /* TEST_DIGIT_1PASS */ + +#ifdef TEST_SNPRINTF +size_t u32toa_snprintf(char buf[minimum_length(11)], uint32_t n) +{ + return snprintf(buf, 11, "%"PRIu32, n); +} + +size_t i32toa_snprintf(char buf[minimum_length(12)], int32_t n) +{ + return snprintf(buf, 12, "%"PRId32, n); +} + +size_t u64toa_snprintf(char buf[minimum_length(21)], uint64_t n) +{ + return snprintf(buf, 21, "%"PRIu64, n); +} + +size_t i64toa_snprintf(char buf[minimum_length(22)], int64_t n) +{ + return snprintf(buf, 22, "%"PRId64, n); +} +#endif /* TEST_SNPRINTF */ + +#ifdef TEST_NAIVE +size_t u32toa_naive(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif + char *p = buf; + char *q = buf + 10; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *--q = (char)('0' + quo); + } + *p++ = (char)('0' + n); + while (q < buf + 10) + *p++ = *q++; + *p = '\0'; + return p - buf; +} + +size_t u64toa_naive(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_naive(buf, n); + + char *p = buf; + char *q = buf + 20; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *--q = (char)('0' + quo); + } + *p++ = (char)('0' + n); + while (q < buf + 20) + *p++ = *q++; + *p = '\0'; + return p - buf; +} + +define_i32toa(naive) +define_i64toa(naive) + +#endif /* TEST_NAIVE */ + +#ifdef TEST_LENGTH_EXPR +size_t u32toa_length_expr(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE_FAST /* 8% */ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } + size_t len = (2 + (n > 99) + (n > 999) + + (n > 9999) + (n > 99999) + (n > 999999) + + (n > 9999999) + (n > 99999999) + (n > 999999999)); +#else + size_t len = (1 + (n > 9) + (n > 99) + (n > 999) + + (n > 9999) + (n > 99999) + (n > 999999) + + (n > 9999999) + (n > 99999999) + (n > 999999999)); +#endif + char *end = buf + len; + *end-- = '\0'; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *end-- = (char)('0' + quo); + } + *end = (char)('0' + n); + return len; +} + +size_t u64toa_length_expr(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_length_expr(buf, n); +#if 0 + size_t len = 10 + ((n >= 10000000000ULL) + + (n >= 100000000000ULL) + + (n >= 1000000000000ULL) + + (n >= 10000000000000ULL) + + (n >= 100000000000000ULL) + + (n >= 1000000000000000ULL) + + (n >= 10000000000000000ULL) + + (n >= 100000000000000000ULL) + + (n >= 1000000000000000000ULL) + + (n >= 10000000000000000000ULL)); + char *end = buf + len; + *end-- = '\0'; +#else + uint64_t n10 = 1000000000; + uint32_t last = n % 10; + n /= 10; + size_t len = 10; + while (n >= n10) { + n10 *= 10; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = (char)('0' + last); +#endif + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *end-- = (char)('0' + quo); + } + *end = (char)('0' + n); + return len; +} + +define_i32toa(length_expr) +define_i64toa(length_expr) + +#endif /* TEST_LENGTH_EXPR */ + +#ifdef TEST_LENGTH_LOOP +size_t u32toa_length_loop(char buf[minimum_length(11)], uint32_t n) +{ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } + uint32_t last = n % 10; + n /= 10; + uint32_t n10 = 10; + size_t len = 2; + while (n >= n10) { + n10 *= 10; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = (char)('0' + last); + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *end-- = (char)('0' + quo); + } + *end = (char)('0' + n); + return len; +} + +size_t u64toa_length_loop(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_length_loop(buf, n); + + uint32_t last = n % 10; + n /= 10; + uint64_t n10 = 1000000000; + size_t len = 10; + while (n >= n10) { + n10 *= 10; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = (char)('0' + last); + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *end-- = (char)('0' + quo); + } + *end = (char)('0' + n); + return len; +} + +define_i32toa(length_loop) +define_i64toa(length_loop) + +#endif /* TEST_LENGTH_LOOP */ + +#if defined(TEST_REVERSE) || defined(TEST_DISPATCH) +size_t u32toa_reverse(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif + char *end; + size_t len = 0; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + buf[len++] = (char)('0' + quo); + } + buf[len++] = (char)('0' + n); + buf[len] = '\0'; + for (end = buf + len - 1; buf < end;) { + char c = *buf; + *buf++ = *end; + *end-- = c; + } + return len; +} + +size_t u64toa_reverse(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_reverse(buf, n); + + char *end; + size_t len = 0; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + buf[len++] = (char)('0' + quo); + } + buf[len++] = (char)('0' + n); + buf[len] = '\0'; + for (end = buf + len - 1; buf < end;) { + char c = *buf; + *buf++ = *end; + *end-- = c; + } + return len; +} + +define_i32toa(reverse) +define_i64toa(reverse) + +#endif /* TEST_REVERSE */ + +#ifdef TEST_BLOCKMOV +size_t u32toa_blockmov(char buf[minimum_length(11)], uint32_t n) +{ +#ifdef USE_SINGLE_CASE_FAST /* 6% */ + if (n < 10) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } +#endif + char buf1[10+10]; + char *p = buf; + char *q = buf1 + 10; + *q = '\0'; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *--q = (char)('0' + quo); + } + *p++ = (char)('0' + n); + memcpy(p, q, 10); + return (buf1 + 10) - q + 1; +} + +size_t u64toa_blockmov(char buf[minimum_length(21)], uint64_t n) +{ + if (likely(n < 0x100000000)) + return u32toa_blockmov(buf, n); + + char buf1[20+20]; + char *p = buf; + char *q = buf1 + 20; + *q = '\0'; + while (n >= 10) { + uint32_t quo = n % 10; + n /= 10; + *--q = (char)('0' + quo); + } + *p++ = (char)('0' + n); + memcpy(p, q, 20); + return (buf1 + 20) - q + 1; +} + +define_i32toa(blockmov) +define_i64toa(blockmov) + +#endif /* TEST_BLOCKMOV */ + +/*---- radix conversion variants ----*/ + +#define define_i32toa_radix(v) \ +size_t i32toa_radix_##v(char buf[minimum_length(34)], int32_t n, unsigned base) \ +{ \ + if (likely(n >= 0)) \ + return u32toa_radix_##v(buf, n, base); \ + buf[0] = '-'; \ + return 1 + u32toa_radix_##v(buf + 1, -(uint32_t)n, base); \ +} + +#define define_i64toa_radix(v) \ +size_t i64toa_radix_##v(char buf[minimum_length(66)], int64_t n, unsigned base) \ +{ \ + if (likely(n >= 0)) \ + return u64toa_radix_##v(buf, n, base); \ + buf[0] = '-'; \ + return 1 + u64toa_radix_##v(buf + 1, -(uint64_t)n, base); \ +} + +#ifdef TEST_NAIVE +size_t u32toa_radix_naive(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u32toa_naive(buf, n); +#endif +#ifdef USE_SINGLE_CASE + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } +#endif + char buf1[32]; + char *q = buf1 + 32; + char *p = buf; + while (n >= base) { + size_t digit = n % base; + n /= base; + *--q = digits36[digit]; + } + *--q = digits36[n]; + while (q < buf1 + 32) { + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +size_t u64toa_radix_naive(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (likely(n < 0x100000000)) + return u32toa_radix_naive(buf, n, base); +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u64toa_naive(buf, n); +#endif + char buf1[64]; + char *q = buf1 + 64; + char *p = buf; + while (n >= base) { + size_t digit = n % base; + n /= base; + *--q = digits36[digit]; + } + *--q = digits36[n]; + while (q < buf1 + 64) { + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +define_i32toa_radix(naive) +define_i64toa_radix(naive) + +#endif // TEST_NAIVE + +#if defined(TEST_REVERSE) || defined(TEST_DISPATCH) +size_t u32toa_radix_reverse(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u32toa_reverse(buf, n); +#endif +#ifdef USE_SINGLE_CASE + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } +#endif + char *end; + size_t len = 0; + while (n >= base) { + uint32_t quo = n % base; + n /= base; + buf[len++] = digits36[quo]; + } + buf[len++] = digits36[n]; + buf[len] = '\0'; + for (end = buf + len - 1; buf < end;) { + char c = *buf; + *buf++ = *end; + *end-- = c; + } + return len; +} + +size_t u64toa_radix_reverse(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (likely(n < 0x100000000)) + return u32toa_radix_reverse(buf, n, base); +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u64toa_reverse(buf, n); +#endif + char *end; + size_t len = 0; + while (n >= base) { + uint32_t quo = n % base; + n /= base; + buf[len++] = digits36[quo]; + } + buf[len++] = digits36[n]; + buf[len] = '\0'; + for (end = buf + len - 1; buf < end;) { + char c = *buf; + *buf++ = *end; + *end-- = c; + } + return len; +} + +define_i32toa_radix(reverse) +define_i64toa_radix(reverse) + +#endif // TEST_REVERSE + +#ifdef TEST_LENGTH_LOOP + +static uint8_t const radix_shift[64] = { + 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 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, +}; + +size_t u32toa_radix_length(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ + int shift; + +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u32toa_length_loop(buf, n); +#endif + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } + shift = radix_shift[base & 63]; + if (shift) { + uint32_t mask = (1 << shift) - 1; + size_t len = (32 - clz32(n) + shift - 1) / shift; + size_t last = n & mask; + char *end = buf + len; + n >>= shift; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n & mask; + n >>= shift; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } else { + size_t len = 2; + size_t last = n % base; + n /= base; + uint32_t nbase = base; + while (n >= nbase) { + nbase *= base; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n % base; + n /= base; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } +} + +size_t u64toa_radix_length(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + int shift; + +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u64toa_length_loop(buf, n); +#endif + shift = radix_shift[base & 63]; + if (shift) { + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } + uint64_t mask = (1 << shift) - 1; + size_t len = (64 - clz64(n) + shift - 1) / shift; + size_t last = n & mask; + char *end = buf + len; + n >>= shift; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n & mask; + n >>= shift; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } else { + if (likely(n < 0x100000000)) + return u32toa_radix_length(buf, n, base); + size_t last = n % base; + n /= base; + uint64_t nbase = base; + size_t len = 2; + while (n >= nbase) { + nbase *= base; + len++; + } + char *end = buf + len; + *end-- = '\0'; + *end-- = digits36[last]; + while (n >= base) { + size_t quo = n % base; + n /= base; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; + } +} + +define_i32toa_radix(length) +define_i64toa_radix(length) + +#endif // TEST_LENGTH_LOOP + +#ifdef TEST_DIV_TABLE +static struct { + uint32_t chunk : 27; + uint32_t ndig : 5; + uint32_t mul; +} const div_table32[37] = { + { 0, 0, 0 }, // 0 + { 1, 1, 1 }, // 1 + { 67108864, 26, 2147483648 }, // 2 + { 129140163, 17, 1431655776 }, // 3 + { 67108864, 13, 1073741824 }, // 4 + { 48828125, 11, 858993464 }, // 5 + { 60466176, 10, 715827888 }, // 6 + { 40353607, 9, 613566760 }, // 7 + { 16777216, 8, 536870912 }, // 8 + { 43046721, 8, 477218592 }, // 9 + { 100000000, 8, 429496732 }, // 10 + { 19487171, 7, 390451574 }, // 11 + { 35831808, 7, 357913944 }, // 12 + { 62748517, 7, 330382100 }, // 13 + { 105413504, 7, 306783380 }, // 14 + { 11390625, 6, 286331154 }, // 15 + { 16777216, 6, 268435456 }, // 16 + { 24137569, 6, 252645136 }, // 17 + { 34012224, 6, 238609296 }, // 18 + { 47045881, 6, 226050912 }, // 19 + { 64000000, 6, 214748366 }, // 20 + { 85766121, 6, 204522253 }, // 21 + { 113379904, 6, 195225787 }, // 22 + { 6436343, 5, 186737709 }, // 23 + { 7962624, 5, 178956972 }, // 24 + { 9765625, 5, 171798692 }, // 25 + { 11881376, 5, 165191050 }, // 26 + { 14348907, 5, 159072864 }, // 27 + { 17210368, 5, 153391690 }, // 28 + { 20511149, 5, 148102321 }, // 29 + { 24300000, 5, 143165577 }, // 30 + { 28629151, 5, 138547333 }, // 31 + { 33554432, 5, 134217728 }, // 32 + { 39135393, 5, 130150525 }, // 33 + { 45435424, 5, 126322568 }, // 34 + { 52521875, 5, 122713352 }, // 35 + { 60466176, 5, 119304648 }, // 36 +}; + +size_t u32toa_radix_div_table(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u32toa_shift(buf, n); +#endif +#ifdef USE_SINGLE_CASE + if (n < base) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } +#endif + char buf1[32]; + char *q = buf1 + 32; + char *p = buf; + uint32_t chunk = div_table32[base].chunk; + uint32_t ndig = div_table32[base].ndig; + uint32_t mul = div_table32[base].mul; + while (n >= chunk) { + uint32_t quo = n / chunk; + uint32_t n1 = n - quo * chunk; + n = quo; + for (uint32_t i = ndig; i-- > 0;) { + uint32_t quo1 = ((uint64_t)n1 * mul) >> 32; + size_t digit = n1 - quo1 * base; + n1 = quo1; + *--q = digits36[digit]; + } + } + while (n >= base) { + uint32_t quo = ((uint64_t)n * mul) >> 32; + size_t digit = n - quo * base; + n = quo; + *--q = digits36[digit]; + } + *--q = digits36[n]; + while (q < buf1 + 32) { + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +size_t u64toa_radix_div_table(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (likely(n < 0x100000000)) + return u32toa_radix_div_table(buf, n, base); +#ifdef USE_SPECIAL_RADIX_10 + if (likely(base == 10)) + return u64toa_shift(buf, n); +#endif + char buf1[64]; + char *q = buf1 + 64; + char *p = buf; + uint32_t chunk = div_table32[base].chunk; + uint32_t ndig = div_table32[base].ndig; + uint32_t mul = div_table32[base].mul; + while (n >= chunk) { + uint64_t quo = n / chunk; + uint32_t n1 = n - quo * chunk; + n = quo; + for (uint32_t i = ndig; i-- > 0;) { + uint32_t quo1 = ((uint64_t)n1 * mul) >> 32; + size_t digit = n1 - quo1 * base; + n1 = quo1; + *--q = digits36[digit]; + } + } + uint32_t n1 = n; + while (n1 >= base) { + uint32_t quo1 = ((uint64_t)n1 * mul) >> 32; + size_t digit = n1 - quo1 * base; + n1 = quo1; + *--q = digits36[digit]; + } + *--q = digits36[n1]; + while (q < buf1 + 64) { + *p++ = *q++; + } + *p = '\0'; + return p - buf; +} + +define_i32toa_radix(div_table) +define_i64toa_radix(div_table) + +#endif // TEST_DIV_TABLE + +#ifdef TEST_DISPATCH + +static size_t u64toa_radix_d10(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + return u64toa_shift(buf, n); +} + +static size_t u64toa_radix_d2(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (n < 2) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } + size_t len = (64 - clz64(n)); + char *end = buf + len; + *end-- = '\0'; + while (n >= 2) { + uint32_t quo = n & 1; + n >>= 1; + *end-- = (char)('0' + quo); + } + *end-- = (char)('0' + n); + return len; +} + +static size_t u64toa_radix_d8(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (n < 8) { + buf[0] = (char)('0' + n); + buf[1] = '\0'; + return 1; + } + size_t len = (64 - clz64(n) + 2) / 3; + char *end = buf + len; + *end-- = '\0'; + while (n >= 8) { + uint32_t quo = n & 7; + n >>= 3; + *end-- = (char)('0' + quo); + } + *end-- = (char)('0' + n); + return len; +} + +static size_t u64toa_radix_d16(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + if (n < 16) { + buf[0] = digits36[n]; + buf[1] = '\0'; + return 1; + } + size_t len = (64 - clz64(n) + 3) / 4; + char *end = buf + len; + *end-- = '\0'; + while (n >= 16) { + uint32_t quo = n & 15; + n >>= 4; + *end-- = digits36[quo]; + } + *end = digits36[n]; + return len; +} + +#define u64toa_reverse_base(radix) \ +static size_t u64toa_reverse_##radix(char buf[minimum_length(65)], uint64_t n, unsigned base) \ +{ \ + char *end; \ + size_t len = 0; \ + while (n >= radix) { \ + size_t quo = n % radix; \ + n /= radix; \ + if (radix > 9) buf[len++] = digits36[quo]; \ + else buf[len++] = (char)('0' + quo); \ + } \ + if (radix > 9) buf[len++] = digits36[n]; \ + else buf[len++] = (char)('0' + n); \ + buf[len] = '\0'; \ + for (end = buf + len - 1; buf < end;) { \ + char c = *buf; \ + *buf++ = *end; \ + *end-- = c; \ + } \ + return len; \ +} + +u64toa_reverse_base(3) +u64toa_reverse_base(4) +u64toa_reverse_base(5) +u64toa_reverse_base(6) +u64toa_reverse_base(7) +u64toa_reverse_base(9) +u64toa_reverse_base(11) +u64toa_reverse_base(12) +u64toa_reverse_base(13) +u64toa_reverse_base(14) +u64toa_reverse_base(15) +u64toa_reverse_base(17) +u64toa_reverse_base(18) +u64toa_reverse_base(19) +u64toa_reverse_base(20) +u64toa_reverse_base(21) +u64toa_reverse_base(22) +u64toa_reverse_base(23) +u64toa_reverse_base(24) +u64toa_reverse_base(25) +u64toa_reverse_base(26) +u64toa_reverse_base(27) +u64toa_reverse_base(28) +u64toa_reverse_base(29) +u64toa_reverse_base(30) +u64toa_reverse_base(31) +u64toa_reverse_base(32) +u64toa_reverse_base(33) +u64toa_reverse_base(34) +u64toa_reverse_base(35) +u64toa_reverse_base(36) + +typedef size_t (*u64toa_radix_func)(char buf[minimum_length(65)], uint64_t n, unsigned base); +static const u64toa_radix_func u64toa_radix_table[37] = { +#if 0 + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_d2, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_d8, u64toa_radix_reverse, u64toa_radix_d10, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_d16, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_reverse, + u64toa_radix_reverse, +#else + u64toa_radix_reverse, u64toa_radix_reverse, u64toa_radix_d2, u64toa_reverse_3, + u64toa_reverse_4, u64toa_reverse_5, u64toa_reverse_6, u64toa_reverse_7, + u64toa_radix_d8, u64toa_reverse_9, u64toa_radix_d10, u64toa_reverse_11, + u64toa_reverse_12, u64toa_reverse_13, u64toa_reverse_14, u64toa_reverse_15, + u64toa_radix_d16, u64toa_reverse_17, u64toa_reverse_18, u64toa_reverse_19, + u64toa_reverse_20, u64toa_reverse_21, u64toa_reverse_22, u64toa_reverse_23, + u64toa_reverse_24, u64toa_reverse_25, u64toa_reverse_26, u64toa_reverse_27, + u64toa_reverse_28, u64toa_reverse_29, u64toa_reverse_30, u64toa_reverse_31, + u64toa_reverse_32, u64toa_reverse_33, u64toa_reverse_34, u64toa_reverse_35, + u64toa_reverse_36, +#endif +}; + +size_t u32toa_radix_dispatch(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ + return u64toa_radix_table[base % 37](buf, n, base); +} + +size_t u64toa_radix_dispatch(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + return u64toa_radix_table[base % 37](buf, n, base); +} + +define_i32toa_radix(dispatch) +define_i64toa_radix(dispatch) + +#endif // TEST_DISPATCH + +#ifdef TEST_SNPRINTF +size_t u32toa_radix_snprintf(char buf[minimum_length(33)], uint32_t n, unsigned base) +{ + switch (base) { +#ifdef PRIb32 + case 2: return snprintf(buf, 33, "%"PRIb32, n); +#endif + case 8: return snprintf(buf, 33, "%"PRIo32, n); + case 10: return snprintf(buf, 33, "%"PRIu32, n); + case 16: return snprintf(buf, 33, "%"PRIx32, n); +#ifdef TEST_NAIVE + default: return u32toa_radix_naive(buf, n, base); +#else + default: return u32toa_radix_reverse(buf, n, base); +#endif + } +} + +size_t u64toa_radix_snprintf(char buf[minimum_length(65)], uint64_t n, unsigned base) +{ + switch (base) { +#ifdef PRIb64 + case 2: return snprintf(buf, 65, "%"PRIb64, n); +#endif + case 8: return snprintf(buf, 65, "%"PRIo64, n); + case 10: return snprintf(buf, 65, "%"PRIu64, n); + case 16: return snprintf(buf, 65, "%"PRIx64, n); +#ifdef TEST_NAIVE + default: return u64toa_radix_naive(buf, n, base); +#else + default: return u64toa_radix_reverse(buf, n, base); +#endif + } +} + +define_i32toa_radix(snprintf) +define_i64toa_radix(snprintf) + +#endif // TEST_SNPRINTF + +/*---- Benchmarking framework ----*/ + +/* Benchmark various alternatives and bases: + - u32toa(), u64toa(), i32toa(), i64toa() + - u32toa_radix(), u64toa_radix(), i32toa_radix(), i64toa_radix() + - different implementations: naive, ... + - various sets of values + */ + +struct { + const char *name; + int enabled; + size_t (*u32toa)(char buf[minimum_length(11)], uint32_t n); + size_t (*i32toa)(char buf[minimum_length(12)], int32_t n); + size_t (*u64toa)(char buf[minimum_length(21)], uint64_t n); + size_t (*i64toa)(char buf[minimum_length(22)], int64_t n); +} impl[] = +{ +#define TESTCASE(v) { #v, 2, u32toa_##v, i32toa_##v, u64toa_##v, i64toa_##v } +#ifdef TEST_SNPRINTF + TESTCASE(snprintf), +#endif +#ifdef TEST_NAIVE + TESTCASE(naive), +#endif +#ifdef TEST_BLOCKMOV + TESTCASE(blockmov), +#endif +#ifdef TEST_REVERSE + TESTCASE(reverse), +#endif +#ifdef TEST_LENGTH_EXPR + TESTCASE(length_expr), +#endif +#ifdef TEST_LENGTH_LOOP + TESTCASE(length_loop), +#endif +#ifdef TEST_SHIFTBUF + TESTCASE(shift), +#endif +#ifdef TEST_DIGIT_PAIRS + TESTCASE(pair), +#endif +#ifdef TEST_DIGIT_1PASS + TESTCASE(pair_1pass), +#endif +#undef TESTCASE +}; + +struct { + const char *name; + int enabled; + size_t (*u32toa_radix)(char buf[minimum_length(33)], uint32_t n, unsigned base); + size_t (*i32toa_radix)(char buf[minimum_length(34)], int32_t n, unsigned base); + size_t (*u64toa_radix)(char buf[minimum_length(65)], uint64_t n, unsigned base); + size_t (*i64toa_radix)(char buf[minimum_length(66)], int64_t n, unsigned base); +} impl1[] = +{ +#define TESTCASE(v) { #v, 2, u32toa_radix_##v, i32toa_radix_##v, u64toa_radix_##v, i64toa_radix_##v } +#ifdef TEST_SNPRINTF + TESTCASE(snprintf), +#endif +#ifdef TEST_NAIVE + TESTCASE(naive), +#endif +#ifdef TEST_REVERSE + TESTCASE(reverse), +#endif +#ifdef TEST_DIV_TABLE + TESTCASE(div_table), +#endif +#ifdef TEST_LENGTH_LOOP + TESTCASE(length), +#endif +#ifdef TEST_DISPATCH + TESTCASE(dispatch), +#endif +#undef TESTCASE +}; + +static clock_t start_timer(void) { + clock_t t0, t; + t0 = clock(); + // wait for next transition + while ((t = clock()) == t0) + continue; + return t; +} + +static clock_t stop_timer(clock_t t) { + return clock() - t; +} + +#define TIME(time, iter, s, w, e) { \ + t = start_timer(); \ + uint64_t r0 = 0; \ + for (int nn = 0; nn < iter; nn++) { \ + r0 = r0 * 1103515245 + 12345; \ + uint##w##_t mask, r = r0; \ + for (int kk = 0; kk < 64; kk += w) { \ + for (mask = 1; mask != 0; ) { \ + mask += mask; \ + if (s) { \ + int##w##_t x = (r & (mask - 1)) - (r & mask); \ + e; \ + } else { \ + uint##w##_t x = r & (mask - 1); \ + e; \ + } \ + } \ + r ^= (r >> 1); \ + } \ + } \ + t = stop_timer(t); \ + if (time == 0 || time > t) \ + time = t; \ + } + +#define CHECK(tab, iter, s, w, e, check) { \ + uint64_t r0 = 0; \ + for (int nn = 0; nn < iter; nn++) { \ + r0 = r0 * 1103515245 + 12345; \ + uint##w##_t mask, r = r0; \ + for (int kk = 0; kk < 64; kk += w) { \ + for (mask = 1; mask != 0; ) { \ + mask += mask; \ + if (s) { \ + int##w##_t x = (r & (mask - 1)) - (r & mask); \ + size_t len = tab.e; \ + errno = 0; \ + int64_t y = check; \ + if (errno || x != y || len != strlen(buf)) { \ + printf("error: %.*s_%s(%lld) base=%d -> %s -> %lld (errno=%d)\n", \ + (int)strcspn(#e, "("), #e, tab.name, \ + (long long)x, base, buf, (long long)y, errno); \ + if (nerrors > 20) exit(1); \ + } \ + } else { \ + uint##w##_t x = r & (mask - 1); \ + size_t len = tab.e; \ + errno = 0; \ + uint64_t y = check; \ + if (errno || x != y || len != strlen(buf)) { \ + printf("error: %.*s_%s(%llu) base=%d -> %s -> %llu (errno=%d)\n", \ + (int)strcspn(#e, "("), #e, tab.name, \ + (unsigned long long)x, base, buf, (unsigned long long)y, errno); \ + if (nerrors > 20) exit(1); \ + } \ + } \ + } \ + r ^= (r >> 1); \ + } \ + } \ + } + +void show_usage(void) { + printf("usage: test_conv [options] [bases] [filters]\n" + " options:\n" + " -h --help output this help\n" + " -t --terse only output average stats\n" + " -v --verbose output stats for all tested bases\n" + " bases\n" + " bases can be specified individually, as ranges or enumerations\n" + " supported bases are 2-36\n" + " examples: 10 2,8,16 2-10,16\n" + " filters are words that must be contained in variant names\n" + " examples: naive pri len rev\n" + " variants:\n" +#ifdef TEST_SNPRINTF + " snprintf use snprintf for supported bases for reference\n" +#endif +#ifdef TEST_NAIVE + " naive naive digit loop and copy loops\n" +#endif +#ifdef TEST_BLOCKMOV + " blockmov same but move all digits together\n" +#endif +#ifdef TEST_REVERSE + " reverse naive digit loop and reverse digit string\n" +#endif +#ifdef TEST_LENGTH_LOOP + " length_loop compute length before digit loop using loop\n" +#endif +#ifdef TEST_LENGTH_EXPR + " length_expr compute length before digit loop using expression\n" +#endif +#ifdef TEST_SHIFTBUF + " shift generate up to 7 digit chunks in a register\n" +#endif +#ifdef TEST_DIGIT_PAIRS + " pair generate 2 decimal digits at a time\n" +#endif +#ifdef TEST_DIGIT_1PASS + " pair_1pass same but as a single left to right pass\n" +#endif +#ifdef TEST_DIV_TABLE + " div_table use multiplier table instead of radix divisions\n" +#endif +#ifdef TEST_DISPATCH + " dispatch use dispatch table to optimal 64-bit radix converters\n" +#endif + ); +} + +int main(int argc, char *argv[]) { + clock_t t; + clock_t times[countof(impl)][4]; + clock_t times1[countof(impl1)][4][37]; + char buf[100]; + uint64_t bases = 0; +#define set_base(bases, b) (*(bases) |= (1ULL << (b))) +#define has_base(bases, b) ((bases) & (1ULL << (b))) +#define single_base(bases) (!((bases) & ((bases) - 1))) + int verbose = 0; + int average = 1; + int enabled = 3; + + memset(times, 0, sizeof times); + memset(times1, 0, sizeof times1); + + for (int a = 1; a < argc; a++) { + char *arg = argv[a]; + if (isdigit((unsigned char)*arg)) { + while (isdigit((unsigned char)*arg)) { + int b1 = strtol(arg, &arg, 10); + set_base(&bases, b1); + if (*arg == '-') { + int b2 = strtol(arg + 1, &arg, 10); + while (++b1 <= b2) + set_base(&bases, b1); + } + if (*arg == ',') { + arg++; + continue; + } + } + if (*arg) { + fprintf(stderr, "invalid option syntax: %s\n", argv[a]); + return 2; + } + continue; + } else if (!strcmp(arg, "-t") || !strcmp(arg, "--terse")) { + verbose = 0; + average = 1; + continue; + } else if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) { + verbose = 1; + continue; + } else if (!strcmp(arg, "-h") || !strcmp(arg, "-?") || !strcmp(arg, "--help")) { + show_usage(); + return 0; + } else { + int found = 0; + for (size_t i = 0; i < countof(impl); i++) { + if (strstr(impl[i].name, arg)) { + impl[i].enabled = 1; + found = 1; + } + } + for (size_t i = 0; i < countof(impl1); i++) { + if (strstr(impl1[i].name, arg)) { + impl1[i].enabled = 1; + found = 1; + } + } + if (!found) { + fprintf(stderr, "no variant for filter: %s\n", argv[a]); + return 2; + } + enabled = 1; + continue; + } + } + if (!bases) + bases = -1; + if (single_base(bases)) { + average = 0; + verbose = 1; + } else { + average = 1; + } + + int numvariant = 0; + int numvariant1 = 0; + int nerrors = 0; + + /* Checking for correctness */ + if (has_base(bases, 10)) { + for (size_t i = 0; i < countof(impl); i++) { + unsigned base = 10; + if (impl[i].enabled & enabled) { + CHECK(impl[i], 100000, 0, 32, u32toa(buf, x), strtoull(buf, NULL, 10)); + CHECK(impl[i], 100000, 1, 32, i32toa(buf, x), strtoll(buf, NULL, 10)); + CHECK(impl[i], 100000, 0, 64, u64toa(buf, x), strtoull(buf, NULL, 10)); + CHECK(impl[i], 100000, 1, 64, i64toa(buf, x), strtoll(buf, NULL, 10)); + } + } + } + for (size_t i = 0; i < countof(impl1); i++) { + if (impl1[i].enabled & enabled) { + for (unsigned base = 2; base <= 36; base++) { + if (has_base(bases, base)) { + CHECK(impl1[i], 1000, 0, 32, u32toa_radix(buf, x, base), strtoull(buf, NULL, base)); + CHECK(impl1[i], 1000, 1, 32, i32toa_radix(buf, x, base), strtoll(buf, NULL, base)); + CHECK(impl1[i], 1000, 0, 64, u64toa_radix(buf, x, base), strtoull(buf, NULL, base)); + CHECK(impl1[i], 1000, 1, 64, i64toa_radix(buf, x, base), strtoll(buf, NULL, base)); + } + } + } + } + if (nerrors) + return 1; + + /* Timing conversions */ + if (has_base(bases, 10)) { + for (int rep = 0; rep < 100; rep++) { + for (size_t i = 0; i < countof(impl); i++) { + if (impl[i].enabled & enabled) { + numvariant++; +#ifdef TEST_SNPRINTF + if (strstr(impl[i].name, "snprintf")) { // avoid wrapper overhead + TIME(times[i][0], 1000, 0, 32, snprintf(buf, 11, "%"PRIu32, x)); + TIME(times[i][1], 1000, 1, 32, snprintf(buf, 12, "%"PRIi32, x)); + TIME(times[i][2], 1000, 0, 64, snprintf(buf, 21, "%"PRIu64, x)); + TIME(times[i][3], 1000, 1, 64, snprintf(buf, 22, "%"PRIi64, x)); + } else +#endif + { + TIME(times[i][0], 1000, 0, 32, impl[i].u32toa(buf, x)); + TIME(times[i][1], 1000, 1, 32, impl[i].i32toa(buf, x)); + TIME(times[i][2], 1000, 0, 64, impl[i].u64toa(buf, x)); + TIME(times[i][3], 1000, 1, 64, impl[i].i64toa(buf, x)); + } + } + } + } + } + for (int rep = 0; rep < 10; rep++) { + for (size_t i = 0; i < countof(impl1); i++) { + if (impl1[i].enabled & enabled) { + numvariant1++; +#ifdef TEST_SNPRINTF + if (strstr(impl[i].name, "snprintf")) { // avoid wrapper overhead +#ifdef PRIb32 + if (has_base(bases, 2)) { + unsigned base = 2; + TIME(times1[i][0][base], 1000, 0, 32, snprintf(buf, 33, "%"PRIb32, x)); + TIME(times1[i][1][base], 1000, 1, 32, impl1[i].i32toa_radix(buf, x, base)); + TIME(times1[i][2][base], 1000, 0, 64, snprintf(buf, 65, "%"PRIb64, x)); + TIME(times1[i][3][base], 1000, 1, 64, impl1[i].i64toa_radix(buf, x, base)); + } +#endif + if (has_base(bases, 8)) { + unsigned base = 8; + TIME(times1[i][0][base], 1000, 0, 32, snprintf(buf, 33, "%"PRIo32, x)); + TIME(times1[i][1][base], 1000, 1, 32, impl1[i].i32toa_radix(buf, x, base)); + TIME(times1[i][2][base], 1000, 0, 64, snprintf(buf, 65, "%"PRIo64, x)); + TIME(times1[i][3][base], 1000, 1, 64, impl1[i].i64toa_radix(buf, x, base)); + } + if (has_base(bases, 10)) { + unsigned base = 10; + TIME(times1[i][0][base], 1000, 0, 32, snprintf(buf, 33, "%"PRIu32, x)); + TIME(times1[i][1][base], 1000, 1, 32, snprintf(buf, 34, "%"PRIi32, x)); + TIME(times1[i][2][base], 1000, 0, 64, snprintf(buf, 64, "%"PRIu64, x)); + TIME(times1[i][3][base], 1000, 1, 64, snprintf(buf, 65, "%"PRIi64, x)); + } + if (has_base(bases, 16)) { + unsigned base = 16; + TIME(times1[i][0][base], 1000, 0, 32, snprintf(buf, 33, "%"PRIx32, x)); + TIME(times1[i][1][base], 1000, 1, 32, impl1[i].i32toa_radix(buf, x, base)); + TIME(times1[i][2][base], 1000, 0, 64, snprintf(buf, 65, "%"PRIx64, x)); + TIME(times1[i][3][base], 1000, 1, 64, impl1[i].i64toa_radix(buf, x, base)); + } + } else +#endif + { + for (unsigned base = 2; base <= 36; base++) { + if (has_base(bases, base)) { + TIME(times1[i][0][base], 1000, 0, 32, impl1[i].u32toa_radix(buf, x, base)); + TIME(times1[i][1][base], 1000, 1, 32, impl1[i].i32toa_radix(buf, x, base)); + TIME(times1[i][2][base], 1000, 0, 64, impl1[i].u64toa_radix(buf, x, base)); + TIME(times1[i][3][base], 1000, 1, 64, impl1[i].i64toa_radix(buf, x, base)); + } + } + } + } + } + } + + if (numvariant) { + printf("%13s %10s %12s %12s %12s\n", + "variant", "u32toa", "i32toa", "u64toa", "i64toa"); + for (size_t i = 0; i < countof(impl); i++) { + if (impl[i].enabled & enabled) { + printf("%13s", impl[i].name); + for (int j = 0; j < 4; j++) + printf(" %6.2fns ", times[i][j] * (1e9 / 1000 / 64 / CLOCKS_PER_SEC)); + printf("\n"); + } + } + } + if (numvariant1) { + printf("%9s rx %12s %12s %12s %12s\n", + "variant", "u32toa_radix", "i32toa_radix", "u64toa_radix", "i64toa_radix"); + for (size_t i = 0; i < countof(impl1); i++) { + int numbases = 0; + for (unsigned base = 2; base <= 36; base++) { + if (has_base(bases, base)) { + if (times1[i][0][base]) { + numbases++; + for (int j = 0; j < 4; j++) + times1[i][j][1] += times1[i][j][base]; + if (verbose) { + printf("%9s %-3d", impl1[i].name, base); + for (int j = 0; j < 4; j++) { + printf(" %6.2fns ", times1[i][j][base] * (1e9 / 1000 / 64 / CLOCKS_PER_SEC)); + } + printf("\n"); + } + } + } + } + if (average && numbases) { + printf("%9s avg", impl1[i].name); + for (int j = 0; j < 4; j++) { + printf(" %6.2fns ", times1[i][j][1] * (1e9 / 1000 / 64 / numbases / CLOCKS_PER_SEC)); + } + printf("\n"); + } + } + } + return 0; +} diff --git a/tests/test_cyclic_import.js b/tests/test_cyclic_import.js new file mode 100644 index 0000000..bf51d9b --- /dev/null +++ b/tests/test_cyclic_import.js @@ -0,0 +1,12 @@ +/*--- +negative: + phase: resolution + type: SyntaxError +---*/ +// FIXME(bnoordhuis) shouldn't throw SyntaxError but that's still better +// than segfaulting, see https://github.com/quickjs-ng/quickjs/issues/567 +import {assert} from "./assert.js" +import {f} from "./fixture_cyclic_import.js" +export {f} +export function g(x) { return x + 1 } +assert(f(1), 4) diff --git a/tests/test_language.js b/tests/test_language.js index 65dab5f..dbb4947 100644 --- a/tests/test_language.js +++ b/tests/test_language.js @@ -1,3 +1,5 @@ +// 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; @@ -5,35 +7,44 @@ function assert(actual, expected, message) { if (actual === expected) return; + if (typeof actual == 'number' && isNaN(actual) + && typeof expected == 'number' && isNaN(expected)) + return; + if (actual !== null && expected !== null && typeof actual == 'object' && typeof expected == 'object' && actual.toString() === expected.toString()) return; + var msg = message ? " (" + message + ")" : ""; throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); + ", expected |" + expected + "|" + msg); } -function assert_throws(expected_error, func) +function assert_throws(expected_error, func, message) { var err = false; + var msg = message ? " (" + message + ")" : ""; try { - func(); + switch (typeof func) { + case 'string': + eval(func); + break; + case 'function': + func(); + break; + } } catch(e) { err = true; if (!(e instanceof expected_error)) { - throw Error("unexpected exception type"); + throw Error(`expected ${expected_error.name}, got ${e.name}${msg}`); } } if (!err) { - throw Error("expected exception"); + throw Error(`expected ${expected_error.name}${msg}`); } } -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - /*----------------*/ function test_op1() @@ -68,10 +79,10 @@ function test_op1() r = 1 << 31; assert(r, -2147483648, "1 << 31 === -2147483648"); - + r = 1 << 32; assert(r, 1, "1 << 32 === 1"); - + r = (1 << 31) < 0; assert(r, true, "(1 << 31) < 0 === true"); @@ -107,20 +118,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() @@ -141,7 +152,7 @@ function test_eq() function test_inc_dec() { var a, r; - + a = 1; r = a++; assert(r === 1 && a === 2, true, "++"); @@ -169,19 +180,19 @@ function test_inc_dec() a = [true]; a[0]++; assert(a[0], 2, "++"); - + a = {x:true}; r = a.x++; assert(r === 1 && a.x === 2, true, "++"); - + a = {x:true}; r = a.x--; assert(r === 1 && a.x === 0, true, "--"); - + a = [true]; r = a[0]++; assert(r === 1 && a[0] === 2, true, "++"); - + a = [true]; r = a[0]--; assert(r === 1 && a[0] === 0, true, "--"); @@ -213,7 +224,7 @@ function test_op2() assert((typeof Object), "function", "typeof"); assert((typeof null), "object", "typeof"); assert((typeof unknown_var), "undefined", "typeof"); - + a = {x: 1, if: 2, async: 3}; assert(a.if === 2); assert(a.async === 3); @@ -226,7 +237,7 @@ function test_delete() a = {x: 1, y: 1}; assert((delete a.x), true, "delete"); assert(("x" in a), false, "delete"); - + /* the following are not tested by test262 */ assert(delete "abc"[100], true); @@ -305,36 +316,50 @@ 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(D.F() === -1); - assert(D.G() === -2); - assert(D.H() === -1); + assert(o.f(), 1); + assert(o.x, 10); + + 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); }; function test_template() @@ -362,8 +387,9 @@ function test_template_skip() function test_object_literal() { var x = 0, get = 1, set = 2; async = 3; - a = { get: 2, set: 3, async: 4 }; - assert(JSON.stringify(a), '{"get":2,"set":3,"async":4}'); + 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); a = { x, get, set, async }; assert(JSON.stringify(a), '{"x":0,"get":1,"set":2,"async":3}'); @@ -373,10 +399,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() @@ -419,9 +445,11 @@ function test_argument_scope() { var f; var c = "global"; - + f = function(a = eval("var arguments")) {}; - assert_throws(SyntaxError, f); + // for some reason v8 does not throw an exception here + if (typeof require === 'undefined') + assert_throws(SyntaxError, f); f = function(a = eval("1"), b = arguments[0]) { return b; }; assert(f(12), 12); @@ -490,7 +518,7 @@ function test_function_expr_name() /* non strict mode test : assignment to the function name silently fails */ - + f = function myfunc() { myfunc = 1; return myfunc; @@ -511,7 +539,7 @@ function test_function_expr_name() return myfunc; }; assert(f(), f); - + /* strict mode test : assignment to the function name raises a TypeError exception */ @@ -536,6 +564,132 @@ 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() +{ + 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); +} + +function test_syntax() +{ + 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"); +} + +/* optional chaining tests not present in test262 */ +function test_optional_chaining() +{ + var a, z; + z = null; + a = { b: { c: 2 } }; + assert(delete z?.b.c, true); + assert(delete a?.b.c, true); + assert(JSON.stringify(a), '{"b":{}}', "optional chaining delete"); + + a = { b: { c: 2 } }; + assert(delete z?.b["c"], true); + assert(delete a?.b["c"], true); + assert(JSON.stringify(a), '{"b":{}}'); + + a = { + b() { return this._b; }, + _b: { c: 42 } + }; + + assert((a?.b)().c, 42); + + assert((a?.["b"])().c, 42); +} + function test_parse_semicolon() { /* 'yield' or 'await' may not be considered as a token if the @@ -558,31 +712,6 @@ function test_parse_semicolon() } } -/* optional chaining tests not present in test262 */ -function test_optional_chaining() -{ - var a, z; - z = null; - a = { b: { c: 2 } }; - assert(delete z?.b.c, true); - assert(delete a?.b.c, true); - assert(JSON.stringify(a), '{"b":{}}', "optional chaining delete"); - - a = { b: { c: 2 } }; - assert(delete z?.b["c"], true); - assert(delete a?.b["c"], true); - assert(JSON.stringify(a), '{"b":{}}'); - - a = { - b() { return this._b; }, - _b: { c: 42 } - }; - - assert((a?.b)().c, 42); - - assert((a?.["b"])().c, 42); -} - test_op1(); test_cvt(); test_eq(); @@ -602,5 +731,8 @@ test_spread(); test_function_length(); test_argument_scope(); test_function_expr_name(); -test_parse_semicolon(); +test_reserved_names(); +test_number_literals(); +test_syntax(); test_optional_chaining(); +test_parse_semicolon(); diff --git a/tests/test_loop.js b/tests/test_loop.js index 084d658..97fc2f6 100644 --- a/tests/test_loop.js +++ b/tests/test_loop.js @@ -1,3 +1,5 @@ +// 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; @@ -15,9 +17,6 @@ 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() @@ -29,7 +28,7 @@ function test_while() c++; i++; } - assert(c === 3); + assert(c, 3); } function test_while_break() @@ -167,29 +166,6 @@ 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; @@ -356,7 +332,7 @@ function test_try_catch7() function test_try_catch8() { var i, s; - + s = ""; for(var i in {x:1, y:2}) { try { @@ -380,7 +356,6 @@ test_switch1(); test_switch2(); test_for_in(); test_for_in2(); -test_for_in_proxy(); test_try_catch1(); test_try_catch2(); diff --git a/tests/test_op_overloading.js b/tests/test_op_overloading.js deleted file mode 100644 index d08a85e..0000000 --- a/tests/test_op_overloading.js +++ /dev/null @@ -1,207 +0,0 @@ -"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 + ")" : "")); -} - -/* operators overloading with Operators.create() */ -function test_operators_create() { - class Vec2 - { - constructor(x, y) { - this.x = x; - this.y = y; - } - static mul_scalar(p1, a) { - var r = new Vec2(); - r.x = p1.x * a; - r.y = p1.y * a; - return r; - } - toString() { - return "Vec2(" + this.x + "," + this.y + ")"; - } - } - - Vec2.prototype[Symbol.operatorSet] = Operators.create( - { - "+"(p1, p2) { - var r = new Vec2(); - r.x = p1.x + p2.x; - r.y = p1.y + p2.y; - return r; - }, - "-"(p1, p2) { - var r = new Vec2(); - r.x = p1.x - p2.x; - r.y = p1.y - p2.y; - return r; - }, - "=="(a, b) { - return a.x == b.x && a.y == b.y; - }, - "<"(a, b) { - var r; - /* lexicographic order */ - if (a.x == b.x) - r = (a.y < b.y); - else - r = (a.x < b.x); - return r; - }, - "++"(a) { - var r = new Vec2(); - r.x = a.x + 1; - r.y = a.y + 1; - return r; - } - }, - { - left: Number, - "*"(a, b) { - return Vec2.mul_scalar(b, a); - } - }, - { - right: Number, - "*"(a, b) { - return Vec2.mul_scalar(a, b); - } - }); - - var a = new Vec2(1, 2); - var b = new Vec2(3, 4); - var r; - - r = a * 2 + 3 * b; - assert(r.x === 11 && r.y === 16); - assert(a == a, true); - assert(a == b, false); - assert(a != a, false); - assert(a < b, true); - assert(a <= b, true); - assert(b < a, false); - assert(b <= a, false); - assert(a <= a, true); - assert(a >= a, true); - a++; - assert(a.x === 2 && a.y === 3); - r = ++a; - assert(a.x === 3 && a.y === 4); - assert(r === a); -} - -/* operators overloading thru inheritance */ -function test_operators() -{ - var Vec2; - - function mul_scalar(p1, a) { - var r = new Vec2(); - r.x = p1.x * a; - r.y = p1.y * a; - return r; - } - - var vec2_ops = Operators({ - "+"(p1, p2) { - var r = new Vec2(); - r.x = p1.x + p2.x; - r.y = p1.y + p2.y; - return r; - }, - "-"(p1, p2) { - var r = new Vec2(); - r.x = p1.x - p2.x; - r.y = p1.y - p2.y; - return r; - }, - "=="(a, b) { - return a.x == b.x && a.y == b.y; - }, - "<"(a, b) { - var r; - /* lexicographic order */ - if (a.x == b.x) - r = (a.y < b.y); - else - r = (a.x < b.x); - return r; - }, - "++"(a) { - var r = new Vec2(); - r.x = a.x + 1; - r.y = a.y + 1; - return r; - } - }, - { - left: Number, - "*"(a, b) { - return mul_scalar(b, a); - } - }, - { - right: Number, - "*"(a, b) { - return mul_scalar(a, b); - } - }); - - Vec2 = class Vec2 extends vec2_ops - { - constructor(x, y) { - super(); - this.x = x; - this.y = y; - } - toString() { - return "Vec2(" + this.x + "," + this.y + ")"; - } - } - - var a = new Vec2(1, 2); - var b = new Vec2(3, 4); - var r; - - r = a * 2 + 3 * b; - assert(r.x === 11 && r.y === 16); - assert(a == a, true); - assert(a == b, false); - assert(a != a, false); - assert(a < b, true); - assert(a <= b, true); - assert(b < a, false); - assert(b <= a, false); - assert(a <= a, true); - assert(a >= a, true); - a++; - assert(a.x === 2 && a.y === 3); - r = ++a; - assert(a.x === 3 && a.y === 4); - assert(r === a); -} - -function test_default_op() -{ - assert(Object(1) + 2, 3); - assert(Object(1) + true, 2); - assert(-Object(1), -1); -} - -test_operators_create(); -test_operators(); -test_default_op(); diff --git a/tests/test_qjscalc.js b/tests/test_qjscalc.js deleted file mode 100644 index 1483466..0000000 --- a/tests/test_qjscalc.js +++ /dev/null @@ -1,256 +0,0 @@ -"use math"; -"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 pow(a, n) -{ - var r, i; - r = 1; - for(i = 0; i < n; i++) - r *= a; - return r; -} - -function test_integer() -{ - var a, r; - a = pow(3, 100); - assert((a - 1) != a); - assert(a == 515377520732011331036461129765621272702107522001); - assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1); - assert(Integer.isInteger(1) === true); - assert(Integer.isInteger(1.0) === false); - - assert(Integer.floorLog2(0) === -1); - assert(Integer.floorLog2(7) === 2); - - r = 1 << 31; - assert(r, 2147483648, "1 << 31 === 2147483648"); - - r = 1 << 32; - assert(r, 4294967296, "1 << 32 === 4294967296"); - - r = (1 << 31) < 0; - assert(r, false, "(1 << 31) < 0 === false"); - - assert(typeof 1 === "number"); - assert(typeof 9007199254740991 === "number"); - assert(typeof 9007199254740992 === "bigint"); -} - -function test_float() -{ - assert(typeof 1.0 === "bigfloat"); - assert(1 == 1.0); - assert(1 !== 1.0); -} - -/* jscalc tests */ - -function test_modulo() -{ - var i, p, a, b; - - /* Euclidian modulo operator */ - assert((-3) % 2 == 1); - assert(3 % (-2) == 1); - - p = 101; - for(i = 1; i < p; i++) { - a = Integer.invmod(i, p); - assert(a >= 0 && a < p); - assert((i * a) % p == 1); - } - - assert(Integer.isPrime(2^107-1)); - assert(!Integer.isPrime((2^107-1) * (2^89-1))); - a = Integer.factor((2^89-1)*2^3*11*13^2*1009); - assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]); -} - -function test_fraction() -{ - assert((1/3 + 1).toString(), "4/3") - assert((2/3)^30, 1073741824/205891132094649); - assert(1/3 < 2/3); - assert(1/3 < 1); - assert(1/3 == 1.0/3); - assert(1.0/3 < 2/3); -} - -function test_mod() -{ - var a, b, p; - - a = Mod(3, 101); - b = Mod(-1, 101); - assert((a + b) == Mod(2, 101)); - assert(a ^ 100 == Mod(1, 101)); - - p = 2 ^ 607 - 1; /* mersenne prime */ - a = Mod(3, p) ^ (p - 1); - assert(a == Mod(1, p)); -} - -function test_polynomial() -{ - var a, b, q, r, t, i; - a = (1 + X) ^ 4; - assert(a == X^4+4*X^3+6*X^2+4*X+1); - - r = (1 + X); - q = (1+X+X^2); - b = (1 - X^2); - a = q * b + r; - t = Polynomial.divrem(a, b); - assert(t[0] == q); - assert(t[1] == r); - - a = 1 + 2*X + 3*X^2; - assert(a.apply(0.1) == 1.23); - - a = 1-2*X^2+2*X^3; - assert(deriv(a) == (6*X^2-4*X)); - assert(deriv(integ(a)) == a); - - a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1); - r = polroots(a); - for(i = 0; i < r.length; i++) { - b = abs(a.apply(r[i])); - assert(b <= 1e-13); - } -} - -function test_poly_mod() -{ - var a, p; - - /* modulo using polynomials */ - p = X^2 + X + 1; - a = PolyMod(3+X, p) ^ 10; - assert(a == PolyMod(-3725*X-18357, p)); - - a = PolyMod(1/X, 1+X^2); - assert(a == PolyMod(-X, X^2+1)); -} - -function test_rfunc() -{ - var a; - a = (X+1)/((X+1)*(X-1)); - assert(a == 1/(X-1)); - a = (X + 2) / (X - 2); - assert(a.apply(1/3) == -7/5); - - assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1)); -} - -function test_series() -{ - var a, b; - a = 1+X+O(X^5); - b = a.inverse(); - assert(b == 1-X+X^2-X^3+X^4+O(X^5)); - assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4)); - assert(deriv(integ(b)) == b); - - a = Series(1/(1-X), 5); - assert(a == 1+X+X^2+X^3+X^4+O(X^5)); - b = a.apply(0.1); - assert(b == 1.1111); - - assert(exp(3*X^2+O(X^10)) == 1+3*X^2+9/2*X^4+9/2*X^6+27/8*X^8+O(X^10)); - assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6)); - assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6)); - assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8)); - assert((1+X+O(X^6))^(2+X) == 1+2*X+2*X^2+3/2*X^3+5/6*X^4+5/12*X^5+O(X^6)); -} - -function test_matrix() -{ - var a, b, r; - a = [[1, 2],[3, 4]]; - b = [3, 4]; - r = a * b; - assert(r == [11, 25]); - r = (a^-1) * 2; - assert(r == [[-4, 2],[3, -1]]); - - assert(norm2([1,2,3]) == 14); - - assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]); - assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]); - assert(trans([1,2,3]) == [[1,2,3]]); - assert(trace(a) == 5); - - assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000); - assert(det(Matrix.hilbert(4)) == 1/6048000); - - a = [[1,2,1],[-2,-3,1],[3,5,0]]; - assert(rank(a) == 2); - assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]); - - assert(dp([1, 2, 3], [3, -4, -7]) === -26); - assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]); -} - -function assert_eq(a, ref) -{ - assert(abs(a / ref - 1.0) <= 1e-15); -} - -function test_trig() -{ - assert_eq(sin(1/2), 0.479425538604203); - assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I); - assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I); - assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I); - assert_eq(sqrt(2*I), 1 + I); -} - -test_integer(); -test_float(); - -test_modulo(); -test_fraction(); -test_mod(); -test_polynomial(); -test_poly_mod(); -test_rfunc(); -test_series(); -test_matrix(); -test_trig(); diff --git a/tests/test_queue_microtask.js b/tests/test_queue_microtask.js new file mode 100644 index 0000000..f06dc8b --- /dev/null +++ b/tests/test_queue_microtask.js @@ -0,0 +1,39 @@ +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/tests/test_std.js b/tests/test_std.js index 6fb94c2..4603590 100644 --- a/tests/test_std.js +++ b/tests/test_std.js @@ -1,28 +1,10 @@ -#! (shebang test) -import * as std from "std"; -import * as os from "os"; +import * as std from "qjs:std"; +import * as os from "qjs:os"; +import { assert } from "./assert.js"; -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; +const isWin = os.platform === 'win32'; +const isCygwin = os.platform === 'cygwin'; - 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 + ")" : "")); -} - -// load more elaborate version of assert if available -try { std.loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ function test_printf() { @@ -45,19 +27,19 @@ function test_file1() 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(); } @@ -72,16 +54,16 @@ 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(); } function test_getline() { var f, line, line_count, lines, i; - + lines = ["hello world", "line 1", "line 2" ]; f = std.tmpfile(); for(i = 0; i < lines.length; i++) { @@ -95,19 +77,20 @@ 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(); } - + function test_popen() { var str, f, fname = "tmp_file.txt"; var content = "hello world"; + var cmd = isWin ? "type" : "cat"; f = std.open(fname, "w"); f.puts(content); @@ -115,9 +98,9 @@ function test_popen() /* test loadFile */ assert(std.loadFile(fname), content); - - /* execute the 'cat' shell command */ - f = std.popen("cat " + fname, "r"); + + /* execute shell command */ + f = std.popen(cmd + " " + fname, "r"); str = f.readAsString(); f.close(); @@ -126,60 +109,47 @@ 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],"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 - "s":"str",} // trailing comma in objects and arrays - `; - obj = std.parseExtJSON(input); - assert(JSON.stringify(obj), expected); -} - function test_os() { var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; - assert(os.isatty(0)); + // XXX(bnoordhuis) disabled because stdio is not a tty on CI + //assert(os.isatty(0)); fdir = "test_tmp_dir"; fname = "tmp_file.txt"; fpath = fdir + "/" + fname; link_path = fdir + "/test_link"; - + os.remove(link_path); os.remove(fpath); 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); - + 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); @@ -189,24 +159,26 @@ function test_os() err = os.utimes(fpath, fdate, fdate); assert(err, 0); - + [st, err] = os.stat(fpath); assert(err, 0); assert(st.mode & os.S_IFMT, os.S_IFREG); assert(st.mtime, fdate); - 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); + if (!isWin) { + err = os.symlink(fname, link_path); + assert(err, 0); - [buf, err] = os.readlink(link_path); - assert(err, 0); - assert(buf, fname); - - assert(os.remove(link_path) === 0); + [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); + + assert(os.remove(link_path) === 0); + } [buf, err] = os.getcwd(); assert(err, 0); @@ -215,7 +187,7 @@ function test_os() assert(err, 0); assert(buf, buf2); - + assert(os.remove(fpath) === 0); fd = os.open(fpath, os.O_RDONLY); @@ -233,7 +205,7 @@ function test_os_exec() ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); assert(ret, 1); - + fds = os.pipe(); pid = os.exec(["sh", "-c", "echo $FOO"], { stdout: fds[1], @@ -253,13 +225,26 @@ function test_os_exec() pid = os.exec(["cat"], { block: false } ); assert(pid >= 0); - os.kill(pid, os.SIGQUIT); + os.kill(pid, os.SIGTERM); [ret, status] = os.waitpid(pid, 0); assert(ret, pid); - assert(status & 0x7f, os.SIGQUIT); + // Flaky on cygwin for unclear reasons, see + // https://github.com/quickjs-ng/quickjs/issues/184 + if (!isCygwin) { + assert(status & 0x7f, os.SIGTERM); + } } -function test_timer() +function test_interval() +{ + var t = os.setInterval(f, 1); + function f() { + if (++f.count === 3) os.clearInterval(t); + } + f.count = 0; +} + +function test_timeout() { var th, i; @@ -271,24 +256,30 @@ function test_timer() os.clearTimeout(th[i]); } -/* test closure variable handling when freeing asynchronous - function */ -function test_async_gc() +function test_timeout_order() { - (async function run () { - let obj = {} - - let done = () => { - obj - std.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" +} + +function test_stdio_close() +{ + 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; } - - Promise.resolve().then(done) - - const p = new Promise(() => {}) - - await p - })(); + assert(caught); + } } test_printf(); @@ -297,8 +288,8 @@ test_file2(); test_getline(); test_popen(); test_os(); -test_os_exec(); -test_timer(); -test_ext_json(); -test_async_gc(); - +!isWin && test_os_exec(); +test_interval(); +test_timeout(); +test_timeout_order(); +test_stdio_close(); diff --git a/tests/test_worker.js b/tests/test_worker.js index 4b52bf8..8309c18 100644 --- a/tests/test_worker.js +++ b/tests/test_worker.js @@ -1,23 +1,5 @@ -/* 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 + ")" : "")); -} +import * as os from "qjs:os"; +import { assert } from "./assert.js"; var worker; @@ -58,5 +40,6 @@ function test_worker() }; } - -test_worker(); +if (os.platform !== 'win32') { + test_worker(); +} diff --git a/tests/test_worker_module.js b/tests/test_worker_module.js index f19600a..7280c69 100644 --- a/tests/test_worker_module.js +++ b/tests/test_worker_module.js @@ -1,6 +1,5 @@ /* Worker code for test_worker.js */ -import * as std from "std"; -import * as os from "os"; +import * as os from "qjs:os"; var parent = os.Worker.parent; @@ -10,7 +9,6 @@ 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 */ @@ -22,10 +20,10 @@ function handle_msg(e) { function worker_main() { var i; - + parent.onmessage = handle_msg; for(i = 0; i < 10; i++) { - parent.postMessage({ type: "num", num: i }); + parent.postMessage({ type: "num", num: i }); } } diff --git a/unicode_download.sh b/unicode_download.sh index 35daf0e..fb8343a 100755 --- a/unicode_download.sh +++ b/unicode_download.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -url="ftp://ftp.unicode.org/Public/15.0.0/ucd" +url="ftp://ftp.unicode.org/Public/16.0.0/ucd" emoji_url="${url}/emoji/emoji-data.txt" files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ diff --git a/unicode_gen.c b/unicode_gen.c index 54da2c1..76806e6 100644 --- a/unicode_gen.c +++ b/unicode_gen.c @@ -1,6 +1,6 @@ /* * Generation of Unicode tables - * + * * Copyright (c) 2017-2018 Fabrice Bellard * Copyright (c) 2017-2018 Charlie Gordon * @@ -291,7 +291,7 @@ void parse_unicode_data(const char *filename) const char *p; int code, lc, uc, last_code; CCInfo *ci, *tab = unicode_db; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -314,7 +314,7 @@ void parse_unicode_data(const char *filename) code = strtoul(p, NULL, 16); lc = 0; uc = 0; - + p = get_field(line, 12); if (p && *p != ';') { uc = strtoul(p, NULL, 16); @@ -350,7 +350,7 @@ void parse_unicode_data(const char *filename) } ci->general_category = i; } - + p = get_field(line, 3); if (p && *p != ';' && *p != '\0') { int cc; @@ -382,27 +382,13 @@ 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); if (p && *p == 'Y') { set_prop(code, PROP_Bidi_Mirrored, 1); } - + /* handle ranges */ get_field_buf(buf1, sizeof(buf1), line, 1); if (strstr(buf1, " Last>")) { @@ -416,7 +402,7 @@ void parse_unicode_data(const char *filename) } last_code = code; } - + fclose(f); } @@ -427,7 +413,7 @@ void parse_special_casing(CCInfo *tab, const char *filename) const char *p; int code; CCInfo *ci; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -458,8 +444,8 @@ void parse_special_casing(CCInfo *tab, const char *filename) if (*p != '#' && *p != '\0') continue; } - - + + p = get_field(line, 1); if (p && *p != ';') { ci->l_len = 0; @@ -492,7 +478,7 @@ void parse_special_casing(CCInfo *tab, const char *filename) ci->u_len = 0; } } - + fclose(f); } @@ -503,7 +489,7 @@ void parse_case_folding(CCInfo *tab, const char *filename) const char *p; int code, status; CCInfo *ci; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -535,7 +521,7 @@ void parse_case_folding(CCInfo *tab, const char *filename) status = *p; if (status != 'C' && status != 'S' && status != 'F') continue; - + p = get_field(line, 2); assert(p != NULL); if (status == 'S') { @@ -555,7 +541,7 @@ void parse_case_folding(CCInfo *tab, const char *filename) ci->f_data[ci->f_len++] = strtoul(p, (char **)&p, 16); } } - + fclose(f); } @@ -564,7 +550,7 @@ void parse_composition_exclusions(const char *filename) FILE *f; char line[4096], *p; uint32_t c0; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -592,7 +578,7 @@ void parse_derived_core_properties(const char *filename) char line[4096], *p, buf[256], *q; uint32_t c0, c1, c; int i; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -620,7 +606,8 @@ void parse_derived_core_properties(const char *filename) p++; p += strspn(p, " \t"); q = buf; - while (*p != '\0' && *p != ' ' && *p != '#' && *p != '\t') { + static const char ignore[] = "\t #;"; // includes \0 + while (!memchr(ignore, *p, sizeof(ignore))) { if ((q - buf) < sizeof(buf) - 1) *q++ = *p; p++; @@ -648,7 +635,7 @@ void parse_derived_norm_properties(const char *filename) FILE *f; char line[4096], *p, buf[256], *q; uint32_t c0, c1, c; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -698,7 +685,7 @@ void parse_prop_list(const char *filename) char line[4096], *p, buf[256], *q; uint32_t c0, c1, c; int i; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -752,7 +739,7 @@ void parse_scripts(const char *filename) char line[4096], *p, buf[256], *q; uint32_t c0, c1, c; int i; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -807,7 +794,7 @@ void parse_script_extensions(const char *filename) int i; uint8_t script_ext[255]; int script_ext_len; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -972,7 +959,7 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code) ci1 = &tab[code + 1]; ci2 = &tab[code + 2]; te->code = code; - + if (ci->l_len == 1 && ci->l_data[0] == code + 2 && ci->f_len == 1 && ci->f_data[0] == ci->l_data[0] && ci->u_len == 0 && @@ -1112,6 +1099,24 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code) te->ext_data[1] = ci->u_data[1]; te->ext_data[2] = ci->u_data[2]; te->ext_len = 3; + } else if (ci->u_len == 2 && ci->l_len == 0 && ci->f_len == 1) { + // U+FB05 LATIN SMALL LIGATURE LONG S T + assert(code == 0xFB05); + te->len = 1; + te->type = RUN_TYPE_UF_EXT2; + te->ext_data[0] = ci->u_data[0]; + te->ext_data[1] = ci->u_data[1]; + te->ext_len = 2; + } else if (ci->u_len == 3 && ci->l_len == 0 && ci->f_len == 1) { + // U+1FD3 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA or + // U+1FE3 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA + assert(code == 0x1FD3 || code == 0x1FE3); + te->len = 1; + te->type = RUN_TYPE_UF_EXT3; + te->ext_data[0] = ci->u_data[0]; + te->ext_data[1] = ci->u_data[1]; + te->ext_data[2] = ci->u_data[2]; + te->ext_len = 3; } else { printf("unsupported encoding case:\n"); dump_cc_info(ci, code); @@ -1140,7 +1145,7 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code) te->data = 0; return; } - + ci = &tab[code]; is_lower = ci->l_len > 0; len = 1; @@ -1221,7 +1226,7 @@ void build_conv_table(CCInfo *tab) int code, i, j; CCInfo *ci; TableEntry *te; - + te = conv_table; for(code = 0; code <= CHARCODE_MAX; code++) { ci = &tab[code]; @@ -1229,12 +1234,6 @@ 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++; @@ -1245,7 +1244,7 @@ void build_conv_table(CCInfo *tab) for(i = 0; i < conv_table_len; i++) { int data_index; te = &conv_table[i]; - + switch(te->type) { case RUN_TYPE_U: case RUN_TYPE_L: @@ -1452,18 +1451,6 @@ 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 } } @@ -1490,7 +1477,7 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) const uint32_t *buf; int buf_len, block_end_pos, bit; char cname[128]; - + dbuf_init(dbuf1); for(i = 0; i <= CHARCODE_MAX;) { @@ -1506,15 +1493,15 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) dbuf_put_u32(dbuf1, n - 1); i += n; } - + dbuf_init(dbuf); dbuf_init(dbuf2); buf = (uint32_t *)dbuf1->buf; buf_len = dbuf1->size / sizeof(buf[0]); - + /* the first value is assumed to be 0 */ assert(get_prop(0, prop_index) == 0); - + block_end_pos = PROP_BLOCK_LEN; i = 0; code = 0; @@ -1575,7 +1562,7 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) snprintf(cname, sizeof(cname), "unicode_prop_%s_index", unicode_prop_name[prop_index]); dump_byte_table(f, cname, dbuf2->buf, dbuf2->size); } - + dbuf_free(dbuf); dbuf_free(dbuf1); dbuf_free(dbuf2); @@ -1587,6 +1574,7 @@ void build_flags_tables(FILE *f) 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); } void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len, @@ -1690,7 +1678,7 @@ void build_general_category_table(FILE *f) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); #endif - + dump_byte_table(f, "unicode_gc_table", dbuf->buf, dbuf->size); dbuf_free(dbuf); @@ -1760,7 +1748,7 @@ void build_script_table(FILE *f) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); #endif - + dump_byte_table(f, "unicode_script_table", dbuf->buf, dbuf->size); dbuf_free(dbuf); @@ -1810,7 +1798,7 @@ void build_script_ext_table(FILE *f) cw_count); printf(", length=%d bytes\n", (int)dbuf->size); #endif - + dump_byte_table(f, "unicode_script_ext_table", dbuf->buf, dbuf->size); dbuf_free(dbuf); @@ -1822,17 +1810,18 @@ void build_script_ext_table(FILE *f) void build_prop_list_table(FILE *f) { int i; - + for(i = 0; i < PROP_TABLE_COUNT; i++) { if (i == PROP_ID_Start || i == PROP_Case_Ignorable || - i == PROP_ID_Continue1) { + i == PROP_ID_Continue1 || + i == PROP_White_Space) { /* already generated */ } else { build_prop_table(f, i, FALSE); } } - + fprintf(f, "typedef enum {\n"); for(i = 0; i < PROP_COUNT; i++) fprintf(f, " UNICODE_PROP_%s,\n", unicode_prop_name[i]); @@ -1870,7 +1859,7 @@ void check_case_conv(void) int l, error; CCInfo ci_s, *ci1, *ci = &ci_s; int code; - + for(code = 0; code <= CHARCODE_MAX; code++) { ci1 = &tab[code]; *ci = *ci1; @@ -1986,7 +1975,7 @@ void build_cc_table(FILE *f) DynBuf dbuf1_s, *dbuf1 = &dbuf1_s; int cw_len_tab[3], cw_start, block_end_pos; uint32_t v; - + dbuf_init(dbuf); dbuf_init(dbuf1); cc_table_len = 0; @@ -2058,7 +2047,7 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf1, v); dbuf_putc(dbuf1, v >> 8); 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); @@ -2163,7 +2152,7 @@ const int decomp_incr_tab[4][4] = { /* entry size: type bits - code 18 + code 18 len 7 compat 1 type 5 @@ -2272,7 +2261,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) DecompEntry de_s, *de = &de_s; CCInfo *ci, *ci1, *ci2; int l, j, n, len_max; - + ci = &unicode_db[i]; l = ci->decomp_len; if (l == 0) { @@ -2283,12 +2272,12 @@ void find_decomp_run(DecompEntry *tab_de, int i) /* the offset for the compose table has only 6 bits, so we must limit if it can be used by the compose table */ if (!ci->is_compat && !ci->is_excluded && l == 2) - len_max = 64; + len_max = 64; else len_max = 127; - + tab_de[i].cost = 0x7fffffff; - + if (!is_16bit(ci->decomp_data, l)) { assert(l <= 2); @@ -2331,7 +2320,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) if (de->cost < tab_de[i].cost) { tab_de[i] = *de; } - + if (!((i + n) <= CHARCODE_MAX && n < len_max)) break; ci1 = &unicode_db[i + n]; @@ -2344,7 +2333,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) n++; } } - + if (l <= 8 || l == 18) { int c_min, c_max, c; c_min = c_max = -1; @@ -2415,7 +2404,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) /* check if a single char is increasing */ if (l <= 4) { int idx1, idx; - + for(idx1 = 1; (idx = decomp_incr_tab[l - 1][idx1]) >= 0; idx1++) { n = 1; for(;;) { @@ -2499,7 +2488,7 @@ void find_decomp_run(DecompEntry *tab_de, int i) if (l == 2) { BOOL is_16bit; - + n = 0; is_16bit = FALSE; for(;;) { @@ -2544,7 +2533,7 @@ void add_decomp_data(uint8_t *data_buf, int *pidx, DecompEntry *de) { int i, j, idx, c; CCInfo *ci; - + idx = *pidx; de->data_index = idx; if (de->type <= DECOMP_TYPE_C1) { @@ -2674,20 +2663,6 @@ 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) @@ -2695,9 +2670,9 @@ void build_decompose_table(FILE *f) int i, array_len, code_max, data_len, count; DecompEntry *tab_de, de_s, *de = &de_s; uint8_t *data_buf; - + code_max = CHARCODE_MAX; - + tab_de = mallocz((code_max + 2) * sizeof(*tab_de)); for(i = code_max; i >= 0; i--) { @@ -2721,7 +2696,7 @@ void build_decompose_table(FILE *f) /* dump */ { int size, size1; - + printf("START LEN TYPE L C SIZE\n"); size = 0; for(i = 0; i <= code_max; i++) { @@ -2735,7 +2710,7 @@ void build_decompose_table(FILE *f) size += size1; } } - + printf("array_len=%d estimated size=%d bytes actual=%d bytes\n", array_len, size, array_len * 6 + data_len); } @@ -2773,7 +2748,7 @@ void build_decompose_table(FILE *f) } } fprintf(f, "\n};\n\n"); - + fprintf(f, "static const uint8_t unicode_decomp_data[%u] = {", data_len); for(i = 0; i < data_len; i++) { @@ -2786,7 +2761,7 @@ void build_decompose_table(FILE *f) build_compose_table(f, tab_de); free(data_buf); - + free(tab_de); } @@ -2817,7 +2792,7 @@ static int get_decomp_pos(const DecompEntry *tab_de, int c) { int i, v, k; const DecompEntry *de; - + k = 0; for(i = 0; i <= CHARCODE_MAX; i++) { de = &tab_de[i]; @@ -2840,14 +2815,14 @@ void build_compose_table(FILE *f, const DecompEntry *tab_de) { int i, v, tab_ce_len; ComposeEntry *ce, *tab_ce; - + tab_ce = malloc(sizeof(*tab_ce) * COMPOSE_LEN_MAX); tab_ce_len = 0; for(i = 0; i <= CHARCODE_MAX; i++) { CCInfo *ci = &unicode_db[i]; if (ci->decomp_len == 2 && !ci->is_compat && !ci->is_excluded) { - assert(tab_ce_len < COMPOSE_LEN_MAX); + assert(tab_ce_len < COMPOSE_LEN_MAX); ce = &tab_ce[tab_ce_len++]; ce->c[0] = ci->decomp_data[0]; ce->c[1] = ci->decomp_data[1]; @@ -2856,16 +2831,6 @@ void build_compose_table(FILE *f, const DecompEntry *tab_de) } qsort(tab_ce, tab_ce_len, sizeof(*tab_ce), ce_cmp); -#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 - fprintf(f, "static const uint16_t unicode_comp_table[%u] = {", tab_ce_len); for(i = 0; i < tab_ce_len; i++) { @@ -2880,7 +2845,7 @@ void build_compose_table(FILE *f, const DecompEntry *tab_de) fprintf(f, " 0x%04x,", v); } fprintf(f, "\n};\n\n"); - + free(tab_ce); } @@ -2929,7 +2894,7 @@ void check_compose_table(void) } } } - + } @@ -2969,7 +2934,7 @@ void check_cc_table(void) #ifdef PROFILE { int64_t ti, count; - + ti = get_time_ns(); count = 0; /* only do it on meaningful chars */ @@ -2992,7 +2957,7 @@ void normalization_test(const char *filename) int *in_str, *nfc_str, *nfd_str, *nfkc_str, *nfkd_str; int in_len, nfc_len, nfd_len, nfkc_len, nfkd_len; int *buf, buf_len, pos; - + f = fopen(filename, "rb"); if (!f) { perror(filename); @@ -3023,7 +2988,7 @@ void normalization_test(const char *filename) buf_len = unicode_normalize((uint32_t **)&buf, (uint32_t *)in_str, in_len, UNICODE_NFKD, NULL, NULL); check_str("nfkd", pos, in_str, in_len, buf, buf_len, nfkd_str, nfkd_len); free(buf); - + buf_len = unicode_normalize((uint32_t **)&buf, (uint32_t *)in_str, in_len, UNICODE_NFC, NULL, NULL); check_str("nfc", pos, in_str, in_len, buf, buf_len, nfc_str, nfc_len); free(buf); @@ -3046,7 +3011,7 @@ 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" @@ -3067,13 +3032,13 @@ int main(int argc, char **argv) snprintf(filename, sizeof(filename), "%s/SpecialCasing.txt", unicode_db_path); parse_special_casing(unicode_db, filename); - + snprintf(filename, sizeof(filename), "%s/CaseFolding.txt", unicode_db_path); parse_case_folding(unicode_db, filename); snprintf(filename, sizeof(filename), "%s/CompositionExclusions.txt", unicode_db_path); parse_composition_exclusions(filename); - + snprintf(filename, sizeof(filename), "%s/DerivedCoreProperties.txt", unicode_db_path); parse_derived_core_properties(filename); @@ -3089,7 +3054,7 @@ int main(int argc, char **argv) snprintf(filename, sizeof(filename), "%s/ScriptExtensions.txt", unicode_db_path); parse_script_extensions(filename); - + snprintf(filename, sizeof(filename), "%s/emoji-data.txt", unicode_db_path); parse_prop_list(filename); @@ -3117,7 +3082,7 @@ int main(int argc, char **argv) } else { FILE *fo = fopen(outfilename, "wb"); - + if (!fo) { perror(outfilename); exit(1); @@ -3131,14 +3096,12 @@ 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); - fprintf(fo, "#endif /* CONFIG_ALL_UNICODE */\n"); fclose(fo); } return 0; diff --git a/unicode_gen_def.h b/unicode_gen_def.h index e7c2464..913d173 100644 --- a/unicode_gen_def.h +++ b/unicode_gen_def.h @@ -85,11 +85,13 @@ DEF(Ethiopic, "Ethi") DEF(Georgian, "Geor") DEF(Glagolitic, "Glag") DEF(Gothic, "Goth") +DEF(Garay, "Gara") DEF(Grantha, "Gran") DEF(Greek, "Grek") DEF(Gujarati, "Gujr") DEF(Gunjala_Gondi, "Gong") DEF(Gurmukhi, "Guru") +DEF(Gurung_Khema, "Gukh") DEF(Han, "Hani") DEF(Hangul, "Hang") DEF(Hanifi_Rohingya, "Rohg") @@ -112,6 +114,7 @@ DEF(Khmer, "Khmr") DEF(Khojki, "Khoj") DEF(Khitan_Small_Script, "Kits") DEF(Khudawadi, "Sind") +DEF(Kirat_Rai, "Krai") DEF(Lao, "Laoo") DEF(Latin, "Latn") DEF(Lepcha, "Lepc") @@ -149,6 +152,7 @@ DEF(Nushu, "Nshu") DEF(Nyiakeng_Puachue_Hmong, "Hmnp") DEF(Ogham, "Ogam") DEF(Ol_Chiki, "Olck") +DEF(Ol_Onal, "Onao") DEF(Old_Hungarian, "Hung") DEF(Old_Italic, "Ital") DEF(Old_North_Arabian, "Narb") @@ -180,6 +184,7 @@ DEF(Sogdian, "Sogd") DEF(Sora_Sompeng, "Sora") DEF(Soyombo, "Soyo") DEF(Sundanese, "Sund") +DEF(Sunuwar, "Sunu") DEF(Syloti_Nagri, "Sylo") DEF(Syriac, "Syrc") DEF(Tagalog, "Tglg") @@ -197,7 +202,9 @@ DEF(Tibetan, "Tibt") DEF(Tifinagh, "Tfng") DEF(Tirhuta, "Tirh") DEF(Tangsa, "Tnsa") +DEF(Todhri, "Todr") DEF(Toto, "Toto") +DEF(Tulu_Tigalari, "Tutg") DEF(Ugaritic, "Ugar") DEF(Vai, "Vaii") DEF(Vithkuqi, "Vith") @@ -236,11 +243,13 @@ DEF(Deprecated, "Dep") DEF(Diacritic, "Dia") DEF(Extender, "Ext") DEF(Hex_Digit, "Hex") +DEF(IDS_Unary_Operator, "IDSU") DEF(IDS_Binary_Operator, "IDSB") DEF(IDS_Trinary_Operator, "IDST") DEF(Ideographic, "Ideo") DEF(Join_Control, "Join_C") DEF(Logical_Order_Exception, "LOE") +DEF(Modifier_Combining_Mark, "MCM") DEF(Noncharacter_Code_Point, "NChar") DEF(Pattern_Syntax, "Pat_Syn") DEF(Pattern_White_Space, "Pat_WS") @@ -279,6 +288,8 @@ DEF(Changes_When_Uppercased, "CWU") DEF(Grapheme_Base, "Gr_Base") DEF(Grapheme_Extend, "Gr_Ext") DEF(ID_Continue, "IDC") +DEF(ID_Compat_Math_Start, "") +DEF(ID_Compat_Math_Continue, "") DEF(Lowercase, "Lower") DEF(Math, "") DEF(Uppercase, "Upper") @@ -288,4 +299,7 @@ DEF(XID_Start, "XIDS") /* internal tables with index */ DEF(Cased1, "") +/* unused by us */ +DEF(InCB, "") + #endif