From 839109b0c8c269e6a2b3d3cc68d7a6712980e8d5 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Sat, 15 Jun 2024 13:18:57 -0400 Subject: [PATCH 1/5] Squashed 'vendor/quickjs/' changes from 626e0d4e..36911f0d 36911f0d regexp: fix non greedy quantizers with zero length matches d86aaf0b updated test262.patch adec7343 fixed test of test262 directory d378a9f3 Improve `js_os_exec` (#295) 97be5a32 Add `js_resolve_proxy` (#293) f3f2f427 Add `JS_StrictEq()`, `JS_SameValue()`, and `JS_SameValueZero()` (#264) 6f9d05fd Expose `JS_SetUncatchableError()` (#262) d53aafe0 Add the missing fuzz_common.c (#292) db9dbd0a Add `JS_HasException()` (#265) 6c430131 Add `JS_NewTypedArray()` (#272) 01454caf OSS-Fuzz targets improvements (#267) 0c8fecab Improve class parser (#289) d9c699f5 fix class method with name get (#258) 7a2c6f42 Improve libunicode and libregexp headers (#288) 1402478d Improve unicode table handling (#286) 3b45d155 Fix endianness handling in `js_dataview_getValue` / `js_dataview_setValue` 653b2276 Improve error handling 203fe2d5 Improve `JSON.stringify` ce6b6dca Use more explicit magic values for array methods c0e67c47 Simplify redundant initializers for `JS_NewBool()` 06651314 Fix compilation with -DCONFIG_BIGNUM 65ecb0b0 Improve Date.parse, small fixes 6a89d7c2 Add CI targets, fix test_std.js (#247) ebe7496d Fix build: use LRE_BOOL in libunicode.h (#244) 1a5333bc prevent 0 length allocation in `js_worker_postMessage` e17cb9fc Add github CI tests 06c100c9 Prevent UB on memcpy and floating point conversions 3dd93eb4 fix microbench when microbench.txt is missing (#246) 35b7b3c3 Improve Date.parse 8d64731e Improve Number.prototype.toString for radix other than 10 a78d2cbf Improve repl regexp handling 8180d3dd Improve microbench.js 78db49cf Improve Date.parse 6428ce0c show readable representation of Date objects in repl 27928ce4 Fix Map hash bug b70e7644 Rewrite `set_date_fields` to match the ECMA specification b91a2aec Add C API function JS_GetClassID() 12c91df5 Improve surrogate handling readability 8d932deb Rename regex flag and field utf16 -> unicode 97ae6f39 Add benchmarks target c24a865a Improve run-test262 bbf36d5b Fix big endian serialization 530ba6a6 handle missing test262 gracefully 0a361b7c handle missing test262 gracefully 74bdb496 Improve tests 85fb2cae Fix UB signed integer overflow in js_math_imul 8df43275 Fix UB left shift of negative number 3bb2ca36 Remove unnecessary ssize_t posix-ism c06af876 Improve string concatenation hack 8e21b967 pass node-js command line arguments to microbench 95e0aa05 Reverse e140122202cc24728b394f8f90fa2f4a2d7c397e 1fe04149 Fix test262 error ef4e7b23 Fix compiler warnings 92e339d1 Simplify and clarify URL quoting js_std_urlGet 636c9465 FreeBSD QuickJS Patch (#203) ae6fa8d3 Fix shell injection bug in std.urlGet (#61) 693449e3 add gitignore for build objects (#84) e1401222 Fix sloppy mode arguments uninitialized value use 6dbf01bb Remove unsafe sprintf() and strcat() calls 65350645 Fix undefined behavior (UBSAN) e53d6223 Fix UB in js_dtoa1 fd6e0397 Add UndefinedBehaviorSanitizer support 325ca194 Add MemorySanitizer support git-subtree-dir: vendor/quickjs git-subtree-split: 36911f0d3ab1a4c190a4d5cbe7c2db225a455389 --- .github/workflows/ci.yml | 166 ++++ .gitignore | 6 + Makefile | 139 ++- VERSION | 2 +- compat/test-closefrom.c | 6 + cutils.c | 2 +- cutils.h | 55 +- fuzz/README | 27 + fuzz/fuzz.dict | 257 ++++++ fuzz/fuzz_common.c | 62 ++ fuzz/fuzz_common.h | 22 + fuzz/fuzz_compile.c | 93 ++ fuzz/fuzz_eval.c | 49 ++ fuzz/fuzz_regexp.c | 59 ++ fuzz/generate_dict.js | 24 + libbf.c | 4 +- libregexp.c | 304 +++---- libregexp.h | 46 +- libunicode-table.h | 161 +++- libunicode.c | 130 ++- libunicode.h | 103 ++- qjs.c | 2 + quickjs-libc.c | 74 +- quickjs.c | 1776 +++++++++++++++++++++++--------------- quickjs.h | 48 +- repl.js | 74 +- run-test262.c | 95 +- tests/microbench.js | 381 +++++--- tests/test262.patch | 34 +- tests/test_bigfloat.js | 279 ++++++ tests/test_bignum.js | 212 ----- tests/test_builtin.js | 207 ++++- tests/test_language.js | 20 +- tests/test_std.js | 9 +- unicode_gen.c | 180 ++-- 35 files changed, 3626 insertions(+), 1482 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 compat/test-closefrom.c create mode 100644 fuzz/README create mode 100644 fuzz/fuzz.dict create mode 100644 fuzz/fuzz_common.c create mode 100644 fuzz/fuzz_common.h create mode 100644 fuzz/fuzz_compile.c create mode 100644 fuzz/fuzz_eval.c create mode 100644 fuzz/fuzz_regexp.c create mode 100644 fuzz/generate_dict.js create mode 100644 tests/test_bigfloat.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9eab46fd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,166 @@ +name: ci + +on: + pull_request: + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!TODO' + - '!doc/**' + - '!examples/**' + - '.github/workflows/ci.yml' + push: + branches: + - '*' + +jobs: + linux: + name: Linux (Ubuntu) + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y + - name: Stats + run: | + ./qjs -qd + - name: Run built-in tests + run: | + make test + - name: Run microbench + run: | + make microbench + + linux-asan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y CONFIG_ASAN=y + - name: Run built-in tests + env: + ASAN_OPTIONS: halt_on_error=1 + run: | + make CONFIG_ASAN=y test + + linux-msan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Build + env: + CC: clang + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y CONFIG_MSAN=y CONFIG_CLANG=y + - name: Run built-in tests + env: + MSAN_OPTIONS: halt_on_error=1 + run: | + make CONFIG_MSAN=y CONFIG_CLANG=y test + + linux-ubsan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y CONFIG_UBSAN=y + - name: Run built-in tests + env: + UBSAN_OPTIONS: halt_on_error=1 + run: | + make CONFIG_UBSAN=y test + + macos: + name: macOS + runs-on: macos-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y + - name: Stats + run: | + ./qjs -qd + - name: Run built-in tests + run: | + make test + + macos-asan: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y CONFIG_ASAN=y + - name: Run built-in tests + env: + ASAN_OPTIONS: halt_on_error=1 + run: | + make CONFIG_ASAN=y test + + macos-ubsan: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: | + make -j$(getconf _NPROCESSORS_ONLN) CONFIG_WERROR=y CONFIG_UBSAN=y + - name: Run built-in tests + env: + UBSAN_OPTIONS: halt_on_error=1 + run: | + make CONFIG_UBSAN=y test + + freebsd: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + prepare: | + pkg install -y gmake + run: | + gmake + ./qjs -qd + gmake test + + qemu-alpine: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + platform: + - i386 + - arm32v6 + - arm32v7 + - arm64v8 + - s390x + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Get qemu + run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + - name: Run tests on ${{ matrix.platform }} + run: docker run --rm --interactive --mount type=bind,source=$(pwd),target=/host ${{ matrix.platform }}/alpine sh -c "apk add git patch make gcc libc-dev && cd /host && make test" + diff --git a/.gitignore b/.gitignore index c4ef1c71..5988f927 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ *.a .obj/ +tests/bjson.so +examples/test_fib +test_fib.c +examples/*.so examples/hello examples/hello_module hello.c @@ -16,3 +20,5 @@ test262o test262o_*.txt unicode unicode_gen +run_octane +run_sunspider_like diff --git a/Makefile b/Makefile index 7e62bea7..cf88a723 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,9 @@ ifeq ($(shell uname -s),Darwin) CONFIG_DARWIN=y endif +ifeq ($(shell uname -s),FreeBSD) +CONFIG_FREEBSD=y +endif # Windows cross compilation from Linux #CONFIG_WIN32=y # use link time optimization (smaller and faster executables but slower build) @@ -43,16 +46,37 @@ PREFIX?=/usr/local #CONFIG_PROFILE=y # use address sanitizer #CONFIG_ASAN=y -# include the code for BigFloat/BigDecimal, math mode and faster large integers +# use memory sanitizer +#CONFIG_MSAN=y +# use UB sanitizer +#CONFIG_UBSAN=y + +# include the code for BigFloat/BigDecimal and math mode CONFIG_BIGNUM=y OBJDIR=.obj +ifdef CONFIG_ASAN +OBJDIR:=$(OBJDIR)/asan +endif +ifdef CONFIG_MSAN +OBJDIR:=$(OBJDIR)/msan +endif +ifdef CONFIG_UBSAN +OBJDIR:=$(OBJDIR)/ubsan +endif + ifdef CONFIG_DARWIN # use clang instead of gcc CONFIG_CLANG=y CONFIG_DEFAULT_AR=y endif +ifdef CONFIG_FREEBSD +# use clang instead of gcc +CONFIG_CLANG=y +CONFIG_DEFAULT_AR=y +CONFIG_LTO= +endif ifdef CONFIG_WIN32 ifdef CONFIG_M32 @@ -87,6 +111,7 @@ ifdef CONFIG_CLANG AR=$(CROSS_PREFIX)ar endif endif + LIB_FUZZING_ENGINE ?= "-fsanitize=fuzzer" else ifdef CONFIG_COSMO CONFIG_LTO= HOST_CC=gcc @@ -118,6 +143,11 @@ endif ifdef CONFIG_WIN32 DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior endif +ifndef CONFIG_WIN32 +ifeq ($(shell $(CC) -o /dev/null compat/test-closefrom.c 2>/dev/null && echo 1),1) +DEFINES+=-DHAVE_CLOSEFROM +endif +endif CFLAGS+=$(DEFINES) CFLAGS_DEBUG=$(CFLAGS) -O0 @@ -142,6 +172,14 @@ ifdef CONFIG_ASAN CFLAGS+=-fsanitize=address -fno-omit-frame-pointer LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer endif +ifdef CONFIG_MSAN +CFLAGS+=-fsanitize=memory -fno-omit-frame-pointer +LDFLAGS+=-fsanitize=memory -fno-omit-frame-pointer +endif +ifdef CONFIG_UBSAN +CFLAGS+=-fsanitize=undefined -fno-omit-frame-pointer +LDFLAGS+=-fsanitize=undefined -fno-omit-frame-pointer +endif ifdef CONFIG_WIN32 LDEXPORT= else @@ -176,12 +214,15 @@ endif # examples ifeq ($(CROSS_PREFIX),) -PROGS+=examples/hello ifndef CONFIG_ASAN -PROGS+=examples/hello_module -endif +ifndef CONFIG_MSAN +ifndef CONFIG_UBSAN +PROGS+=examples/hello examples/hello_module examples/test_fib ifdef CONFIG_SHARED_LIBS -PROGS+=examples/test_fib examples/fib.so examples/point.so +PROGS+=examples/fib.so examples/point.so +endif +endif +endif endif endif @@ -213,6 +254,17 @@ qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS)) qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +fuzz_eval: $(OBJDIR)/fuzz_eval.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a + $(CC) $(CFLAGS_OPT) $^ -o fuzz_eval $(LIB_FUZZING_ENGINE) + +fuzz_compile: $(OBJDIR)/fuzz_compile.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a + $(CC) $(CFLAGS_OPT) $^ -o fuzz_compile $(LIB_FUZZING_ENGINE) + +fuzz_regexp: $(OBJDIR)/fuzz_regexp.o $(OBJDIR)/libregexp.fuzz.o $(OBJDIR)/cutils.fuzz.o $(OBJDIR)/libunicode.fuzz.o + $(CC) $(CFLAGS_OPT) $^ -o fuzz_regexp $(LIB_FUZZING_ENGINE) + +libfuzzer: fuzz_eval fuzz_compile fuzz_regexp + ifneq ($(CROSS_PREFIX),) $(QJSC): $(OBJDIR)/qjsc.host.o \ @@ -254,6 +306,9 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS)) $(AR) rcs $@ $^ endif # CONFIG_LTO +libquickjs.fuzz.a: $(patsubst %.o, %.fuzz.o, $(QJS_LIB_OBJS)) + $(AR) rcs $@ $^ + repl.c: $(QJSC) repl.js $(QJSC) -c -o $@ -m repl.js @@ -282,6 +337,9 @@ run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS) $(OBJDIR)/%.o: %.c | $(OBJDIR) $(CC) $(CFLAGS_OPT) -c -o $@ $< +$(OBJDIR)/fuzz_%.o: fuzz/fuzz_%.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -c -I. -o $@ $< + $(OBJDIR)/%.host.o: %.c | $(OBJDIR) $(HOST_CC) $(CFLAGS_OPT) -c -o $@ $< @@ -300,6 +358,9 @@ $(OBJDIR)/%.m32s.o: %.c | $(OBJDIR) $(OBJDIR)/%.debug.o: %.c | $(OBJDIR) $(CC) $(CFLAGS_DEBUG) -c -o $@ $< +$(OBJDIR)/%.fuzz.o: %.c | $(OBJDIR) + $(CC) $(CFLAGS_OPT) -fsanitize=fuzzer-no-link -c -o $@ $< + $(OBJDIR)/%.check.o: %.c | $(OBJDIR) $(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $< @@ -311,11 +372,12 @@ unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c u clean: rm -f repl.c qjscalc.c out.c - rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS) + rm -f *.a *.o *.d *~ unicode_gen regexp_test fuzz_eval fuzz_compile fuzz_regexp $(PROGS) rm -f hello.c test_fib.c rm -f examples/*.so tests/*.so rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug rm -rf run-test262-debug run-test262-32 + rm -f run_octane run_sunspider_like install: all mkdir -p "$(DESTDIR)$(PREFIX)/bin" @@ -404,8 +466,9 @@ endif test: qjs ./qjs tests/test_closure.js ./qjs tests/test_language.js - ./qjs tests/test_builtin.js + ./qjs --std tests/test_builtin.js ./qjs tests/test_loop.js + ./qjs tests/test_bignum.js ./qjs tests/test_std.js ./qjs tests/test_worker.js ifdef CONFIG_SHARED_LIBS @@ -418,19 +481,20 @@ endif endif ifdef CONFIG_BIGNUM ./qjs --bignum tests/test_op_overloading.js - ./qjs --bignum tests/test_bignum.js + ./qjs --bignum tests/test_bigfloat.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 --std tests/test_builtin.js ./qjs32 tests/test_loop.js + ./qjs32 tests/test_bignum.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 --bignum tests/test_bigfloat.js ./qjs32 --qjscalc tests/test_qjscalc.js endif endif @@ -445,31 +509,41 @@ microbench: qjs microbench-32: qjs32 ./qjs32 --std tests/microbench.js +ifeq ($(wildcard test262o/tests.txt),) +test2o test2o-32 test2o-update: + @echo test262o tests not installed +else # ES5 tests (obsolete) test2o: run-test262 - time ./run-test262 -m -c test262o.conf + time ./run-test262 -t -m -c test262o.conf test2o-32: run-test262-32 - time ./run-test262-32 -m -c test262o.conf + time ./run-test262-32 -t -m -c test262o.conf test2o-update: run-test262 - ./run-test262 -u -c test262o.conf + ./run-test262 -t -u -c test262o.conf +endif +ifeq ($(wildcard test262/features.txt),) +test2 test2-32 test2-update test2-default test2-check: + @echo test262 tests not installed +else # Test262 tests test2-default: run-test262 - time ./run-test262 -m -c test262.conf + time ./run-test262 -t -m -c test262.conf test2: run-test262 - time ./run-test262 -m -c test262.conf -a + time ./run-test262 -t -m -c test262.conf -a test2-32: run-test262-32 - time ./run-test262-32 -m -c test262.conf -a + time ./run-test262-32 -t -m -c test262.conf -a test2-update: run-test262 - ./run-test262 -u -c test262.conf -a + ./run-test262 -t -u -c test262.conf -a test2-check: run-test262 - time ./run-test262 -m -c test262.conf -E -a + time ./run-test262 -t -m -c test262.conf -E -a +endif testall: all test microbench test2o test2 @@ -477,11 +551,40 @@ testall-32: all test-32 microbench-32 test2o-32 test2-32 testall-complete: testall testall-32 +node-test: + node tests/test_closure.js + node tests/test_language.js + node tests/test_builtin.js + node tests/test_loop.js + node tests/test_bignum.js + +node-microbench: + node tests/microbench.js -s microbench-node.txt + node --jitless tests/microbench.js -s microbench-node-jitless.txt + bench-v8: qjs make -C tests/bench-v8 ./qjs -d tests/bench-v8/combined.js +node-bench-v8: + make -C tests/bench-v8 + node --jitless tests/bench-v8/combined.js + tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) +BENCHMARKDIR=../quickjs-benchmarks + +run_sunspider_like: $(BENCHMARKDIR)/run_sunspider_like.c + $(CC) $(CFLAGS) $(LDFLAGS) -DNO_INCLUDE_DIR -I. -o $@ $< libquickjs$(LTOEXT).a $(LIBS) + +run_octane: $(BENCHMARKDIR)/run_octane.c + $(CC) $(CFLAGS) $(LDFLAGS) -DNO_INCLUDE_DIR -I. -o $@ $< libquickjs$(LTOEXT).a $(LIBS) + +benchmarks: run_sunspider_like run_octane + ./run_sunspider_like $(BENCHMARKDIR)/kraken-1.0/ + ./run_sunspider_like $(BENCHMARKDIR)/kraken-1.1/ + ./run_sunspider_like $(BENCHMARKDIR)/sunspider-1.0/ + ./run_octane $(BENCHMARKDIR)/ + -include $(wildcard $(OBJDIR)/*.d) diff --git a/VERSION b/VERSION index e89de35f..e32e065c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2024-01-13 +2024-02-14 diff --git a/compat/test-closefrom.c b/compat/test-closefrom.c new file mode 100644 index 00000000..1324e97b --- /dev/null +++ b/compat/test-closefrom.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + closefrom(3); + return 0; +} diff --git a/cutils.c b/cutils.c index b4960f9c..c0aacef6 100644 --- a/cutils.c +++ b/cutils.c @@ -140,7 +140,7 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) if (dbuf_realloc(s, s->size + len)) return -1; } - memcpy(s->buf + s->size, data, len); + memcpy_no_ub(s->buf + s->size, data, len); s->size += len; return 0; } diff --git a/cutils.h b/cutils.h index a9077f54..f079e5c5 100644 --- a/cutils.h +++ b/cutils.h @@ -26,11 +26,9 @@ #define CUTILS_H #include +#include #include -/* set if CPU is big endian */ -#undef WORDS_BIGENDIAN - #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define force_inline inline __attribute__((always_inline)) @@ -48,9 +46,16 @@ #ifndef countof #define countof(x) (sizeof(x) / sizeof((x)[0])) #endif - +#ifndef container_of /* return the pointer of type 'type *' containing 'ptr' as field 'member' */ #define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member))) +#endif + +#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define minimum_length(n) static n +#else +#define minimum_length(n) n +#endif typedef int BOOL; @@ -66,6 +71,12 @@ 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); +/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */ +static inline void memcpy_no_ub(void *dest, const void *src, size_t n) { + if (n) + memcpy(dest, src, n); +} + static inline int max_int(int a, int b) { if (a > b) @@ -210,17 +221,22 @@ 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)) | @@ -232,6 +248,7 @@ static inline uint64_t bswap64(uint64_t v) ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8)); } +#endif /* XXX: should take an extra argument to pass slack information to the caller */ typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); @@ -281,6 +298,36 @@ static inline void dbuf_set_error(DynBuf *s) 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); +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 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00); +} + static inline int from_hex(int c) { if (c >= '0' && c <= '9') diff --git a/fuzz/README b/fuzz/README new file mode 100644 index 00000000..18c71cd3 --- /dev/null +++ b/fuzz/README @@ -0,0 +1,27 @@ +libFuzzer support for QuickJS +============================= + +Build QuickJS with libFuzzer support as follows: + + CONFIG_CLANG=y make libfuzzer + +This can be extended with sanitizer support to improve efficacy: + + CONFIG_CLANG=y CONFIG_ASAN=y make libfuzzer + + +Currently, there are three fuzzing targets defined: fuzz_eval, fuzz_compile and fuzz_regexp. +The above build command will produce an executable binary for each of them, which can be +simply executed as: + + ./fuzz_eval + +or with an initial corpus: + + ./fuzz_compile corpus_dir/ + +or with a predefined dictionary to improve its efficacy: + + ./fuzz_eval -dict fuzz/fuzz.dict + +or with arbitrary CLI arguments provided by libFuzzer (https://llvm.org/docs/LibFuzzer.html). diff --git a/fuzz/fuzz.dict b/fuzz/fuzz.dict new file mode 100644 index 00000000..a5010e4d --- /dev/null +++ b/fuzz/fuzz.dict @@ -0,0 +1,257 @@ +"__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 new file mode 100644 index 00000000..9f1662dd --- /dev/null +++ b/fuzz/fuzz_common.c @@ -0,0 +1,62 @@ +/* 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 new file mode 100644 index 00000000..10cb4976 --- /dev/null +++ b/fuzz/fuzz_common.h @@ -0,0 +1,22 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" + +static int nbinterrupts = 0; + +void reset_nbinterrupts(); +void test_one_input_init(JSRuntime *rt, JSContext *ctx); diff --git a/fuzz/fuzz_compile.c b/fuzz/fuzz_compile.c new file mode 100644 index 00000000..0ab1b033 --- /dev/null +++ b/fuzz/fuzz_compile.c @@ -0,0 +1,93 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" +#include "cutils.h" +#include "fuzz/fuzz_common.h" + +#include +#include + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size == 0) + return 0; + + JSRuntime *rt = JS_NewRuntime(); + JSContext *ctx = JS_NewContext(rt); + test_one_input_init(rt, ctx); + + uint8_t *null_terminated_data = malloc(size + 1); + memcpy(null_terminated_data, data, size); + null_terminated_data[size] = 0; + + JSValue obj = JS_Eval(ctx, (const char *)null_terminated_data, size, "", JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_MODULE); + free(null_terminated_data); + //TODO target with JS_ParseJSON + if (JS_IsException(obj)) { + js_std_free_handlers(rt); + JS_FreeValue(ctx, obj); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + obj = js_std_await(ctx, obj); + size_t bytecode_size; + uint8_t* bytecode = JS_WriteObject(ctx, &bytecode_size, obj, JS_WRITE_OBJ_BYTECODE); + JS_FreeValue(ctx, obj); + if (!bytecode) { + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + obj = JS_ReadObject(ctx, bytecode, bytecode_size, JS_READ_OBJ_BYTECODE); + js_free(ctx, bytecode); + if (JS_IsException(obj)) { + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + reset_nbinterrupts(); + /* this is based on + * js_std_eval_binary(ctx, bytecode, bytecode_size, 0); + * modified so as not to exit on JS exception + */ + JSValue val; + if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { + if (JS_ResolveModule(ctx, obj) < 0) { + JS_FreeValue(ctx, obj); + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + } + js_module_set_import_meta(ctx, obj, FALSE, TRUE); + } + val = JS_EvalFunction(ctx, obj); + if (JS_IsException(val)) { + js_std_dump_error(ctx); + } else { + js_std_loop(ctx); + } + JS_FreeValue(ctx, val); + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + return 0; +} diff --git a/fuzz/fuzz_eval.c b/fuzz/fuzz_eval.c new file mode 100644 index 00000000..aa26f1ef --- /dev/null +++ b/fuzz/fuzz_eval.c @@ -0,0 +1,49 @@ +/* Copyright 2020 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "quickjs.h" +#include "quickjs-libc.h" +#include "fuzz/fuzz_common.h" + +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size == 0) + return 0; + + JSRuntime *rt = JS_NewRuntime(); + JSContext *ctx = JS_NewContext(rt); + test_one_input_init(rt, ctx); + + uint8_t *null_terminated_data = malloc(size + 1); + memcpy(null_terminated_data, data, size); + null_terminated_data[size] = 0; + + reset_nbinterrupts(); + //the final 0 does not count (as in strlen) + JSValue val = JS_Eval(ctx, (const char *)null_terminated_data, size, "", JS_EVAL_TYPE_GLOBAL); + free(null_terminated_data); + //TODO targets with JS_ParseJSON, JS_ReadObject + if (!JS_IsException(val)) { + js_std_loop(ctx); + JS_FreeValue(ctx, val); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; +} diff --git a/fuzz/fuzz_regexp.c b/fuzz/fuzz_regexp.c new file mode 100644 index 00000000..29d19512 --- /dev/null +++ b/fuzz/fuzz_regexp.c @@ -0,0 +1,59 @@ +/* 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 new file mode 100644 index 00000000..1366fea1 --- /dev/null +++ b/fuzz/generate_dict.js @@ -0,0 +1,24 @@ +// Function to recursively iterate through built-in names. +function collectBuiltinNames(obj, visited = new Set(), result = new Set()) { + // Check if the object has already been visited to avoid infinite recursion. + if (visited.has(obj)) + return; + + // Add the current object to the set of visited objects + visited.add(obj); + // Get the property names of the current object + const properties = Object.getOwnPropertyNames(obj); + // Iterate through each property + for (var i=0; i < properties.length; i++) { + var property = properties[i]; + if (property != "collectBuiltinNames" && typeof property != "number") + result.add(property); + // Check if the property is an object and if so, recursively iterate through its properties. + if (typeof obj[property] === 'object' && obj[property] !== null) + collectBuiltinNames(obj[property], visited, result); + } + return result; +} + +// Start the recursive iteration with the global object. +console.log(Array.from(collectBuiltinNames(this)).join('\n')); diff --git a/libbf.c b/libbf.c index b3ed2094..05d62ed6 100644 --- a/libbf.c +++ b/libbf.c @@ -136,6 +136,7 @@ static inline slimb_t ceil_div(slimb_t a, slimb_t b) return a / b; } +#ifdef USE_BF_DEC /* b must be >= 1 */ static inline slimb_t floor_div(slimb_t a, slimb_t b) { @@ -145,6 +146,7 @@ static inline slimb_t floor_div(slimb_t a, slimb_t b) return (a - b + 1) / b; } } +#endif /* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */ static inline limb_t smod(slimb_t a, slimb_t b) @@ -309,7 +311,7 @@ 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)); + memcpy_no_ub(r->tab, a->tab, a->len * sizeof(limb_t)); return 0; } diff --git a/libregexp.c b/libregexp.c index 982d171b..a2d56a7d 100644 --- a/libregexp.c +++ b/libregexp.c @@ -30,6 +30,7 @@ #include "cutils.h" #include "libregexp.h" +#include "libunicode.h" /* TODO: @@ -66,7 +67,7 @@ typedef struct { const uint8_t *buf_end; const uint8_t *buf_start; int re_flags; - BOOL is_utf16; + BOOL is_unicode; BOOL ignore_case; BOOL dotall; int capture_count; @@ -100,6 +101,7 @@ 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_BYTECODE_LEN 3 #define RE_HEADER_LEN 7 @@ -140,32 +142,6 @@ static const uint16_t char_range_s[] = { 0xFEFF, 0xFEFF + 1, }; -BOOL lre_is_space(int c) -{ - int i, n, low, high; - n = (countof(char_range_s) - 1) / 2; - for(i = 0; i < n; i++) { - low = char_range_s[2 * i + 1]; - if (c < low) - return FALSE; - high = char_range_s[2 * i + 2]; - if (c < high) - return TRUE; - } - return FALSE; -} - -uint32_t const lre_id_start_table_ascii[4] = { - /* $ A-Z _ a-z */ - 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE -}; - -uint32_t const lre_id_continue_table_ascii[4] = { - /* $ 0-9 A-Z _ a-z */ - 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE -}; - - static const uint16_t char_range_w[] = { 4, 0x0030, 0x0039 + 1, @@ -185,7 +161,7 @@ typedef enum { CHAR_RANGE_W, } CharRangeEnum; -static const uint16_t *char_range_table[] = { +static const uint16_t * const char_range_table[] = { char_range_d, char_range_s, char_range_w, @@ -224,16 +200,16 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, 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); @@ -494,7 +470,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 +481,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); } } } @@ -696,10 +672,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' */ @@ -710,7 +686,7 @@ static int get_class_atom(REParseState *s, CharRange *cr, #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; @@ -720,14 +696,14 @@ static int get_class_atom(REParseState *s, CharRange *cr, #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) { invalid_escape: return re_parse_error(s, "invalid escape sequence in regular expression"); } else { @@ -749,7 +725,7 @@ static int get_class_atom(REParseState *s, CharRange *cr, /* normal char */ if (c >= 128) { c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); - if ((unsigned)c > 0xffff && !s->is_utf16) { + if ((unsigned)c > 0xffff && !s->is_unicode) { /* XXX: should handle non BMP-1 code points */ return re_parse_error(s, "malformed unicode char"); } @@ -811,11 +787,13 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) cr_init(cr, s->opaque, lre_realloc); p = *pp; p++; /* skip '[' */ + invert = FALSE; if (*p == '^') { p++; invert = TRUE; } + for(;;) { if (*p == ']') break; @@ -825,7 +803,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) 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 +815,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 +844,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) { @@ -934,7 +912,7 @@ static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) case REOP_backward_back_reference: break; default: - /* safe behvior: we cannot predict the outcome */ + /* safe behavior: we cannot predict the outcome */ return TRUE; } pos += len; @@ -1003,10 +981,10 @@ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) break; } else if (c >= 128) { c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); - if (c >= 0xD800 && c <= 0xDBFF) { + if (is_hi_surrogate(c)) { d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); - if (d >= 0xDC00 && d <= 0xDFFF) { - c = 0x10000 + 0x400 * (c - 0xD800) + (d - 0xDC00); + if (is_lo_surrogate(d)) { + c = from_surrogate(c, d); p = p1; } } @@ -1114,9 +1092,10 @@ static int find_group_name(REParseState *s, const char *name) 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); @@ -1161,7 +1140,7 @@ 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])) { /* Annex B: we accept '{' not followed by digits as a @@ -1213,7 +1192,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; } @@ -1289,7 +1268,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) /* 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 +1276,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 +1287,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,7 +1299,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) case '0': p += 2; c = 0; - if (s->is_utf16) { + if (s->is_unicode) { if (is_digit(*p)) { return re_parse_error(s, "invalid decimal escape in regular expression"); } @@ -1342,7 +1321,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) 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 +1363,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,7 +1385,7 @@ 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); + c = lre_canonicalize(c, s->is_unicode); if (c <= 0xffff) re_emit_op_u16(s, REOP_char, c); else @@ -1442,7 +1421,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) /* 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 (s->is_unicode) goto invalid_quant_count; break; } @@ -1461,7 +1440,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; @@ -1509,15 +1488,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) 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; @@ -1753,7 +1730,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, s->buf_end = s->buf_ptr + buf_len; s->buf_start = s->buf_ptr; s->re_flags = re_flags; - s->is_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); @@ -1811,7 +1788,8 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, 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)) { @@ -1842,93 +1820,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) && cbuf_type == 2) { \ + if (_p < _end && 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; \ +#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) && cbuf_type == 2) { \ + if (_p < _end && is_lo_surrogate(*_p)) { \ + c = from_surrogate(c, *_p); \ } \ } \ - } \ + } \ } 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_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) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ } \ } \ } \ } 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 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) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ } \ } \ + cptr = (const void *)_p; \ } \ } 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 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) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + --_p; \ } \ } \ + cptr = (const void *)_p; \ } \ } while (0) @@ -1959,7 +1930,7 @@ typedef struct { 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; @@ -2068,7 +2039,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; @@ -2103,9 +2074,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, 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; @@ -2150,7 +2121,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 +2130,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 +2196,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)) @@ -2257,11 +2228,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 +2242,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; @@ -2292,9 +2263,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, 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); @@ -2332,9 +2303,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, 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 +2335,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: { @@ -2423,16 +2394,16 @@ int lre_exec(uint8_t **capture, 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; @@ -2470,8 +2441,8 @@ 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); } #ifdef TEST @@ -2488,25 +2459,26 @@ 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]); - exit(1); + if (argc < 4) { + printf("usage: %s regexp flags input\n", argv[0]); + return 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); diff --git a/libregexp.h b/libregexp.h index 7c03b1ad..7af7ece0 100644 --- a/libregexp.h +++ b/libregexp.h @@ -25,19 +25,15 @@ #define LIBREGEXP_H #include - -#include "libunicode.h" - -#define LRE_BOOL int /* for documentation purposes */ +#include #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 */ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, @@ -51,43 +47,9 @@ int lre_exec(uint8_t **capture, int cbuf_type, void *opaque); int lre_parse_escape(const uint8_t **pp, int allow_utf16); -LRE_BOOL lre_is_space(int c); -/* must be provided by the user */ -LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); +/* must be provided by the user, return non zero if overflow */ +int lre_check_stack_overflow(void *opaque, size_t alloca_size); void *lre_realloc(void *opaque, void *ptr, size_t size); -/* JS identifier test */ -extern uint32_t const lre_id_start_table_ascii[4]; -extern uint32_t const lre_id_continue_table_ascii[4]; - -static inline int lre_js_is_ident_first(int c) -{ - if ((uint32_t)c < 128) { - return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; - } else { -#ifdef CONFIG_ALL_UNICODE - return lre_is_id_start(c); -#else - return !lre_is_space(c); -#endif - } -} - -static inline int lre_js_is_ident_next(int c) -{ - if ((uint32_t)c < 128) { - return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; - } else { - /* ZWNJ and ZWJ are accepted in identifiers */ -#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 - #endif /* LIBREGEXP_H */ diff --git a/libunicode-table.h b/libunicode-table.h index 513ed94b..72d495e7 100644 --- a/libunicode-table.h +++ b/libunicode-table.h @@ -189,9 +189,13 @@ static const uint8_t unicode_prop_Cased1_table[196] = { }; 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, + 0xb9, 0x02, 0xe0, // 002B9 at 39 + 0xc0, 0x1d, 0x20, // 01DC0 at 65 + 0xe5, 0x2c, 0x20, // 02CE5 at 97 + 0xb1, 0x07, 0x21, // 107B1 at 129 + 0xc1, 0xd6, 0x21, // 1D6C1 at 161 + 0x4a, 0xf1, 0x01, // 1F14A at 192 + 0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound) }; static const uint8_t unicode_prop_Case_Ignorable_table[737] = { @@ -291,15 +295,29 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = { }; static const uint8_t unicode_prop_Case_Ignorable_index[69] = { - 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, + 0xbe, 0x05, 0x00, // 005BE at 32 + 0xfe, 0x07, 0x00, // 007FE at 64 + 0x52, 0x0a, 0xa0, // 00A52 at 101 + 0xc1, 0x0b, 0x00, // 00BC1 at 128 + 0x82, 0x0d, 0x00, // 00D82 at 160 + 0x3f, 0x10, 0x80, // 0103F at 196 + 0xd4, 0x17, 0x40, // 017D4 at 226 + 0xcf, 0x1a, 0x20, // 01ACF at 257 + 0xf5, 0x1c, 0x00, // 01CF5 at 288 + 0x80, 0x20, 0x00, // 02080 at 320 + 0x16, 0xa0, 0x00, // 0A016 at 352 + 0xc6, 0xa8, 0x00, // 0A8C6 at 384 + 0xc2, 0xaa, 0x60, // 0AAC2 at 419 + 0x56, 0xfe, 0x20, // 0FE56 at 449 + 0xb1, 0x07, 0x01, // 107B1 at 480 + 0x75, 0x10, 0x01, // 11075 at 512 + 0xeb, 0x12, 0x21, // 112EB at 545 + 0x41, 0x16, 0x01, // 11641 at 576 + 0x5c, 0x1a, 0x01, // 11A5C at 608 + 0x43, 0x1f, 0x01, // 11F43 at 640 + 0x2e, 0xcf, 0x41, // 1CF2E at 674 + 0x25, 0xe0, 0x01, // 1E025 at 704 + 0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound) }; static const uint8_t unicode_prop_ID_Start_table[1100] = { @@ -444,20 +462,41 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = { }; static const uint8_t unicode_prop_ID_Start_index[105] = { - 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, - 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, + 0xf6, 0x03, 0x20, // 003F6 at 33 + 0xa6, 0x07, 0x00, // 007A6 at 64 + 0xa9, 0x09, 0x20, // 009A9 at 97 + 0xb1, 0x0a, 0x00, // 00AB1 at 128 + 0xba, 0x0b, 0x20, // 00BBA at 161 + 0x3b, 0x0d, 0x20, // 00D3B at 193 + 0xc7, 0x0e, 0x20, // 00EC7 at 225 + 0x49, 0x12, 0x00, // 01249 at 256 + 0x9b, 0x16, 0x00, // 0169B at 288 + 0xac, 0x19, 0x00, // 019AC at 320 + 0xc0, 0x1d, 0x80, // 01DC0 at 356 + 0x80, 0x20, 0x20, // 02080 at 385 + 0x70, 0x2d, 0x00, // 02D70 at 416 + 0x00, 0x32, 0x00, // 03200 at 448 + 0xda, 0xa7, 0x00, // 0A7DA at 480 + 0x4c, 0xaa, 0x20, // 0AA4C at 513 + 0xc7, 0xd7, 0x20, // 0D7C7 at 545 + 0xfc, 0xfd, 0x20, // 0FDFC at 577 + 0x9d, 0x02, 0x21, // 1029D at 609 + 0x96, 0x05, 0x01, // 10596 at 640 + 0xf3, 0x08, 0x01, // 108F3 at 672 + 0xb3, 0x0c, 0x21, // 10CB3 at 705 + 0x73, 0x11, 0x61, // 11173 at 739 + 0x34, 0x13, 0x01, // 11334 at 768 + 0x1b, 0x17, 0x21, // 1171B at 801 + 0x8a, 0x1a, 0x01, // 11A8A at 832 + 0x34, 0x1f, 0x21, // 11F34 at 865 + 0xbf, 0x6a, 0x01, // 16ABF at 896 + 0x23, 0xb1, 0xa1, // 1B123 at 933 + 0xad, 0xd4, 0x01, // 1D4AD at 960 + 0x6f, 0xd7, 0x01, // 1D76F at 992 + 0xff, 0xe7, 0x61, // 1E7FF at 1027 + 0x5e, 0xee, 0x01, // 1EE5E at 1056 + 0xe1, 0xeb, 0x22, // 2EBE1 at 1089 + 0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound) }; static const uint8_t unicode_prop_ID_Continue1_table[660] = { @@ -547,14 +586,27 @@ static const uint8_t unicode_prop_ID_Continue1_table[660] = { }; static const uint8_t unicode_prop_ID_Continue1_index[63] = { - 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, + 0xfa, 0x06, 0x00, // 006FA at 32 + 0x70, 0x09, 0x00, // 00970 at 64 + 0xf0, 0x0a, 0x40, // 00AF0 at 98 + 0x57, 0x0c, 0x00, // 00C57 at 128 + 0xf0, 0x0d, 0x60, // 00DF0 at 163 + 0xc7, 0x0f, 0x20, // 00FC7 at 193 + 0xea, 0x17, 0x40, // 017EA at 226 + 0x05, 0x1b, 0x00, // 01B05 at 256 + 0x41, 0x20, 0x00, // 02041 at 288 + 0x0c, 0xa8, 0x80, // 0A80C at 324 + 0x37, 0xaa, 0x20, // 0AA37 at 353 + 0x50, 0xfe, 0x20, // 0FE50 at 385 + 0x3a, 0x0d, 0x21, // 10D3A at 417 + 0x74, 0x11, 0x01, // 11174 at 448 + 0x5a, 0x14, 0x21, // 1145A at 481 + 0x44, 0x19, 0x81, // 11944 at 516 + 0x5a, 0x1d, 0xa1, // 11D5A at 549 + 0xf5, 0x6a, 0x21, // 16AF5 at 577 + 0x45, 0xd2, 0x41, // 1D245 at 610 + 0xaf, 0xe2, 0x21, // 1E2AF at 641 + 0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound) }; #ifdef CONFIG_ALL_UNICODE @@ -676,17 +728,35 @@ static const uint8_t unicode_cc_table[899] = { }; static const uint8_t unicode_cc_index[87] = { - 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05, - 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c, - 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00, - 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10, - 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3, - 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00, - 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab, - 0x00, 0x39, 0x0a, 0x01, 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, + 0x4d, 0x03, 0x00, // 0034D at 32 + 0x97, 0x05, 0x20, // 00597 at 65 + 0xc6, 0x05, 0x00, // 005C6 at 96 + 0xe7, 0x06, 0x00, // 006E7 at 128 + 0x45, 0x07, 0x00, // 00745 at 160 + 0x9c, 0x08, 0x00, // 0089C at 192 + 0x4d, 0x09, 0x00, // 0094D at 224 + 0x3c, 0x0b, 0x00, // 00B3C at 256 + 0x3d, 0x0d, 0x00, // 00D3D at 288 + 0x36, 0x0f, 0x00, // 00F36 at 320 + 0x38, 0x10, 0x20, // 01038 at 353 + 0x3a, 0x19, 0x00, // 0193A at 384 + 0xcb, 0x1a, 0x20, // 01ACB at 417 + 0xd3, 0x1c, 0x00, // 01CD3 at 448 + 0xcf, 0x1d, 0x00, // 01DCF at 480 + 0xe2, 0x20, 0x00, // 020E2 at 512 + 0x2e, 0x30, 0x20, // 0302E at 545 + 0x2b, 0xa9, 0x20, // 0A92B at 577 + 0xed, 0xab, 0x00, // 0ABED at 608 + 0x39, 0x0a, 0x01, // 10A39 at 640 + 0x51, 0x0f, 0x01, // 10F51 at 672 + 0x73, 0x11, 0x01, // 11173 at 704 + 0x75, 0x13, 0x01, // 11375 at 736 + 0x2b, 0x17, 0x21, // 1172B at 769 + 0x3f, 0x1c, 0x21, // 11C3F at 801 + 0x9e, 0xbc, 0x21, // 1BC9E at 833 + 0x08, 0xe0, 0x01, // 1E008 at 864 + 0x44, 0xe9, 0x01, // 1E944 at 896 + 0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound) }; static const uint32_t unicode_decomp_table1[699] = { @@ -4484,3 +4554,4 @@ static const uint16_t unicode_prop_len_table[] = { }; #endif /* CONFIG_ALL_UNICODE */ +/* 62 tables / 32261 bytes, 5 index / 345 bytes */ diff --git a/libunicode.c b/libunicode.c index 4200252d..c80d2f3d 100644 --- a/libunicode.c +++ b/libunicode.c @@ -262,11 +262,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 @@ -317,6 +313,14 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table, return FALSE; /* outside the table */ p = table + pos; bit = 0; + /* Compressed run length encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ for(;;) { b = *p++; if (b < 64) { @@ -833,6 +837,13 @@ static int unicode_get_cc(uint32_t c) if (pos < 0) return 0; p = unicode_cc_table + pos; + /* Compressed run length encoding: + - 2 high order bits are combining class type + - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte + - 00..2F: range length (add 1) + - 30..37: 3-bit range-length + 1 extra byte + - 38..3F: 3-bit range-length + 2 extra byte + */ for(;;) { b = *p++; type = b >> 6; @@ -1185,6 +1196,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask) p = unicode_gc_table; p_end = unicode_gc_table + countof(unicode_gc_table); c = 0; + /* Compressed range encoding: + initial byte: + bits 0..4: category number (special case 31) + bits 5..7: range length (add 1) + special case bits 5..7 == 7: read an extra byte + - 00..7F: range length (add 7 + 1) + - 80..BF: 6-bits plus extra byte for range length (add 7 + 128) + - C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384) + */ while (p < p_end) { b = *p++; n = b >> 5; @@ -1238,6 +1258,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx) p_end = p + unicode_prop_len_table[prop_idx]; c = 0; bit = 0; + /* Compressed range encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ while (p < p_end) { c0 = c; b = *p++; @@ -1786,3 +1814,97 @@ int unicode_prop(CharRange *cr, const char *prop_name) } #endif /* CONFIG_ALL_UNICODE */ + +/*---- lre codepoint categorizing functions ----*/ + +#define S UNICODE_C_SPACE +#define D UNICODE_C_DIGIT +#define X UNICODE_C_XDIGIT +#define U UNICODE_C_UPPER +#define L UNICODE_C_LOWER +#define _ UNICODE_C_UNDER +#define d UNICODE_C_DOLLAR + +uint8_t const lre_ctype_bits[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, S, S, S, S, S, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, d, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D, + X|D, X|D, 0, 0, 0, 0, 0, 0, + + 0, X|U, X|U, X|U, X|U, X|U, X|U, U, + U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, + U, U, U, 0, 0, 0, 0, _, + + 0, X|L, X|L, X|L, X|L, X|L, X|L, L, + L, L, L, L, L, L, L, L, + L, L, L, L, L, L, L, L, + L, L, L, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#undef S +#undef D +#undef X +#undef U +#undef L +#undef _ +#undef d + +/* code point ranges for Zs,Zl or Zp property */ +static const uint16_t char_range_s[] = { + 10, + 0x0009, 0x000D + 1, + 0x0020, 0x0020 + 1, + 0x00A0, 0x00A0 + 1, + 0x1680, 0x1680 + 1, + 0x2000, 0x200A + 1, + /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */ + /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */ + 0x2028, 0x2029 + 1, + 0x202F, 0x202F + 1, + 0x205F, 0x205F + 1, + 0x3000, 0x3000 + 1, + /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */ + 0xFEFF, 0xFEFF + 1, +}; + +BOOL lre_is_space_non_ascii(uint32_t c) +{ + size_t i, n; + + n = countof(char_range_s); + for(i = 5; i < n; i += 2) { + uint32_t low = char_range_s[i]; + uint32_t high = char_range_s[i + 1]; + if (c < low) + return FALSE; + if (c < high) + return TRUE; + } + return FALSE; +} diff --git a/libunicode.h b/libunicode.h index 5f29eda1..cc2f244c 100644 --- a/libunicode.h +++ b/libunicode.h @@ -24,27 +24,13 @@ #ifndef LIBUNICODE_H #define LIBUNICODE_H -#include - -#define LRE_BOOL int /* for documentation purposes */ +#include /* define it to include all the unicode tables (40KB larger) */ #define CONFIG_ALL_UNICODE #define LRE_CC_RES_LEN_MAX 3 -typedef enum { - UNICODE_NFC, - UNICODE_NFD, - UNICODE_NFKC, - UNICODE_NFKD, -} UnicodeNormalizationEnum; - -int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); -int lre_canonicalize(uint32_t c, BOOL is_unicode); -LRE_BOOL lre_is_cased(uint32_t c); -LRE_BOOL lre_is_case_ignorable(uint32_t c); - /* char ranges */ typedef struct { @@ -102,12 +88,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, int cr_invert(CharRange *cr); -int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode); - -#ifdef CONFIG_ALL_UNICODE +int cr_regexp_canonicalize(CharRange *cr, int is_unicode); -LRE_BOOL lre_is_id_start(uint32_t c); -LRE_BOOL lre_is_id_continue(uint32_t c); +typedef enum { + UNICODE_NFC, + UNICODE_NFD, + UNICODE_NFKC, + UNICODE_NFKD, +} UnicodeNormalizationEnum; int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, UnicodeNormalizationEnum n_type, @@ -115,13 +103,80 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, /* Unicode character range functions */ -int unicode_script(CharRange *cr, - const char *script_name, LRE_BOOL is_ext); +int unicode_script(CharRange *cr, const char *script_name, int is_ext); int unicode_general_category(CharRange *cr, const char *gc_name); int unicode_prop(CharRange *cr, const char *prop_name); -#endif /* CONFIG_ALL_UNICODE */ +int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); +int lre_canonicalize(uint32_t c, int is_unicode); + +/* Code point type categories */ +enum { + UNICODE_C_SPACE = (1 << 0), + UNICODE_C_DIGIT = (1 << 1), + UNICODE_C_UPPER = (1 << 2), + UNICODE_C_LOWER = (1 << 3), + UNICODE_C_UNDER = (1 << 4), + UNICODE_C_DOLLAR = (1 << 5), + UNICODE_C_XDIGIT = (1 << 6), +}; +extern uint8_t const lre_ctype_bits[256]; + +/* zero or non-zero return value */ +int lre_is_cased(uint32_t c); +int lre_is_case_ignorable(uint32_t c); +int lre_is_id_start(uint32_t c); +int lre_is_id_continue(uint32_t c); + +static inline int lre_is_space_byte(uint8_t c) { + return lre_ctype_bits[c] & UNICODE_C_SPACE; +} + +static inline int lre_is_id_start_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR); +} -#undef LRE_BOOL +static inline int lre_is_id_continue_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR | + UNICODE_C_DIGIT); +} + +int lre_is_space_non_ascii(uint32_t c); + +static inline int lre_is_space(uint32_t c) { + if (c < 256) + return lre_is_space_byte(c); + else + return lre_is_space_non_ascii(c); +} + +static inline int lre_js_is_ident_first(uint32_t c) { + if (c < 128) { + return lre_is_id_start_byte(c); + } else { +#ifdef CONFIG_ALL_UNICODE + return lre_is_id_start(c); +#else + return !lre_is_space_non_ascii(c); +#endif + } +} + +static inline int lre_js_is_ident_next(uint32_t c) { + if (c < 128) { + return lre_is_id_continue_byte(c); + } else { + /* ZWNJ and ZWJ are accepted in identifiers */ + if (c >= 0x200C && c <= 0x200D) + return TRUE; +#ifdef CONFIG_ALL_UNICODE + return lre_is_id_continue(c); +#else + return !lre_is_space_non_ascii(c); +#endif + } +} #endif /* LIBUNICODE_H */ diff --git a/qjs.c b/qjs.c index bcee9576..03328959 100644 --- a/qjs.c +++ b/qjs.c @@ -36,6 +36,8 @@ #include #elif defined(__linux__) #include +#elif defined(__FreeBSD__) +#include #endif #include "cutils.h" diff --git a/quickjs-libc.c b/quickjs-libc.c index 42fee032..81371507 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -47,8 +47,15 @@ #include #include -#if defined(__APPLE__) +#if defined(__FreeBSD__) +extern char **environ; +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) typedef sig_t sighandler_t; +#endif + +#if defined(__APPLE__) #if !defined(environ) #include #define environ (*_NSGetEnviron()) @@ -1282,7 +1289,7 @@ static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, /* urlGet */ -#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, @@ -1328,7 +1335,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, DynBuf header_buf_s, *header_buf = &header_buf_s; char *buf; size_t i, len; - int c, status; + int status; JSValue response = JS_UNDEFINED, ret_obj; JSValueConst options_obj; FILE *f; @@ -1355,16 +1362,25 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, } 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); @@ -1671,7 +1687,7 @@ static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, int fd; if (JS_ToInt32(ctx, &fd, argv[0])) return JS_EXCEPTION; - return JS_NewBool(ctx, (isatty(fd) != 0)); + return JS_NewBool(ctx, isatty(fd)); } #if defined(_WIN32) @@ -2999,7 +3015,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++) { @@ -3008,9 +3023,28 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, _exit(127); } } - - for(i = 3; i < fd_max; i++) - close(i); +#if defined(HAVE_CLOSEFROM) + /* closefrom() is available on many recent unix systems: + Linux with glibc 2.34+, Solaris 9+, FreeBSD 7.3+, + NetBSD 3.0+, OpenBSD 3.5+. + Linux with the musl libc and macOS don't have it. + */ + + closefrom(3); +#else + { + /* Close the file handles manually, limit to 1024 to avoid + costly loop on linux Alpine where sysconf(_SC_OPEN_MAX) + returns a huge value 1048576. + Patch inspired by nicolas-duteil-nova. See also: + https://stackoverflow.com/questions/73229353/ + https://stackoverflow.com/questions/899038/#918469 + */ + int fd_max = min_int(sysconf(_SC_OPEN_MAX), 1024); + for(i = 3; i < fd_max; i++) + close(i); + } +#endif if (cwd) { if (chdir(cwd) < 0) _exit(127); @@ -3511,10 +3545,12 @@ 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); + 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, sizeof(msg->sab_tab[0]) * sab_tab_len); + } msg->sab_tab_len = sab_tab_len; js_free(ctx, data); diff --git a/quickjs.c b/quickjs.c index c39e83c7..f000ff74 100644 --- a/quickjs.c +++ b/quickjs.c @@ -44,6 +44,7 @@ #include "list.h" #include "quickjs.h" #include "libregexp.h" +#include "libunicode.h" #include "libbf.h" #define OPTIMIZE 1 @@ -968,6 +969,7 @@ struct JSObject { } u; /* byte sizes: 40/48/72 */ }; + enum { __JS_ATOM_NULL = JS_ATOM_NULL, #define DEF(name, str) JS_ATOM_ ## name, @@ -1103,6 +1105,12 @@ 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); @@ -1124,7 +1132,7 @@ 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_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2); static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2); static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2); static JSValue JS_ToObject(JSContext *ctx, JSValueConst val); @@ -1167,9 +1175,10 @@ 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_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception); static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj); -static int js_proxy_isArray(JSContext *ctx, JSValueConst obj); static int JS_CreateProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, @@ -1268,7 +1277,6 @@ 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); @@ -1454,6 +1462,10 @@ 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; @@ -2427,10 +2439,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) @@ -2439,10 +2448,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'); @@ -2487,10 +2493,24 @@ static uint32_t hash_string(const JSString *str, uint32_t h) return h; } -static __maybe_unused void JS_DumpString(JSRuntime *rt, - const JSString *p) +static __maybe_unused void JS_DumpChar(JSRuntime *rt, int c, int sep) { - int i, c, sep; + if (c == sep || c == '\\') { + putchar('\\'); + putchar(c); + } else if (c >= ' ' && c <= 126) { + putchar(c); + } else if (c == '\n') { + putchar('\\'); + putchar('n'); + } else { + printf("\\u%04x", c); + } +} + +static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p) +{ + int i, sep; if (p == NULL) { printf(""); @@ -2500,21 +2520,7 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt, sep = (p->header.ref_count == 1) ? '\"' : '\''; 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]; - if (c == sep || c == '\\') { - putchar('\\'); - putchar(c); - } else if (c >= ' ' && c <= 126) { - putchar(c); - } else if (c == '\n') { - putchar('\\'); - putchar('n'); - } else { - printf("\\u%04x", c); - } + JS_DumpChar(rt, string_get(p, i), sep); } putchar(sep); } @@ -2857,6 +2863,7 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, return __JS_NewAtom(rt, p, atom_type); } +/* Warning: str must be ASCII only */ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, int atom_type) { @@ -2951,11 +2958,13 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p) return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING); } +/* str is UTF-8 encoded */ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len) { JSValue val; if (len == 0 || !is_digit(*str)) { + // XXX: this will not work if UTF-8 encoded str contains non ASCII bytes JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING); if (atom) return atom; @@ -3061,10 +3070,7 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size, return (const char *)str->u.str8; } for(i = 0; i < str->len; i++) { - if (str->is_wide_char) - c = str->u.str16[i]; - else - c = str->u.str8[i]; + c = string_get(str, i); if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX) break; if (c < 128) { @@ -3393,6 +3399,15 @@ JSClassID JS_NewClassID(JSClassID *pclass_id) 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 && @@ -3687,28 +3702,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++; } } @@ -3906,9 +3916,8 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) } else if (c <= 0x10FFFF) { p = p_next; /* surrogate pair */ - c -= 0x10000; - string_buffer_putc16(b, (c >> 10) + 0xd800); - c = (c & 0x3ff) + 0xdc00; + string_buffer_putc16(b, get_hi_surrogate(c)); + c = get_lo_surrogate(c); } else { /* invalid char */ c = 0xfffd; @@ -4046,13 +4055,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 */ @@ -4185,6 +4193,42 @@ static JSValue JS_ConcatString1(JSContext *ctx, return JS_MKPTR(JS_TAG_STRING, p); } +static BOOL JS_ConcatStringInPlace(JSContext *ctx, JSString *p1, JSValueConst op2) { + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + JSString *p2 = JS_VALUE_GET_STRING(op2); + size_t size1; + + if (p2->len == 0) + return TRUE; + if (p1->header.ref_count != 1) + return FALSE; + size1 = js_malloc_usable_size(ctx, p1); + if (p1->is_wide_char) { + if (size1 >= sizeof(*p1) + ((p1->len + p2->len) << 1)) { + if (p2->is_wide_char) { + memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1); + p1->len += p2->len; + return TRUE; + } else { + size_t i; + for (i = 0; i < p2->len; i++) { + p1->u.str16[p1->len++] = p2->u.str8[i]; + } + return TRUE; + } + } + } else if (!p2->is_wide_char) { + if (size1 >= sizeof(*p1) + p1->len + p2->len + 1) { + memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len); + p1->len += p2->len; + p1->u.str8[p1->len] = '\0'; + return TRUE; + } + } + } + return FALSE; +} + /* op1 and op2 are converted to strings. For convenience, op1 or op2 = JS_EXCEPTION are accepted and return JS_EXCEPTION. */ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) @@ -4207,27 +4251,11 @@ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) } } p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - - /* XXX: could also check if p1 is empty */ - if (p2->len == 0) { - goto ret_op1; - } - if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char - && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) { - /* Concatenate in place in available space at the end of p1 */ - if (p1->is_wide_char) { - memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1); - p1->len += p2->len; - } else { - memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len); - p1->len += p2->len; - p1->u.str8[p1->len] = '\0'; - } - ret_op1: + if (JS_ConcatStringInPlace(ctx, p1, op2)) { JS_FreeValue(ctx, op2); return op1; } + p2 = JS_VALUE_GET_STRING(op2); ret = JS_ConcatString1(ctx, p1, p2); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); @@ -6228,7 +6256,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) "BigNum " #endif CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n", - (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit); + (int)sizeof(void *) * 8, s->malloc_limit); #if 1 if (rt) { static const struct { @@ -6374,6 +6402,11 @@ JSValue JS_GetException(JSContext *ctx) return val; } +JS_BOOL JS_HasException(JSContext *ctx) +{ + return !JS_IsNull(ctx->rt->current_exception); +} + static void dbuf_put_leb128(DynBuf *s, uint32_t v) { uint32_t a; @@ -9828,12 +9861,6 @@ 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) - static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint) { int i; @@ -11058,6 +11085,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; @@ -11308,6 +11337,8 @@ static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val) #endif /* CONFIG_BIGNUM */ /* 2 <= base <= 36 */ +static char const digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz"; + static char *i64toa(char *buf_end, int64_t n, unsigned int base) { char *q = buf_end; @@ -11319,15 +11350,20 @@ static char *i64toa(char *buf_end, int64_t n, unsigned int base) 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 (base == 10) { + /* division by known base uses multiplication */ + do { + digit = (uint64_t)n % 10; + n = (uint64_t)n / 10; + *--q = '0' + digit; + } while (n != 0); + } else { + do { + digit = (uint64_t)n % base; + n = (uint64_t)n / base; + *--q = digits[digit]; + } while (n != 0); + } if (is_neg) *--q = '-'; return q; @@ -11417,20 +11453,20 @@ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf, return n_digits; } -static int js_fcvt1(char *buf, int buf_size, double d, int n_digits, +static int js_fcvt1(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits, int rounding_mode) { int n; if (rounding_mode != FE_TONEAREST) fesetround(rounding_mode); - n = snprintf(buf, buf_size, "%.*f", n_digits, d); + n = snprintf(*buf, sizeof(*buf), "%.*f", n_digits, d); if (rounding_mode != FE_TONEAREST) fesetround(FE_TONEAREST); - assert(n < buf_size); + assert(n < sizeof(*buf)); return n; } -static void js_fcvt(char *buf, int buf_size, double d, int n_digits) +static void js_fcvt(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits) { int rounding_mode; rounding_mode = FE_TONEAREST; @@ -11444,12 +11480,12 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits) 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); + n1 = js_fcvt1(&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); + n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_DOWNWARD); + n2 = js_fcvt1(&buf2, d, n_digits + 1, FE_UPWARD); if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) { /* exact result: round away from zero */ if (buf1[0] == '-') @@ -11460,7 +11496,7 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits) } } #endif /* CONFIG_PRINTF_RNDN */ - js_fcvt1(buf, buf_size, d, n_digits, rounding_mode); + js_fcvt1(buf, d, n_digits, rounding_mode); } /* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */ @@ -11476,33 +11512,35 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits) /* 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) +static void js_dtoa1(char (*buf)[JS_DTOA_BUF_SIZE], double d, + int radix, int n_digits, int flags) { char *q; if (!isfinite(d)) { if (isnan(d)) { - strcpy(buf, "NaN"); + pstrcpy(*buf, sizeof(*buf), "NaN"); + } else if (d < 0) { + pstrcpy(*buf, sizeof(*buf), "-Infinity"); } else { - q = buf; - if (d < 0) - *q++ = '-'; - strcpy(q, "Infinity"); + pstrcpy(*buf, sizeof(*buf), "Infinity"); } } else if (flags == JS_DTOA_VAR_FORMAT) { int64_t i64; char buf1[70], *ptr; + if (d > (double)MAX_SAFE_INTEGER || d < (double)-MAX_SAFE_INTEGER) + goto generic_conv; i64 = (int64_t)d; - if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER) + if (d != i64) goto generic_conv; /* fast path for integers */ ptr = i64toa(buf1 + sizeof(buf1), i64, radix); - strcpy(buf, ptr); + pstrcpy(*buf, sizeof(*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); + js_fcvt(buf, d, n_digits); } else { char buf1[JS_DTOA_BUF_SIZE]; int sign, decpt, k, n, i, p, n_max; @@ -11517,7 +11555,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) /* 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; + q = *buf; if (sign) *q++ = '-'; if (flags & JS_DTOA_FORCE_EXP) @@ -11559,7 +11597,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) p = n - 1; if (p >= 0) *q++ = '+'; - sprintf(q, "%d", p); + snprintf(q, *buf + sizeof(*buf) - q, "%d", p); } } } @@ -11569,10 +11607,84 @@ static JSValue js_dtoa(JSContext *ctx, double d, int radix, int n_digits, int flags) { char buf[JS_DTOA_BUF_SIZE]; - js_dtoa1(buf, d, radix, n_digits, flags); + js_dtoa1(&buf, d, radix, n_digits, flags); return JS_NewString(ctx, buf); } +static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix) +{ + char buf[2200], *ptr, *ptr2; + /* d is finite */ + int sign = d < 0; + int digit; + double frac, d0; + int64_t n0 = 0; + d = fabs(d); + d0 = trunc(d); + frac = d - d0; + ptr = buf + 1100; + *ptr = '\0'; + if (d0 <= MAX_SAFE_INTEGER) { + int64_t n = n0 = (int64_t)d0; + while (n >= radix) { + digit = n % radix; + n = n / radix; + *--ptr = digits[digit]; + } + *--ptr = digits[(int)n]; + } else { + /* no decimals */ + while (d0 >= radix) { + digit = fmod(d0, radix); + d0 = trunc(d0 / radix); + if (d0 >= MAX_SAFE_INTEGER) + digit = 0; + *--ptr = digits[digit]; + } + *--ptr = digits[(int)d0]; + goto done; + } + if (frac != 0) { + double log2_radix = log2(radix); + double prec = 1023 + 51; // handle subnormals + ptr2 = buf + 1100; + *ptr2++ = '.'; + while (frac != 0 && n0 <= MAX_SAFE_INTEGER/2 && prec > 0) { + frac *= radix; + digit = trunc(frac); + frac -= digit; + *ptr2++ = digits[digit]; + n0 = n0 * radix + digit; + prec -= log2_radix; + } + *ptr2 = '\0'; + if (frac * radix >= radix / 2) { + char nine = digits[radix - 1]; + // round to closest + while (ptr2[-1] == nine) + *--ptr2 = '\0'; + if (ptr2[-1] == '.') { + *--ptr2 = '\0'; + while (ptr2[-1] == nine) + *--ptr2 = '0'; + } + if (ptr2 - 1 == ptr) + *--ptr = '1'; + else + ptr2[-1] += 1; + } else { + while (ptr2[-1] == '0') + *--ptr2 = '\0'; + if (ptr2[-1] == '.') + *--ptr2 = '\0'; + } + } +done: + ptr[-1] = '-'; + ptr -= sign; + return JS_NewString(ctx, ptr); +} + JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey) { uint32_t tag; @@ -11713,7 +11825,7 @@ 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)) goto fail; @@ -11998,15 +12110,14 @@ static __maybe_unused void JS_PrintValue(JSContext *ctx, } /* return -1 if exception (proxy case) or TRUE/FALSE */ +// TODO: should take flags to make proxy resolution and exceptions optional int JS_IsArray(JSContext *ctx, JSValueConst val) { - JSObject *p; + if (js_resolve_proxy(ctx, &val, TRUE)) + return -1; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(val); - if (unlikely(p->class_id == JS_CLASS_PROXY)) - return js_proxy_isArray(ctx, val); - else - return p->class_id == JS_CLASS_ARRAY; + JSObject *p = JS_VALUE_GET_OBJ(val); + return p->class_id == JS_CLASS_ARRAY; } else { return FALSE; } @@ -14128,7 +14239,7 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, goto exception; } } - res = js_strict_eq(ctx, op1, op2); + res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } else if (tag1 == JS_TAG_BOOL) { op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1)); goto redo; @@ -14446,9 +14557,16 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, return res; } -static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2) +static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_strict_eq2(ctx, + JS_DupValue(ctx, op1), JS_DupValue(ctx, op2), + JS_EQ_STRICT); +} + +BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); + return js_strict_eq(ctx, op1, op2); } static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) @@ -14458,6 +14576,11 @@ static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) JS_EQ_SAME_VALUE); } +BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_same_value(ctx, op1, op2); +} + static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) { return js_strict_eq2(ctx, @@ -14465,11 +14588,16 @@ static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op JS_EQ_SAME_VALUE_ZERO); } +BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2) +{ + return js_same_value_zero(ctx, op1, op2); +} + static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, BOOL is_neq) { BOOL res; - res = js_strict_eq(ctx, sp[-2], sp[-1]); + res = js_strict_eq2(ctx, sp[-2], sp[-1], JS_EQ_STRICT); sp[-2] = JS_NewBool(ctx, res ^ is_neq); return 0; } @@ -17776,6 +17904,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + JS_VALUE_GET_FLOAT64(op2)); sp--; + } else if (JS_IsString(op1) && JS_IsString(op2)) { + sp[-2] = JS_ConcatString(ctx, op1, op2); + sp--; + if (JS_IsException(sp[-1])) + goto exception; } else { add_slow: if (js_add_slow(ctx, sp)) @@ -17786,38 +17919,45 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_add_loc): { + JSValue op2; JSValue *pv; int idx; idx = *pc; pc += 1; + op2 = sp[-1]; pv = &var_buf[idx]; - if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) { + if (likely(JS_VALUE_IS_BOTH_INT(*pv, op2))) { int64_t r; - r = (int64_t)JS_VALUE_GET_INT(*pv) + - JS_VALUE_GET_INT(sp[-1]); + r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) goto add_loc_slow; *pv = JS_NewInt32(ctx, r); sp--; + } else if (JS_VALUE_IS_BOTH_FLOAT(*pv, op2)) { + *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) + + JS_VALUE_GET_FLOAT64(op2)); + sp--; } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { - JSValue op1; - op1 = sp[-1]; sp--; - op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); - if (JS_IsException(op1)) + op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE); + if (JS_IsException(op2)) goto exception; - op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1); - if (JS_IsException(op1)) - goto exception; - set_value(ctx, pv, op1); + if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) { + JS_FreeValue(ctx, op2); + } else { + op2 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op2); + if (JS_IsException(op2)) + goto exception; + set_value(ctx, pv, op2); + } } else { JSValue ops[2]; add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ ops[0] = JS_DupValue(ctx, *pv); - ops[1] = sp[-1]; + ops[1] = op2; sp--; if (js_add_slow(ctx, ops + 2)) goto exception; @@ -18935,10 +19075,10 @@ 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; switch(s->state) { default: case JS_GENERATOR_STATE_SUSPENDED_START: + sf = &s->func_state->frame; if (magic == GEN_MAGIC_NEXT) { goto exec_no_arg; } else { @@ -18948,6 +19088,7 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, break; case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR: case JS_GENERATOR_STATE_SUSPENDED_YIELD: + sf = &s->func_state->frame; /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */ ret = JS_DupValue(ctx, argv[0]); if (magic == GEN_MAGIC_THROW && @@ -21069,8 +21210,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) for(;;) { buf[ident_pos++] = c; c = *p; - if (c >= 128 || - !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1)) + if (c >= 128 || !lre_is_id_continue_byte(c)) break; p++; if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { @@ -21282,9 +21422,29 @@ static __exception int json_next_token(JSParseState *s) return -1; } -/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is - only set if TOK_IMPORT is returned */ -/* XXX: handle all unicode cases */ +static int match_identifier(const uint8_t *p, const char *s) { + uint32_t c; + while (*s) { + if ((uint8_t)*s++ != *p++) + return 0; + } + c = *p; + if (c >= 128) + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + return !lre_js_is_ident_next(c); +} + +/* simple_next_token() is used to check for the next token in simple cases. + It is only used for ':' and '=>', 'let' or 'function' look-ahead. + (*pp) is only set if TOK_IMPORT is returned for JS_DetectModule() + Whitespace and comments are skipped correctly. + Then the next token is analyzed, only for specific words. + Return values: + - '\n' if !no_line_terminator + - TOK_ARROW, TOK_IN, TOK_IMPORT, TOK_OF, TOK_EXPORT, TOK_FUNCTION + - TOK_IDENT is returned for other identifiers and keywords + - otherwise the next character or unicode codepoint is returned. + */ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) { const uint8_t *p; @@ -21328,33 +21488,42 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) if (*p == '>') return TOK_ARROW; break; + case 'i': + if (match_identifier(p, "n")) + return TOK_IN; + if (match_identifier(p, "mport")) { + *pp = p + 5; + return TOK_IMPORT; + } + return TOK_IDENT; + case 'o': + if (match_identifier(p, "f")) + return TOK_OF; + return TOK_IDENT; + case 'e': + if (match_identifier(p, "xport")) + return TOK_EXPORT; + return TOK_IDENT; + case 'f': + if (match_identifier(p, "unction")) + return TOK_FUNCTION; + return TOK_IDENT; + case '\\': + if (*p == 'u') { + if (lre_js_is_ident_first(lre_parse_escape(&p, TRUE))) + return TOK_IDENT; + } + break; default: - if (lre_js_is_ident_first(c)) { - if (c == 'i') { - if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) { - return TOK_IN; - } - if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' && - p[3] == 'r' && p[4] == 't' && - !lre_js_is_ident_next(p[5])) { - *pp = p + 5; - return TOK_IMPORT; - } - } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) { - return TOK_OF; - } else if (c == 'e' && - p[0] == 'x' && p[1] == 'p' && p[2] == 'o' && - p[3] == 'r' && p[4] == 't' && - !lre_js_is_ident_next(p[5])) { - *pp = p + 5; - return TOK_EXPORT; - } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && - p[2] == 'c' && p[3] == 't' && p[4] == 'i' && - p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) { - return TOK_FUNCTION; - } - return TOK_IDENT; + if (c >= 128) { + c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p); + if (no_line_terminator && (c == CP_PS || c == CP_LS)) + return '\n'; } + if (lre_is_space(c)) + continue; + if (lre_js_is_ident_first(c)) + return TOK_IDENT; break; } return c; @@ -22232,7 +22401,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 == '=') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -22248,7 +22418,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 == '=') { is_non_reserved_ident = TRUE; goto ident_found; } @@ -22932,7 +23103,12 @@ 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)) @@ -26092,7 +26268,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 (;;) { @@ -26125,12 +26300,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; } @@ -27360,6 +27529,7 @@ static char *js_default_module_normalize_name(JSContext *ctx, { char *filename, *p; const char *r; + int cap; int len; if (name[0] != '.') { @@ -27373,7 +27543,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); @@ -27405,8 +27576,8 @@ static char *js_default_module_normalize_name(JSContext *ctx, } } if (filename[0] != '\0') - strcat(filename, "/"); - strcat(filename, r); + pstrcat(filename, cap, "/"); + pstrcat(filename, cap, r); // printf("normalize: %s %s -> %s\n", base_name, name, filename); return filename; } @@ -33270,8 +33441,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) } } else { b->vardefs = (void *)((uint8_t*)b + vardefs_offset); - memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0])); - memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0])); + memcpy_no_ub(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0])); + memcpy_no_ub(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0])); } b->var_count = fd->var_count; b->arg_count = fd->arg_count; @@ -33825,6 +33996,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; } @@ -34551,8 +34724,6 @@ 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, @@ -34562,24 +34733,21 @@ typedef enum BCTagEnum { BC_TAG_DATE, BC_TAG_OBJECT_VALUE, BC_TAG_OBJECT_REFERENCE, +#ifdef CONFIG_BIGNUM + BC_TAG_BIG_FLOAT, + BC_TAG_BIG_DECIMAL, +#endif } 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) +#define BC_VERSION 0x43 #else -#define BC_VERSION BC_BASE_VERSION +#define BC_VERSION 3 #endif typedef struct BCWriterState { JSContext *ctx; DynBuf dbuf; - BOOL byte_swap : 8; BOOL allow_bytecode : 8; BOOL allow_sab : 8; BOOL allow_reference : 8; @@ -34609,8 +34777,6 @@ static const char * const bc_tag_str[] = { "object", "array", "bigint", - "bigfloat", - "bigdecimal", "template", "function", "module", @@ -34620,9 +34786,22 @@ static const char * const bc_tag_str[] = { "Date", "ObjectValue", "ObjectReference", +#ifdef CONFIG_BIGNUM + "bigfloat", + "bigdecimal", +#endif }; #endif +static inline BOOL is_be(void) +{ + union { + uint16_t a; + uint8_t b; + } u = {0x100}; + return u.b; +} + static void bc_put_u8(BCWriterState *s, uint8_t v) { dbuf_putc(&s->dbuf, v); @@ -34630,21 +34809,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)); } @@ -34814,7 +34993,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s, pos += len; } - if (s->byte_swap) + if (is_be()) bc_byte_swap(bc_buf, bc_len); dbuf_put(&s->dbuf, bc_buf, bc_len); @@ -34876,7 +35055,7 @@ 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"); return -1; @@ -34905,20 +35084,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) 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)); + 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); -#endif - dbuf_put_u64(&s->dbuf, v); + bc_put_u64(s, v); #endif } } else { @@ -34961,14 +35134,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) v8 = d; bpos = 1; } else { - dbuf_putc(&s->dbuf, v8 | (d << 4)); + bc_put_u8(s, v8 | (d << 4)); bpos = 0; } } } /* flush the last digit */ if (bpos) { - dbuf_putc(&s->dbuf, v8); + bc_put_u8(s, v8); } } } @@ -35381,15 +35554,10 @@ 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++) { @@ -35422,8 +35590,6 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, 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); @@ -35544,33 +35710,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; } @@ -35682,7 +35860,13 @@ 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 @@ -35721,6 +35905,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, } 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]; @@ -35761,11 +35948,10 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) uint8_t v8; int32_t e; uint32_t len; - limb_t l, i, n, j; + limb_t l, i, n; JSBigFloat *p; limb_t v; bf_t *a; - int bpos, d; p = js_new_bf(s->ctx); if (!p) @@ -35815,45 +36001,23 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) JS_ThrowInternalError(s->ctx, "invalid bignum length"); goto fail; } - if (tag != BC_TAG_BIG_DECIMAL) - l = (len + sizeof(limb_t) - 1) / sizeof(limb_t); - else +#ifdef CONFIG_BIGNUM + if (tag == BC_TAG_BIG_DECIMAL) { l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS; + } else +#endif + { + 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)) - 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; - } - } else { +#ifdef CONFIG_BIGNUM + if (tag == BC_TAG_BIG_DECIMAL) { + limb_t j; + int bpos, d; + bpos = 0; for(i = 0; i < l; i++) { if (i == 0 && (n = len % LIMB_DIGITS) != 0) { @@ -35880,6 +36044,32 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) } a->tab[i] = v; } + } else +#endif /* CONFIG_BIGNUM */ + { + 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)) + goto fail; +#else + if (bc_get_u64(s, &v)) + goto fail; +#endif + a->tab[i] = v; + } } } bc_read_trace(s, "}\n"); @@ -36557,7 +36747,6 @@ static int JS_ReadObjectAtoms(BCReaderState *s) 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); @@ -36932,12 +37121,10 @@ static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val, static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - BOOL res; double d; if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; - res = isfinite(d); - return JS_NewBool(ctx, res); + return JS_NewBool(ctx, isfinite(d)); } /* Object class */ @@ -37331,13 +37518,13 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t } else { if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0) + JS_NewBool(ctx, 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_NewBool(ctx, 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_NewBool(ctx, desc.flags & JS_PROP_CONFIGURABLE), flags) < 0) goto exception1; js_free_desc(ctx, &desc); } @@ -38085,7 +38272,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_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE); js_free_desc(ctx, &desc); } else { res = JS_FALSE; @@ -38320,7 +38507,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 */ @@ -39084,7 +39273,7 @@ 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; } @@ -39493,9 +39682,10 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *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)) @@ -39627,10 +39817,10 @@ 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, @@ -39656,14 +39846,13 @@ 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 @@ -39681,7 +39870,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; @@ -39695,7 +39884,7 @@ 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) + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) return JS_NewInt32(ctx, -1); else return JS_UNDEFINED; @@ -40722,10 +40911,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 ), @@ -40931,8 +41120,16 @@ static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val, if (base < 0) goto fail; } + if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) { + char buf1[70], *ptr; + ptr = i64toa(buf1 + sizeof(buf1), JS_VALUE_GET_INT(val), base); + return JS_NewString(ctx, ptr); + } if (JS_ToFloat64Free(ctx, &d, val)) return JS_EXCEPTION; + if (base != 10 && isfinite(d)) { + return js_dtoa_radix(ctx, d, base); + } return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT); fail: JS_FreeValue(ctx, val); @@ -41137,10 +41334,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; @@ -41295,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 (isnan(d) || d < 0 || d > 0x10ffff || (c = (int)d) != d) goto range_error; } if (string_buffer_putc(b, c)) @@ -41406,10 +41600,7 @@ 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]; + c = string_get(p, idx); ret = JS_NewInt32(ctx, c); } JS_FreeValue(ctx, val); @@ -41439,10 +41630,7 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val, else ret = js_new_string8(ctx, NULL, 0); } 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); @@ -41554,18 +41742,18 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode) -1 if none */ static int js_string_find_invalid_codepoint(JSString *p) { - int i, c; + int i; 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) + uint32_t c = p->u.str16[i]; + if (is_surrogate(c)) { + if (is_hi_surrogate(c) && (i + 1) < p->len + && is_lo_surrogate(p->u.str16[i + 1])) { + i++; + } else { return i; - i++; + } } } return -1; @@ -41592,7 +41780,7 @@ static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val, { JSValue str, ret; JSString *p; - int c, i; + int i; str = JS_ToStringCheckObject(ctx, this_val); if (JS_IsException(str)) @@ -41611,17 +41799,13 @@ static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_STRING(ret); for (; i < p->len; i++) { - c = p->u.str16[i]; - if (c >= 0xD800 && c <= 0xDFFF) { - if (c >= 0xDC00 || (i + 1) >= p->len) { - p->u.str16[i] = 0xFFFD; + uint32_t c = p->u.str16[i]; + if (is_surrogate(c)) { + if (is_hi_surrogate(c) && (i + 1) < p->len + && is_lo_surrogate(p->u.str16[i + 1])) { + i++; } else { - c = p->u.str16[i + 1]; - if (c < 0xDC00 || c > 0xDFFF) { - p->u.str16[i] = 0xFFFD; - } else { - i++; - } + p->u.str16[i] = 0xFFFD; } } } @@ -41710,7 +41894,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]); @@ -42272,7 +42456,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)) @@ -42334,8 +42518,9 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val, len = p->len; if (len == 0 || n == 1) return str; + // XXX: potential arithmetic overflow if (val * len > JS_STRING_LEN_MAX) { - JS_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)) @@ -42398,10 +42583,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--; } } @@ -43069,14 +43254,16 @@ static double js_math_fround(double a) static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *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_NewInt32(ctx, d); } static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, @@ -43324,7 +43511,7 @@ 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 'y': mask = LRE_FLAG_STICKY; @@ -43342,7 +43529,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, JS_FreeCString(ctx, str); } - str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16)); + 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, @@ -43643,7 +43830,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas } flags = lre_get_flags(re->bytecode->u.str8); - return JS_NewBool(ctx, (flags & mask) != 0); + return JS_NewBool(ctx, flags & mask); } static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val) @@ -44009,7 +44196,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon 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); @@ -44784,7 +44971,7 @@ 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("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 ), @@ -44944,7 +45131,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_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true); } else if (s->token.u.ident.atom == JS_ATOM_null) { val = JS_NULL; } else { @@ -44956,7 +45143,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); @@ -45123,22 +45310,27 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, JSValue v; JSValueConst args[2]; - if (JS_IsObject(val) || - JS_IsBigInt(ctx, val) /* XXX: probably useless */ + /* check for object.toJSON method */ + /* ECMA specifies this is done only for Object and BigInt */ + /* we do it for BigFloat and BigDecimal as an extension */ + if (JS_IsObject(val) || JS_IsBigInt(ctx, val) +#ifdef CONFIG_BIGNUM + || JS_IsBigFloat(val) || JS_IsBigDecimal(val) +#endif ) { - JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON); - if (JS_IsException(f)) + 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; - 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); - } + } else { + JS_FreeValue(ctx, f); } + } if (!JS_IsUndefined(jsc->replacer_func)) { args[0] = key; @@ -45157,12 +45349,13 @@ 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: +#ifdef CONFIG_BIGNUM + case JS_TAG_BIG_FLOAT: + case JS_TAG_BIG_DECIMAL: +#endif case JS_TAG_EXCEPTION: return val; default: @@ -45192,36 +45385,29 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, 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 + goto concat_primitive; + } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT #ifdef CONFIG_BIGNUM - if (cl == JS_CLASS_BIG_FLOAT) { - return string_buffer_concat_value_free(jsc->b, val); - } else + || cl == JS_CLASS_BIG_FLOAT + || cl == JS_CLASS_BIG_DECIMAL #endif - if (cl == JS_CLASS_BIG_INT) { - JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify"); - goto exception; + ) + { + /* This will thow the same error as for the primitive object */ + set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data)); + goto concat_primitive; } v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val); if (JS_IsException(v)) @@ -45319,7 +45505,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, has_content = TRUE; } } - if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) { + if (has_content && !JS_IsEmptyString(jsc->gap)) { string_buffer_putc8(jsc->b, '\n'); string_buffer_concat_value(jsc->b, indent); } @@ -45334,6 +45520,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)) @@ -45345,15 +45534,17 @@ 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"); +#ifdef CONFIG_BIGNUM + case JS_TAG_BIG_FLOAT: + case JS_TAG_BIG_DECIMAL: +#endif + /* reject big numbers: use toJSON method to override */ + JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt"); goto exception; default: JS_FreeValue(ctx, val); @@ -46060,17 +46251,17 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val, } if (flags & JS_PROP_HAS_WRITABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0), + JS_NewBool(ctx, flags & JS_PROP_WRITABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_ENUMERABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0), + JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE), JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_CONFIGURABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0), + JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE), JS_PROP_C_W_E); } return ret; @@ -46522,20 +46713,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, return ret; } -static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) -{ - JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); - if (!s) - return FALSE; - if (js_check_stack_overflow(ctx->rt, 0)) { - JS_ThrowStackOverflow(ctx); - return -1; - } - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - return -1; +/* `js_resolve_proxy`: resolve the proxy chain + `*pval` is updated with to ultimate proxy target + `throw_exception` controls whether exceptions are thown or not + - return -1 in case of error + - otherwise return 0 + */ +static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) { + int depth = 0; + JSObject *p; + JSProxyData *s; + + while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) { + p = JS_VALUE_GET_OBJ(*pval); + if (p->class_id != JS_CLASS_PROXY) + break; + if (depth++ > 1000) { + if (throw_exception) + JS_ThrowStackOverflow(ctx); + return -1; + } + s = p->u.opaque; + if (s->is_revoked) { + if (throw_exception) + JS_ThrowTypeErrorRevokedProxy(ctx); + return -1; + } + *pval = s->target; } - return JS_IsArray(ctx, s->target); + return 0; } static const JSClassExoticMethods js_proxy_exotic_methods = { @@ -46930,7 +47136,7 @@ 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_FLOAT64: d = JS_VALUE_GET_FLOAT64(key); @@ -46940,7 +47146,7 @@ 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 */ break; @@ -47164,7 +47370,7 @@ static JSValue js_map_has(JSContext *ctx, JSValueConst this_val, 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_NewBool(ctx, mr != NULL); } static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val, @@ -49083,8 +49289,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; } @@ -49159,21 +49364,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); @@ -49281,6 +49486,7 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ), JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ), JS_PROP_UNDEFINED_DEF("undefined", 0 ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), }; /* Date */ @@ -49361,7 +49567,7 @@ static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; static char const day_names[] = "SunMonTueWedThuFriSat"; static __exception int get_date_fields(JSContext *ctx, JSValueConst obj, - double fields[9], int is_local, int force) + double fields[minimum_length(9)], int is_local, int force) { double dval; int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0; @@ -49374,7 +49580,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; @@ -49420,33 +49626,63 @@ 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); - - for(i = 0; i < m; i++) { - md = month_days[i]; +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 */ + + /* 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, @@ -49496,9 +49732,9 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val, res = FALSE; fields[first_field + i] = trunc(a); } - if (res && argc > 0) { + if (res && argc > 0) d = set_date_fields(fields, is_local); - } + return JS_SetThisTimeValue(ctx, this_val, d); } @@ -49724,145 +49960,418 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val, return JS_NewFloat64(ctx, 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; + } +} + +/* 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; +} + +/* 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; } -static void string_skip_non_spaces(JSString *sp, int *pp) { - while (*pp < sp->len && string_get(sp, *pp) != ' ') +/* 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 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; +/* 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; +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; - if (p >= sp->len) - return -1; - - 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; + p_start = p; + while ((c = sp[p]) >= '0' && c <= '9') { + ms += (c - '0') * mul; + mul /= 10; + p++; + if (p - p_start == 9) + break; + } + if (p > p_start) { + /* only consume the separator if digits are present */ + *pval = ms; + *pp = p; + } } - *pp = p; - return res; + return TRUE; } -/* 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; +static uint8_t upper_ascii(uint8_t c) { + return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c; +} - 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++; +static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) { + int tz = 0, sgn, hh, mm, p = *pp; + + sgn = sp[p++]; + if (sgn == '+' || sgn == '-') { + int n = p; + if (!string_get_digits(sp, &p, &hh, 1, 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; } - *pval = v; *pp = p; - return 0; + *tzp = tz; + return TRUE; } -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 - break; - } - if (mul == 1 && c >= '5') - ms += 1; - ms += (c - '0') * (mul /= 10); +static BOOL string_match(const uint8_t *sp, int *pp, const char *s) { + int p = *pp; + while (*s != '\0') { + if (upper_ascii(sp[p]) != upper_ascii(*s++)) + return FALSE; p++; } - *pval = ms; *pp = p; - return 0; + return TRUE; } - -static int find_abbrev(JSString *sp, int p, const char *list, int count) { +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 (upper_ascii(sp[p + i]) != 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; +} + +/* 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) { + for (size_t i = 0; i < countof(js_tzabbr); i++) { + if (string_match(sp, pp, js_tzabbr[i].name)) { + *offset = js_tzabbr[i].offset; + return TRUE; + } + } + return 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]); + } + 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")) { + if (fields[3] < 12) + fields[3] += 12; + continue; + } else + if (has_time && string_match(sp, &p, "AM")) { + 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, JSValueConst this_val, int argc, JSValueConst *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; @@ -49872,145 +50381,33 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, 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; - } - } - /* 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; - } + /* 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; + } + /* 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; } @@ -50041,9 +50438,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: @@ -50067,6 +50462,7 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val, if (isnan(v)) return JS_NAN; else + /* assuming -8.64e15 <= v <= -8.64e15 */ return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v))); } @@ -50205,6 +50601,15 @@ 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_NewFloat64(ctx, time_clip(epoch_ms))); + return obj; +} + void JS_AddIntrinsicDate(JSContext *ctx) { JSValueConst obj; @@ -50555,7 +50960,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue 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; @@ -50573,7 +50978,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); } @@ -50601,7 +51006,7 @@ 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; } @@ -50627,7 +51032,7 @@ static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val) return JS_DupValue(ctx, 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, @@ -51668,9 +52073,9 @@ static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_v 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); + return JS_NewBool(ctx, fe->flags & BF_FLAG_SUBNORMAL); default: - return JS_NewBool(ctx, (fe->status & magic) != 0); + return JS_NewBool(ctx, fe->status & magic); } } @@ -52393,11 +52798,13 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JS_NewGlobalCConstructor2(ctx, obj1, "Error", ctx->class_proto[JS_CLASS_ERROR]); + /* 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_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i], @@ -52424,7 +52831,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) /* XXX: create auto_initializer */ { /* initialize Array.prototype[Symbol.unscopables] */ - char const unscopables[] = + static const char unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" @@ -53022,6 +53429,16 @@ static JSValue js_typed_array_get_byteOffset(JSContext *ctx, return JS_NewInt32(ctx, ta->offset); } +JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, + JSTypedArrayEnum type) +{ + 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. */ @@ -53183,7 +53600,7 @@ static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, if (idx < 0) idx = len + idx; if (idx < 0 || idx >= len) - return JS_ThrowRangeError(ctx, "out of bound"); + return JS_ThrowRangeError(ctx, "invalid array index"); val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER); if (JS_IsException(val)) @@ -53577,14 +53994,13 @@ 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) { @@ -53599,7 +54015,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 { @@ -53608,7 +54024,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, } JS_FreeValue(ctx, val); } - if (mode == special_findIndex || mode == special_findLastIndex) + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) return JS_NewInt32(ctx, -1); else return JS_UNDEFINED; @@ -53690,8 +54106,10 @@ 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); + if (d >= INT64_MIN && d < 0x1p63) { + v64 = d; + is_int = (v64 == d); + } } else if (tag == JS_TAG_BIG_INT) { JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]); @@ -54450,10 +54868,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 ), @@ -54814,7 +55232,8 @@ static JSValue js_dataview_getValue(JSContext *ctx, { JSTypedArray *ta; JSArrayBuffer *abuf; - int is_swap, size; + BOOL littleEndian, is_swap; + int size; uint8_t *ptr; uint32_t v; uint64_t pos; @@ -54825,12 +55244,8 @@ 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); @@ -54915,7 +55330,8 @@ static JSValue js_dataview_setValue(JSContext *ctx, { JSTypedArray *ta; JSArrayBuffer *abuf; - int is_swap, size; + BOOL littleEndian, is_swap; + int size; uint8_t *ptr; uint64_t v64; uint32_t v; @@ -54954,12 +55370,8 @@ 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); @@ -55525,6 +55937,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]; @@ -55537,7 +55951,7 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx) 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]); diff --git a/quickjs.h b/quickjs.h index 59148f70..edc7b47b 100644 --- a/quickjs.h +++ b/quickjs.h @@ -499,7 +499,10 @@ typedef struct JSClassDef { JSClassExoticMethods *exotic; } JSClassDef; +#define JS_INVALID_CLASS_ID 0 JSClassID JS_NewClassID(JSClassID *pclass_id); +/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */ +JSClassID JS_GetClassID(JSValue v); int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); @@ -547,23 +550,21 @@ 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); + if (d >= INT32_MIN && d <= INT32_MAX) { + u.d = d; + val = (int32_t)d; + t.d = val; + /* -0 cannot be represented as integer, so we compare the bit + representation */ + if (u.u == t.u) + return JS_MKVAL(JS_TAG_INT, val); } - return v; + return __JS_NewFloat64(ctx, d); } static inline JS_BOOL JS_IsNumber(JSValueConst v) @@ -632,7 +633,9 @@ static inline JS_BOOL JS_IsObject(JSValueConst v) JSValue JS_Throw(JSContext *ctx, JSValue obj); JSValue JS_GetException(JSContext *ctx); +JS_BOOL JS_HasException(JSContext *ctx); JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); +void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag); void JS_ResetUncatchableError(JSContext *ctx); JSValue JS_NewError(JSContext *ctx); JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); @@ -681,6 +684,10 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) return (JSValue)v; } +JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2); +JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2); +JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2); + int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) @@ -723,6 +730,8 @@ JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val) JSValue JS_NewArray(JSContext *ctx); int JS_IsArray(JSContext *ctx, JSValueConst val); +JSValue JS_NewDate(JSContext *ctx, double epoch_ms); + JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst receiver, JS_BOOL throw_ref_error); @@ -821,6 +830,23 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); + +typedef enum JSTypedArrayEnum { + JS_TYPED_ARRAY_UINT8C = 0, + JS_TYPED_ARRAY_INT8, + JS_TYPED_ARRAY_UINT8, + JS_TYPED_ARRAY_INT16, + JS_TYPED_ARRAY_UINT16, + JS_TYPED_ARRAY_INT32, + JS_TYPED_ARRAY_UINT32, + JS_TYPED_ARRAY_BIG_INT64, + JS_TYPED_ARRAY_BIG_UINT64, + JS_TYPED_ARRAY_FLOAT32, + JS_TYPED_ARRAY_FLOAT64, +} JSTypedArrayEnum; + +JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, + JSTypedArrayEnum array_type); JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, size_t *pbyte_offset, size_t *pbyte_length, diff --git a/repl.js b/repl.js index 42aaa84b..cb92d3b1 100644 --- a/repl.js +++ b/repl.js @@ -67,38 +67,20 @@ import * as os from "os"; bright_white: "\x1b[37;1m", }; - var styles; - if (config_numcalc) { - styles = { - 'default': 'black', - '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 = { - 'default': 'bright_green', - 'comment': 'white', - 'string': 'bright_cyan', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'bright_white', - 'function': 'bright_yellow', - 'type': 'bright_magenta', - 'identifier': 'bright_green', - 'error': 'red', - 'result': 'bright_white', - 'error_msg': 'bright_red', - }; - } + var styles = { + 'default': 'bright_green', + 'comment': 'white', + 'string': 'bright_cyan', + 'regex': 'cyan', + 'number': 'green', + 'keyword': 'bright_white', + 'function': 'bright_yellow', + 'type': 'bright_magenta', + 'identifier': 'bright_green', + 'error': 'red', + 'result': 'bright_white', + 'error_msg': 'bright_red', + }; var history = []; var clip_board = ""; @@ -109,11 +91,7 @@ import * as os from "os"; var pstate = ""; var prompt = ""; var plen = 0; - var ps1; - if (config_numcalc) - ps1 = "> "; - else - ps1 = "qjs > "; + var ps1 = "qjs > "; var ps2 = " ... "; var utf8 = true; var show_time = false; @@ -613,6 +591,9 @@ import * as os from "os"; base = get_context_word(line, pos); if (["true", "false", "null", "this"].includes(base) || !isNaN(+base)) return eval(base); + // Check if `base` is a set of regexp flags + if (pos - base.length >= 3 && line[pos - base.length - 1] === '/') + return new RegExp('', base); obj = get_context_object(line, pos - base.length); if (obj === null || obj === void 0) return obj; @@ -1005,6 +986,8 @@ import * as os from "os"; std.puts(a); } else if (stack.indexOf(a) >= 0) { std.puts("[circular]"); + } else if (a instanceof Date) { + std.puts("Date " + a.toGMTString().__quote()); } else if (has_jscalc && (a instanceof Fraction || a instanceof Complex || a instanceof Mod || @@ -1179,6 +1162,23 @@ import * as os from "os"; } if (config_numcalc) { + styles = { + 'default': 'black', + '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', + }; + + ps1 = "> "; + /* called by the GUI */ g.execCmd = function (cmd) { switch(cmd) { diff --git a/run-test262.c b/run-test262.c index 84b510ae..4afb3f84 100644 --- a/run-test262.c +++ b/run-test262.c @@ -63,6 +63,8 @@ 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 compact; +int show_timings; int skip_async; int skip_module; int new_style; @@ -530,6 +532,7 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val, { const char *script; Test262Agent *agent; + pthread_attr_t attr; if (JS_GetContextOpaque(ctx) != NULL) return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); @@ -544,7 +547,12 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val, agent->script = strdup(script); JS_FreeCString(ctx, script); list_add_tail(&agent->link, &agent_list); - pthread_create(&agent->tid, NULL, agent_start, agent); + pthread_attr_init(&attr); + // musl libc gives threads 80 kb stacks, much smaller than + // JS_DEFAULT_STACK_SIZE (256 kb) + pthread_attr_setstacksize(&attr, 2 << 20); // 2 MB, glibc default + pthread_create(&agent->tid, &attr, agent_start, agent); + pthread_attr_destroy(&attr); return JS_UNDEFINED; } @@ -813,6 +821,19 @@ 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) { @@ -910,7 +931,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; @@ -965,6 +986,10 @@ void load_config(const char *filename) printf("%s:%d: syntax error\n", filename, lineno); continue; } + if (strstr(ignore, p)) { + printf("%s:%d: ignoring %s=%s\n", filename, lineno, p, q); + continue; + } if (str_equal(p, "style")) { new_style = str_equal(q, "new"); continue; @@ -1540,7 +1565,7 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip, 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); @@ -1656,7 +1681,7 @@ int run_test(const char *filename, int index) /* XXX: should extract the phase */ char *q = find_tag(p, "type:", &state); if (q) { - while (isspace(*q)) + while (isspace((unsigned char)*q)) q++; error_type = strdup_len(q, strcspn(q, " \n")); } @@ -1841,7 +1866,7 @@ int run_test262_harness_test(const char *filename, BOOL is_module) 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); @@ -1900,9 +1925,27 @@ void show_progress(int force) { clock_t t = clock(); if (force || !last_clock || (t - last_clock) > CLOCKS_PER_SEC / 20) { last_clock = t; - /* 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); + if (compact) { + static int last_test_skipped; + static int last_test_failed; + static int dots; + char c = '.'; + if (test_skipped > last_test_skipped) + c = '-'; + if (test_failed > last_test_failed) + c = '!'; + last_test_skipped = test_skipped; + last_test_failed = test_failed; + fputc(c, stderr); + if (force || ++dots % 60 == 0) { + fprintf(stderr, " %d/%d/%d\n", + test_failed, test_count, test_skipped); + } + } else { + /* output progress indicator: erase end of line and return to col 0 */ + fprintf(stderr, "%d/%d/%d\033[K\r", + test_failed, test_count, test_skipped); + } fflush(stderr); } } @@ -1953,6 +1996,8 @@ void help(void) "-N run test prepared by test262-harness+eshost\n" "-s run tests in strict mode, skip @nostrict tests\n" "-E only run tests from the error file\n" + "-C use compact progress indicator\n" + "-t show timings\n" "-u update error file\n" "-v verbose: output error messages\n" "-T duration display tests taking more than 'duration' ms\n" @@ -1979,14 +2024,29 @@ int main(int argc, char **argv) BOOL is_dir_list; BOOL only_check_errors = FALSE; const char *filename; + const char *ignore = ""; BOOL is_test262_harness = FALSE; BOOL is_module = FALSE; + clock_t clocks; #if !defined(_WIN32) + compact = !isatty(STDERR_FILENO); /* Date tests assume California local time */ setenv("TZ", "America/Los_Angeles", 1); #endif + optind = 1; + while (optind < argc) { + char *arg = argv[optind]; + if (*arg != '-') + break; + optind++; + if (strstr("-c -d -e -x -f -r -E -T", arg)) + optind++; + if (strstr("-d -f", arg)) + ignore = "testdir"; // run only the tests from -d or -f + } + /* cannot use getopt because we want to pass the command line to the script */ optind = 1; @@ -2006,12 +2066,16 @@ int main(int argc, char **argv) test_mode = TEST_STRICT; } else if (str_equal(arg, "-a")) { test_mode = TEST_ALL; + } else if (str_equal(arg, "-t")) { + show_timings++; } else if (str_equal(arg, "-u")) { update_errors++; } else if (str_equal(arg, "-v")) { verbose++; + } else if (str_equal(arg, "-C")) { + compact = 1; } else if (str_equal(arg, "-c")) { - load_config(get_opt_arg(arg, argv[optind++])); + 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")) { @@ -2042,7 +2106,7 @@ int main(int argc, char **argv) if (is_test262_harness) { return run_test262_harness_test(argv[optind], is_module); } - + error_out = stdout; if (error_filename) { error_file = load_file(error_filename, NULL); @@ -2062,8 +2126,10 @@ int main(int argc, char **argv) update_exclude_dirs(); + clocks = clock(); + 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); } @@ -2098,6 +2164,8 @@ int main(int argc, char **argv) } } + clocks = clock() - clocks; + if (dump_memory) { if (dump_memory > 1 && stats_count > 1) { printf("\nMininum memory statistics for %s:\n\n", stats_min_filename); @@ -2126,6 +2194,8 @@ int main(int argc, char **argv) fprintf(stderr, ", %d fixed", fixed_errors); } fprintf(stderr, "\n"); + if (show_timings) + fprintf(stderr, "Total time: %.3fs\n", (double)clocks / CLOCKS_PER_SEC); } if (error_out && error_out != stdout) { @@ -2141,5 +2211,6 @@ int main(int argc, char **argv) free(harness_exclude); free(error_file); - return 0; + /* Signal that the error file is out of date. */ + return new_errors || changed_errors || fixed_errors; } diff --git a/tests/microbench.js b/tests/microbench.js index 302f2ad7..c25e4d16 100644 --- a/tests/microbench.js +++ b/tests/microbench.js @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +if (typeof require !== 'undefined') { + var fs = require('fs'); +} + function pad(str, n) { str += ""; while (str.length < n) @@ -63,9 +67,9 @@ function toPrec(n, prec) { var ref_data; var log_data; -var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (%)" ]; +var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (1000)" ]; var widths = [ 22, 10, 9, 9, 9 ]; -var precs = [ 0, 0, 2, 2, 2 ]; +var precs = [ 0, 0, 2, 2, 0 ]; var total = [ 0, 0, 0, 0, 0 ]; var total_score = 0; var total_scale = 0; @@ -89,13 +93,27 @@ function log_line() { } var clocks_per_sec = 1000; -var max_iterations = 10; -var clock_threshold = 100; /* favoring short measuring spans */ +var max_iterations = 100; +var clock_threshold = 2; /* favoring short measuring spans */ var min_n_argument = 1; -var get_clock = Date.now; -if (typeof(os) !== "undefined") { +var get_clock; +if (typeof performance !== "undefined") { + // use more precise clock on NodeJS + // need a method call on performance object + get_clock = () => performance.now(); +} else +if (typeof os !== "undefined") { // use more precise clock on QuickJS get_clock = os.now; +} else { + // use Date.now and round up to the next millisecond + get_clock = () => { + var t0 = Date.now(); + var t; + while ((t = Date.now()) == t0) + continue; + return t; + } } function log_one(text, n, ti) { @@ -109,7 +127,7 @@ function log_one(text, n, ti) { ti = Math.round(ti * 100) / 100; log_data[text] = ti; if (typeof ref === "number") { - log_line(text, n, ti, ref, ti * 100 / ref); + log_line(text, n, ti, ref, Math.round(ref * 1000 / ti)); total_score += ti * 100 / ref; total_scale += 100; } else { @@ -121,28 +139,27 @@ function log_one(text, n, ti) { function bench(f, text) { - var i, j, n, t, t1, ti, nb_its, ref, ti_n, ti_n1, min_ti; + var i, j, n, t, ti, nb_its, ref, ti_n, ti_n1; nb_its = n = 1; if (f.bench) { ti_n = f(text); } else { + // measure ti_n: the shortest time for an individual operation ti_n = 1000000000; - min_ti = clock_threshold / 10; for(i = 0; i < 30; i++) { + // measure ti: the shortest time for max_iterations iterations ti = 1000000000; for (j = 0; j < max_iterations; j++) { t = get_clock(); - while ((t1 = get_clock()) == t) - continue; nb_its = f(n); + t = get_clock() - t; if (nb_its < 0) return; // test failure - t1 = get_clock() - t1; - if (ti > t1) - ti = t1; + if (ti > t) + ti = t; } - if (ti >= min_ti) { + if (ti >= clock_threshold / 10) { ti_n1 = ti / nb_its; if (ti_n > ti_n1) ti_n = ti_n1; @@ -196,6 +213,32 @@ function date_now(n) { return n; } +function date_parse(n) { + var x0 = 0, dx = 0; + var j; + for(j = 0; j < n; j++) { + var x1 = x0 - x0 % 1000; + var x2 = -x0; + var x3 = -x1; + var d0 = new Date(x0); + var d1 = new Date(x1); + var d2 = new Date(x2); + var d3 = new Date(x3); + if (Date.parse(d0.toISOString()) != x0 + || Date.parse(d1.toGMTString()) != x1 + || Date.parse(d1.toString()) != x1 + || Date.parse(d2.toISOString()) != x2 + || Date.parse(d3.toGMTString()) != x3 + || Date.parse(d3.toString()) != x3) { + console.log("Date.parse error for " + x0); + return -1; + } + dx = (dx * 1.1 + 1) >> 0; + x0 = (x0 + dx) % 8.64e15; + } + return n * 6; +} + function prop_read(n) { var obj, sum, j; @@ -224,30 +267,78 @@ function prop_write(n) return n * 4; } -function prop_create(n) +function prop_update(n) { var obj, j; + obj = {a: 1, b: 2, c:3, d:4 }; for(j = 0; j < n; j++) { - obj = new Object(); + obj.a += j; + obj.b += j; + obj.c += j; + obj.d += j; + } + return n * 4; +} + +function prop_create(n) +{ + var obj, i, j; + for(j = 0; j < n; j++) { + obj = {}; obj.a = 1; obj.b = 2; obj.c = 3; obj.d = 4; + obj.e = 5; + obj.f = 6; + obj.g = 7; + obj.h = 8; + obj.i = 9; + obj.j = 10; + for(i = 0; i < 10; i++) { + obj[i] = i; + } } - return n * 4; + return n * 20; } -function prop_delete(n) +function prop_clone(n) { - var obj, j; - obj = {}; - for(j = 0; j < n; j++) { - obj[j] = 1; + var ref, obj, j, k; + ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; + for(k = 0; k < 10; k++) { + ref[k] = k; } - for(j = 0; j < n; j++) { - delete obj[j]; + for (j = 0; j < n; j++) { + global_res = { ...ref }; } - return n; + return n * 20; +} + +function prop_delete(n) +{ + var ref, obj, j, k; + ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; + for(k = 0; k < 10; k++) { + ref[k] = k; + } + for (j = 0; j < n; j++) { + obj = { ...ref }; + delete obj.a; + delete obj.b; + delete obj.c; + delete obj.d; + delete obj.e; + delete obj.f; + delete obj.g; + delete obj.h; + delete obj.i; + delete obj.j; + for(k = 0; k < 10; k++) { + delete obj[k]; + } + } + return n * 20; } function array_read(n) @@ -308,15 +399,32 @@ function array_prop_create(n) return len * n; } +function array_slice(n) +{ + var ref, a, i, j, len; + len = 1000; + ref = []; + for(i = 0; i < len; i++) + ref[i] = i; + for(j = 0; j < n; j++) { + ref[0] = j; + a = ref.slice(); + a[0] = 0; + global_res = a; + } + return len * n; +} + function array_length_decr(n) { - var tab, i, j, len; + var tab, ref, i, j, len; len = 1000; - tab = []; + ref = []; for(i = 0; i < len; i++) - tab[i] = i; + ref[i] = i; for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) + tab = ref.slice(); + for(i = len; i --> 0;) tab.length = i; } return len * n; @@ -324,15 +432,16 @@ function array_length_decr(n) function array_hole_length_decr(n) { - var tab, i, j, len; + var tab, ref, i, j, len; len = 1000; - tab = []; + ref = []; for(i = 0; i < len; i++) { - if (i != 3) - tab[i] = i; + if (i % 10 == 9) + ref[i] = i; } for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) + tab = ref.slice(); + for(i = len; i --> 0;) tab.length = i; } return len * n; @@ -352,12 +461,13 @@ function array_push(n) function array_pop(n) { - var tab, i, j, len, sum; + var tab, ref, i, j, len, sum; len = 500; + ref = []; + for(i = 0; i < len; i++) + ref[i] = i; for(j = 0; j < n; j++) { - tab = []; - for(i = 0; i < len; i++) - tab[i] = i; + tab = ref.slice(); sum = 0; for(i = 0; i < len; i++) sum += tab.pop(); @@ -429,6 +539,7 @@ function global_read(n) return n * 4; } +// non strict version var global_write = (1, eval)(`(function global_write(n) { @@ -471,6 +582,7 @@ function local_destruct(n) var global_v1, global_v2, global_v3, global_v4; var global_a, global_b, global_c, global_d; +// non strict version var global_destruct = (1, eval)(`(function global_destruct(n) { @@ -498,6 +610,25 @@ function global_destruct_strict(n) return n * 8; } +function g(a) +{ + return 1; +} + +function global_func_call(n) +{ + var j, sum; + sum = 0; + for(j = 0; j < n; j++) { + sum += g(j); + sum += g(j); + sum += g(j); + sum += g(j); + } + global_res = sum; + return n * 4; +} + function func_call(n) { function f(a) @@ -517,7 +648,7 @@ function func_call(n) return n * 4; } -function closure_var(n) +function func_closure_call(n) { function f(a) { @@ -622,8 +753,8 @@ function bigint256_arith(n) function set_collection_add(n) { var s, i, j, len = 100; - s = new Set(); for(j = 0; j < n; j++) { + s = new Set(); for(i = 0; i < len; i++) { s.add(String(i), i); } @@ -637,25 +768,25 @@ function set_collection_add(n) function array_for(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; - for(i = 0; i < 100; i++) { + for(i = 0; i < len; i++) { sum += r[i]; } global_res = sum; } - return n * 100; + return n * len; } function array_for_in(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; @@ -664,14 +795,14 @@ function array_for_in(n) } global_res = sum; } - return n * 100; + return n * len; } function array_for_of(n) { - var r, i, j, sum; + var r, i, j, sum, len = 100; r = []; - for(i = 0; i < 100; i++) + for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; @@ -680,7 +811,7 @@ function array_for_of(n) } global_res = sum; } - return n * 100; + return n * len; } function math_min(n) @@ -700,11 +831,11 @@ function regexp_ascii(n) var i, j, r, s; s = "the quick brown fox jumped over the lazy dog" for(j = 0; j < n; j++) { - for(i = 0; i < 10000; i++) + for(i = 0; i < 1000; i++) r = /the quick brown fox/.exec(s) global_res = r; } - return n * 10000; + return n * 1000; } function regexp_utf16(n) @@ -712,91 +843,91 @@ function regexp_utf16(n) var i, j, r, s; s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" for(j = 0; j < n; j++) { - for(i = 0; i < 10000; i++) + for(i = 0; i < 1000; i++) r = /the quick brown ᶠᵒˣ/.exec(s) global_res = r; } - return n * 10000; + return n * 1000; } /* incremental string contruction as local var */ function string_build1(n) { var i, j, r; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r += "x"; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction using + */ function string_build1x(n) { var i, j, r; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r = r + "x"; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction using +2c */ function string_build2c(n) { var i, j; - var r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + var r = ""; + for(i = 0; i < 1000; i++) r += "xy"; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction as arg */ function string_build2(n, r) { var i, j; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r += "x"; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction by prepending */ function string_build3(n) { var i, j, r; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) + r = ""; + for(i = 0; i < 1000; i++) r = "x" + r; global_res = r; } - return n * 100; + return n * 1000; } /* incremental string contruction with multiple reference */ function string_build4(n) { var i, j, r, s; - r = ""; for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) { + r = ""; + for(i = 0; i < 1000; i++) { s = r; r += "x"; } global_res = r; } - return n * 100; + return n * 1000; } /* sort bench */ @@ -940,21 +1071,22 @@ sort_bench.verbose = false; function int_to_string(n) { - var s, r, j; - r = 0; + var s, j; for(j = 0; j < n; j++) { - s = (j + 1).toString(); + s = (j % 1000).toString(); + s = (1234000 + j % 1000).toString(); } - return n; + global_res = s; + return n * 2; } function float_to_string(n) { - var s, r, j; - r = 0; + var s, j; for(j = 0; j < n; j++) { s = (j + 0.1).toString(); } + global_res = s; return n; } @@ -963,7 +1095,6 @@ function string_to_int(n) var s, r, j; r = 0; s = "12345"; - r = 0; for(j = 0; j < n; j++) { r += (s | 0); } @@ -976,7 +1107,6 @@ function string_to_float(n) var s, r, j; r = 0; s = "12345.6"; - r = 0; for(j = 0; j < n; j++) { r -= s; } @@ -986,32 +1116,71 @@ function string_to_float(n) function load_result(filename) { - var f, str, res; - if (typeof std === "undefined") + var has_filename = filename; + var has_error = false; + var str, res; + + if (!filename) + filename = "microbench.txt"; + + if (typeof fs !== "undefined") { + // read the file in Node.js + try { + str = fs.readFileSync(filename, { encoding: "utf8" }); + } catch { + has_error = true; + } + } else + if (typeof std !== "undefined") { + // read the file in QuickJS + var f = std.open(filename, "r"); + if (f) { + str = f.readAsString(); + f.close(); + } else { + has_error = true; + } + } else { return null; - f = std.open(filename ? filename : "microbench.txt", "r"); - if (!f) { - if (filename) { + } + if (has_error) { + if (has_filename) { // Should throw exception? console.log("cannot load " + filename); } return null; } - str = f.readAsString(); res = JSON.parse(str); - f.close(); return res; } function save_result(filename, obj) { - var f; - if (typeof std === "undefined") + var str = JSON.stringify(obj, null, 2) + "\n"; + var has_error = false; + + if (typeof fs !== "undefined") { + // save the file in Node.js + try { + str = fs.writeFileSync(filename, str, { encoding: "utf8" }); + } catch { + has_error = true; + } + } else + if (typeof std !== "undefined") { + // save the file in QuickJS + var f = std.open(filename, "w"); + if (f) { + f.puts(str); + f.close(); + } else { + has_error = 'true'; + } + } else { return; - f = std.open(filename, "w"); - f.puts(JSON.stringify(obj, null, 2)); - f.puts("\n"); - f.close(); + } + if (has_error) + console.log("cannot save " + filename); } function main(argc, argv, g) @@ -1022,13 +1191,17 @@ function main(argc, argv, g) empty_down_loop2, empty_do_loop, date_now, + date_parse, prop_read, prop_write, + prop_update, prop_create, + prop_clone, prop_delete, array_read, array_write, array_prop_create, + array_slice, array_length_decr, array_hole_length_decr, array_push, @@ -1041,8 +1214,9 @@ function main(argc, argv, g) local_destruct, global_destruct, global_destruct_strict, + global_func_call, func_call, - closure_var, + func_closure_call, int_arith, float_arith, set_collection_add, @@ -1065,7 +1239,7 @@ function main(argc, argv, g) ]; var tests = []; var i, j, n, f, name, found; - var ref_file; + var ref_file, new_ref_file = "microbench-new.txt"; if (typeof BigInt === "function") { /* BigInt test */ @@ -1101,6 +1275,10 @@ function main(argc, argv, g) ref_file = argv[i++]; continue; } + if (name == "-s") { + new_ref_file = argv[i++]; + continue; + } for (j = 0, found = false; j < test_list.length; j++) { f = test_list[j]; if (f.name.startsWith(name)) { @@ -1128,14 +1306,17 @@ function main(argc, argv, g) n++; } if (ref_data) - log_line("total", "", total[2], total[3], total_score * 100 / total_scale); + log_line("total", "", total[2], total[3], Math.round(total_scale * 1000 / total_score)); else log_line("total", "", total[2]); - if (tests == test_list) - save_result("microbench-new.txt", log_data); + if (tests == test_list && new_ref_file) + save_result(new_ref_file, log_data); } -if (typeof scriptArgs === "undefined") +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 index a46fa302..ba8d27cb 100644 --- a/tests/test262.patch +++ b/tests/test262.patch @@ -1,8 +1,8 @@ diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js -index 9c1217351e..3c24755558 100644 +index 9828b15..4a5919d 100644 --- a/harness/atomicsHelper.js +++ b/harness/atomicsHelper.js -@@ -227,10 +227,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { +@@ -272,10 +272,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { * } */ $262.agent.timeouts = { @@ -22,13 +22,13 @@ index 9c1217351e..3c24755558 100644 /** diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js -index be7039fda0..7b38abf8df 100644 +index b55f3c6..396bad4 100644 --- a/harness/regExpUtils.js +++ b/harness/regExpUtils.js -@@ -6,24 +6,27 @@ description: | - defines: [buildString, testPropertyEscapes, matchValidator] +@@ -6,27 +6,30 @@ description: | + defines: [buildString, testPropertyEscapes, testPropertyOfStrings, testExtendedCharacterClass, matchValidator] ---*/ - + +if ($262 && typeof $262.codePointRange === "function") { + /* use C function to build the codePointRange (much faster with + slow JS engines) */ @@ -44,7 +44,12 @@ index be7039fda0..7b38abf8df 100644 + } +} + - function buildString({ loneCodePoints, ranges }) { + function buildString(args) { + // Use member expressions rather than destructuring `args` for improved + // compatibility with engines that only implement assignment patterns + // partially or not at all. + const loneCodePoints = args.loneCodePoints; + const ranges = args.ranges; - const CHUNK_SIZE = 10000; - let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints); - for (let i = 0; i < ranges.length; i++) { @@ -58,14 +63,11 @@ index be7039fda0..7b38abf8df 100644 - 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; ++ let result = String.fromCodePoint.apply(null, loneCodePoints); ++ for (const [start, end] of ranges) { ++ result += codePointRange(start, end + 1); + } + return result; } - - function testPropertyEscapes(regex, string, expression) { diff --git a/tests/test_bigfloat.js b/tests/test_bigfloat.js new file mode 100644 index 00000000..c35fb724 --- /dev/null +++ b/tests/test_bigfloat.js @@ -0,0 +1,279 @@ +"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) {} + +/*----------------*/ + +/* 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_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_bigint_ext(); +test_bigfloat(); +test_bigdecimal(); diff --git a/tests/test_bignum.js b/tests/test_bignum.js index 51aa5b25..1520d82c 100644 --- a/tests/test_bignum.js +++ b/tests/test_bignum.js @@ -110,217 +110,5 @@ function test_bigint2() 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_builtin.js b/tests/test_builtin.js index a9b2264e..15cd1894 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -1,19 +1,51 @@ "use strict"; +var status = 0; +var throw_errors = true; + +function throw_error(msg) { + if (throw_errors) + throw Error(msg); + console.log(msg); + status = 1; +} + function assert(actual, expected, message) { + function get_full_type(o) { + var type = typeof(o); + if (type === 'object') { + if (o === null) + return 'null'; + if (o.constructor && o.constructor.name) + return o.constructor.name; + } + return type; + } + 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 + "|" + + if (typeof actual === typeof expected) { + if (actual === expected) { + if (actual !== 0 || (1 / actual) === (1 / expected)) + return; + } + if (typeof actual === 'number') { + if (isNaN(actual) && isNaN(expected)) + return true; + } + if (typeof actual === 'object') { + if (actual !== null && expected !== null + && actual.constructor === expected.constructor + && actual.toString() === expected.toString()) + return; + } + } + // Should output the source file and line number and extract + // the expression from the assert call + throw_error("assertion failed: got " + + get_full_type(actual) + ":|" + actual + "|, expected " + + get_full_type(expected) + ":|" + expected + "|" + (message ? " (" + message + ")" : "")); } @@ -25,11 +57,16 @@ function assert_throws(expected_error, func) } catch(e) { err = true; if (!(e instanceof expected_error)) { - throw Error("unexpected exception type"); + // Should output the source file and line number and extract + // the expression from the assert_throws() call + throw_error("unexpected exception type"); + return; } } if (!err) { - throw Error("expected exception"); + // Should output the source file and line number and extract + // the expression from the assert_throws() call + throw_error("expected exception"); } } @@ -311,10 +348,14 @@ 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); - assert(Math.hypot(3, 4) == 5); + assert(Math.hypot(), 0); + assert(Math.hypot(-2), 2); + assert(Math.hypot(3, 4), 5); assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15); } @@ -327,6 +368,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,6 +381,11 @@ function test_number() assert(Number.isNaN(Number("-"))); assert(Number.isNaN(Number("\x00a"))); + // TODO: Fix rounding errors on Windows/Cygwin. + if (typeof os !== 'undefined' && ['win32', 'cygwin'].includes(os.platform)) { + return; + } + assert((25).toExponential(0), "3e+1"); assert((-25).toExponential(0), "-3e+1"); assert((2.5).toPrecision(1), "3"); @@ -481,26 +531,105 @@ 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 (!(typeof os !== 'undefined' && ['win32', 'cygwin'].includes(os.platform))) { + // from test262/test/built-ins/Date/UTC/fp-evaluation-order.js + assert(Date.UTC(1970, 0, 1, 80063993375, 29, 1, -288230376151711740), 29312, + 'order of operations / precision in MakeTime'); + 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); } function test_regexp() @@ -549,6 +678,8 @@ function test_regexp() assert(a, ["a", undefined]); a = /(?:|[\w])+([0-9])/.exec("123a23"); assert(a, ["123a23", "3"]); + a = /()*?a/.exec(","); + assert(a, null); } function test_symbol() @@ -587,6 +718,20 @@ function test_map() { var a, i, n, tab, o, v; n = 1000; + + a = new Map(); + for (var i = 0; i < n; i++) { + a.set(i, i); + } + a.set(-2147483648, 1); + assert(a.get(-2147483648), 1); + assert(a.get(-2147483647 - 1), 1); + assert(a.get(-2147483647.5 - 0.5), 1); + + a.set(1n, 1n); + assert(a.get(1n), 1n); + assert(a.get(2n**1000n - (2n**1000n - 1n)), 1n); + a = new Map(); tab = []; for(i = 0; i < n; i++) { diff --git a/tests/test_language.js b/tests/test_language.js index 75f5cdcc..7e98d7a8 100644 --- a/tests/test_language.js +++ b/tests/test_language.js @@ -335,6 +335,13 @@ function test_class() assert(S.x === 42); assert(S.y === 42); assert(S.z === 42); + + class P { + get = () => "123"; + static() { return 42; } + } + assert(new P().get() === "123"); + assert(new P().static() === 42); }; function test_template() @@ -362,8 +369,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}'); @@ -420,8 +428,12 @@ function test_argument_scope() var f; var c = "global"; - f = function(a = eval("var arguments")) {}; - assert_throws(SyntaxError, f); + (function() { + "use strict"; + // XXX: node only throws in strict mode + f = function(a = eval("var arguments")) {}; + assert_throws(SyntaxError, f); + })(); f = function(a = eval("1"), b = arguments[0]) { return b; }; assert(f(12), 12); diff --git a/tests/test_std.js b/tests/test_std.js index 562c96ca..c8448692 100644 --- a/tests/test_std.js +++ b/tests/test_std.js @@ -144,7 +144,9 @@ function test_os() { var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; - assert(os.isatty(0)); + const stdinIsTTY = !os.exec(["/bin/sh", "-c", "test -t 0"], { usePath: false }); + + assert(os.isatty(0), stdinIsTTY, `isatty(STDIN)`); fdir = "test_tmp_dir"; fname = "tmp_file.txt"; @@ -253,10 +255,11 @@ 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); + assert(status !== 0, true, `expect nonzero exit code (got ${status})`); + assert(status & 0x7f, os.SIGTERM); } function test_timer() diff --git a/unicode_gen.c b/unicode_gen.c index 1d2be2a0..4f38052b 100644 --- a/unicode_gen.c +++ b/unicode_gen.c @@ -33,6 +33,11 @@ #include "cutils.h" +uint32_t total_tables; +uint32_t total_table_bytes; +uint32_t total_index; +uint32_t total_index_bytes; + /* define it to be able to test unicode.c */ //#define USE_TEST /* profile tests */ @@ -268,7 +273,7 @@ int find_name(const char **tab, int tab_len, const char *name) return -1; } -static int get_prop(uint32_t c, int prop_idx) +static BOOL get_prop(uint32_t c, int prop_idx) { return (unicode_db[c].prop_bitmap_tab[prop_idx >> 5] >> (prop_idx & 0x1f)) & 1; } @@ -1328,7 +1333,9 @@ void dump_case_conv_table(FILE *f) uint32_t v; const TableEntry *te; - fprintf(f, "static const uint32_t case_conv_table1[%u] = {", conv_table_len); + total_tables++; + total_table_bytes += conv_table_len * sizeof(uint32_t); + fprintf(f, "static const uint32_t case_conv_table1[%d] = {", conv_table_len); for(i = 0; i < conv_table_len; i++) { if (i % 4 == 0) fprintf(f, "\n "); @@ -1341,7 +1348,9 @@ void dump_case_conv_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint8_t case_conv_table2[%u] = {", conv_table_len); + total_tables++; + total_table_bytes += conv_table_len; + fprintf(f, "static const uint8_t case_conv_table2[%d] = {", conv_table_len); for(i = 0; i < conv_table_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -1350,7 +1359,9 @@ void dump_case_conv_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint16_t case_conv_ext[%u] = {", ext_data_len); + total_tables++; + total_table_bytes += ext_data_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t case_conv_ext[%d] = {", ext_data_len); for(i = 0; i < ext_data_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -1470,6 +1481,9 @@ void compute_internal_props(void) void dump_byte_table(FILE *f, const char *cname, const uint8_t *tab, int len) { int i; + + total_tables++; + total_table_bytes += len; fprintf(f, "static const uint8_t %s[%d] = {", cname, len); for(i = 0; i < len; i++) { if (i % 8 == 0) @@ -1479,9 +1493,26 @@ void dump_byte_table(FILE *f, const char *cname, const uint8_t *tab, int len) fprintf(f, "\n};\n\n"); } +void dump_index_table(FILE *f, const char *cname, const uint8_t *tab, int len) +{ + int i, code, offset; + + total_index++; + total_index_bytes += len; + fprintf(f, "static const uint8_t %s[%d] = {\n", cname, len); + for(i = 0; i < len; i += 3) { + code = tab[i] + (tab[i+1] << 8) + ((tab[i+2] & 0x1f) << 16); + offset = ((i / 3) + 1) * 32 + (tab[i+2] >> 5); + fprintf(f, " 0x%02x, 0x%02x, 0x%02x,", tab[i], tab[i+1], tab[i+2]); + fprintf(f, " // %6.5X at %d%s\n", code, offset, + i == len - 3 ? " (upper bound)" : ""); + } + fprintf(f, "};\n\n"); +} + #define PROP_BLOCK_LEN 32 -void build_prop_table(FILE *f, int prop_index, BOOL add_index) +void build_prop_table(FILE *f, const char *name, int prop_index, BOOL add_index) { int i, j, n, v, offset, code; DynBuf dbuf_s, *dbuf = &dbuf_s; @@ -1533,6 +1564,14 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) block_end_pos += PROP_BLOCK_LEN; } + /* Compressed byte encoding: + 00..3F: 2 packed lengths: 3-bit + 3-bit + 40..5F: 5-bits plus extra byte for length + 60..7F: 5-bits plus 2 extra bytes for length + 80..FF: 7-bit length + lengths must be incremented to get character count + Ranges alternate between false and true return value. + */ v = buf[i]; code += v + 1; bit ^= 1; @@ -1573,7 +1612,7 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) dump_byte_table(f, cname, dbuf->buf, dbuf->size); if (add_index) { snprintf(cname, sizeof(cname), "unicode_prop_%s_index", unicode_prop_name[prop_index]); - dump_byte_table(f, cname, dbuf2->buf, dbuf2->size); + dump_index_table(f, cname, dbuf2->buf, dbuf2->size); } dbuf_free(dbuf); @@ -1583,10 +1622,10 @@ void build_prop_table(FILE *f, int prop_index, BOOL add_index) void build_flags_tables(FILE *f) { - build_prop_table(f, PROP_Cased1, TRUE); - build_prop_table(f, PROP_Case_Ignorable, TRUE); - build_prop_table(f, PROP_ID_Start, TRUE); - build_prop_table(f, PROP_ID_Continue1, TRUE); + build_prop_table(f, "Cased1", PROP_Cased1, TRUE); + build_prop_table(f, "Case_Ignorable", PROP_Case_Ignorable, TRUE); + build_prop_table(f, "ID_Start", PROP_ID_Start, TRUE); + build_prop_table(f, "ID_Continue1", PROP_ID_Continue1, TRUE); } void dump_name_table(FILE *f, const char *cname, const char **tab_name, int len, @@ -1621,7 +1660,9 @@ void build_general_category_table(FILE *f) { int i, v, j, n, n1; DynBuf dbuf_s, *dbuf = &dbuf_s; +#ifdef DUMP_TABLE_SIZE int cw_count, cw_len_count[4], cw_start; +#endif fprintf(f, "typedef enum {\n"); for(i = 0; i < GCAT_COUNT; i++) @@ -1635,9 +1676,11 @@ void build_general_category_table(FILE *f) dbuf_init(dbuf); +#ifdef DUMP_TABLE_SIZE cw_count = 0; for(i = 0; i < 4; i++) cw_len_count[i] = 0; +#endif for(i = 0; i <= CHARCODE_MAX;) { v = unicode_db[i].general_category; j = i + 1; @@ -1656,9 +1699,11 @@ void build_general_category_table(FILE *f) } } // printf("%05x %05x %d\n", i, n, v); - cw_count++; n--; +#ifdef DUMP_TABLE_SIZE + cw_count++; cw_start = dbuf->size; +#endif if (n < 7) { dbuf_putc(dbuf, (n << 5) | v); } else if (n < 7 + 128) { @@ -1680,12 +1725,13 @@ void build_general_category_table(FILE *f) dbuf_putc(dbuf, n1 >> 8); dbuf_putc(dbuf, n1); } +#ifdef DUMP_TABLE_SIZE cw_len_count[dbuf->size - cw_start - 1]++; +#endif i += n + 1; } #ifdef DUMP_TABLE_SIZE - printf("general category: %d entries [", - cw_count); + printf("general category: %d entries [", cw_count); for(i = 0; i < 4; i++) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); @@ -1700,7 +1746,9 @@ void build_script_table(FILE *f) { int i, v, j, n, n1, type; DynBuf dbuf_s, *dbuf = &dbuf_s; +#ifdef DUMP_TABLE_SIZE int cw_count, cw_len_count[4], cw_start; +#endif fprintf(f, "typedef enum {\n"); for(i = 0; i < SCRIPT_COUNT; i++) @@ -1714,9 +1762,11 @@ void build_script_table(FILE *f) unicode_script_short_name + i); dbuf_init(dbuf); +#ifdef DUMP_TABLE_SIZE cw_count = 0; for(i = 0; i < 4; i++) cw_len_count[i] = 0; +#endif for(i = 0; i <= CHARCODE_MAX;) { v = unicode_db[i].script; j = i + 1; @@ -1726,9 +1776,11 @@ void build_script_table(FILE *f) if (v == 0 && j == (CHARCODE_MAX + 1)) break; // printf("%05x %05x %d\n", i, n, v); - cw_count++; n--; +#ifdef DUMP_TABLE_SIZE + cw_count++; cw_start = dbuf->size; +#endif if (v == 0) type = 0; else @@ -1750,12 +1802,13 @@ void build_script_table(FILE *f) if (type != 0) dbuf_putc(dbuf, v); +#ifdef DUMP_TABLE_SIZE cw_len_count[dbuf->size - cw_start - 1]++; +#endif i += n + 1; } -#if defined(DUMP_TABLE_SIZE) - printf("script: %d entries [", - cw_count); +#ifdef DUMP_TABLE_SIZE + printf("script: %d entries [", cw_count); for(i = 0; i < 4; i++) printf(" %d", cw_len_count[i]); printf(" ], length=%d bytes\n", (int)dbuf->size); @@ -1770,10 +1823,11 @@ void build_script_ext_table(FILE *f) { int i, j, n, n1, script_ext_len; DynBuf dbuf_s, *dbuf = &dbuf_s; - int cw_count; +#if defined(DUMP_TABLE_SIZE) + int cw_count = 0; +#endif dbuf_init(dbuf); - cw_count = 0; for(i = 0; i <= CHARCODE_MAX;) { script_ext_len = unicode_db[i].script_ext_len; j = i + 1; @@ -1784,7 +1838,9 @@ void build_script_ext_table(FILE *f) j++; } n = j - i; +#if defined(DUMP_TABLE_SIZE) cw_count++; +#endif n--; if (n < 128) { dbuf_putc(dbuf, n); @@ -1806,8 +1862,7 @@ void build_script_ext_table(FILE *f) i += n + 1; } #ifdef DUMP_TABLE_SIZE - printf("script_ext: %d entries", - cw_count); + printf("script_ext: %d entries", cw_count); printf(", length=%d bytes\n", (int)dbuf->size); #endif @@ -1829,7 +1884,7 @@ void build_prop_list_table(FILE *f) i == PROP_ID_Continue1) { /* already generated */ } else { - build_prop_table(f, i, FALSE); + build_prop_table(f, unicode_prop_name[i], i, FALSE); } } @@ -1926,7 +1981,7 @@ void check_flags(void) BOOL flag_ref, flag; for(c = 0; c <= CHARCODE_MAX; c++) { flag_ref = get_prop(c, PROP_Cased); - flag = lre_is_cased(c); + flag = !!lre_is_cased(c); if (flag != flag_ref) { printf("ERROR: c=%05x cased=%d ref=%d\n", c, flag, flag_ref); @@ -1934,7 +1989,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_Case_Ignorable); - flag = lre_is_case_ignorable(c); + flag = !!lre_is_case_ignorable(c); if (flag != flag_ref) { printf("ERROR: c=%05x case_ignorable=%d ref=%d\n", c, flag, flag_ref); @@ -1942,7 +1997,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_ID_Start); - flag = lre_is_id_start(c); + flag = !!lre_is_id_start(c); if (flag != flag_ref) { printf("ERROR: c=%05x id_start=%d ref=%d\n", c, flag, flag_ref); @@ -1950,7 +2005,7 @@ void check_flags(void) } flag_ref = get_prop(c, PROP_ID_Continue); - flag = lre_is_id_continue(c); + flag = !!lre_is_id_continue(c); if (flag != flag_ref) { printf("ERROR: c=%05x id_cont=%d ref=%d\n", c, flag, flag_ref); @@ -1964,7 +2019,7 @@ void check_flags(void) count = 0; for(c = 0x20; c <= 0xffff; c++) { flag_ref = get_prop(c, PROP_ID_Start); - flag = lre_is_id_start(c); + flag = !!lre_is_id_start(c); assert(flag == flag_ref); count++; } @@ -1981,17 +2036,23 @@ void check_flags(void) void build_cc_table(FILE *f) { - int i, cc, n, cc_table_len, type, n1; + // Compress combining class table + // see: https://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values + int i, cc, n, type, n1, block_end_pos; DynBuf dbuf_s, *dbuf = &dbuf_s; DynBuf dbuf1_s, *dbuf1 = &dbuf1_s; - int cw_len_tab[3], cw_start, block_end_pos; +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) + int cw_len_tab[3], cw_start, cc_table_len; +#endif uint32_t v; dbuf_init(dbuf); dbuf_init(dbuf1); +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cc_table_len = 0; for(i = 0; i < countof(cw_len_tab); i++) cw_len_tab[i] = 0; +#endif block_end_pos = CC_BLOCK_LEN; for(i = 0; i <= CHARCODE_MAX;) { cc = unicode_db[i].combining_class; @@ -2032,7 +2093,16 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf1, v >> 16); block_end_pos += CC_BLOCK_LEN; } +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cw_start = dbuf->size; +#endif + /* Compressed run length encoding: + - 2 high order bits are combining class type + - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte + - 00..2F: range length (add 1) + - 30..37: 3-bit range-length + 1 extra byte + - 38..3F: 3-bit range-length + 2 extra byte + */ if (n1 < 48) { dbuf_putc(dbuf, n1 | (type << 6)); } else if (n1 < 48 + (1 << 11)) { @@ -2046,10 +2116,12 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf, n1 >> 8); dbuf_putc(dbuf, n1); } +#if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) cw_len_tab[dbuf->size - cw_start - 1]++; + cc_table_len++; +#endif if (type == 0 || type == 1) dbuf_putc(dbuf, cc); - cc_table_len++; i += n; } @@ -2060,7 +2132,7 @@ void build_cc_table(FILE *f) dbuf_putc(dbuf1, v >> 16); dump_byte_table(f, "unicode_cc_table", dbuf->buf, dbuf->size); - dump_byte_table(f, "unicode_cc_index", dbuf1->buf, dbuf1->size); + dump_index_table(f, "unicode_cc_index", dbuf1->buf, dbuf1->size); #if defined(DUMP_CC_TABLE) || defined(DUMP_TABLE_SIZE) printf("CC table: size=%d (%d entries) [", @@ -2741,8 +2813,9 @@ void build_decompose_table(FILE *f) } #endif - fprintf(f, "static const uint32_t unicode_decomp_table1[%u] = {", - array_len); + total_tables++; + total_table_bytes += array_len * sizeof(uint32_t); + fprintf(f, "static const uint32_t unicode_decomp_table1[%d] = {", array_len); count = 0; for(i = 0; i <= code_max; i++) { de = &tab_de[i]; @@ -2760,8 +2833,9 @@ void build_decompose_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint16_t unicode_decomp_table2[%u] = {", - array_len); + total_tables++; + total_table_bytes += array_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t unicode_decomp_table2[%d] = {", array_len); count = 0; for(i = 0; i <= code_max; i++) { de = &tab_de[i]; @@ -2774,8 +2848,9 @@ void build_decompose_table(FILE *f) } fprintf(f, "\n};\n\n"); - fprintf(f, "static const uint8_t unicode_decomp_data[%u] = {", - data_len); + total_tables++; + total_table_bytes += data_len; + fprintf(f, "static const uint8_t unicode_decomp_data[%d] = {", data_len); for(i = 0; i < data_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -2866,8 +2941,9 @@ void build_compose_table(FILE *f, const DecompEntry *tab_de) } #endif - fprintf(f, "static const uint16_t unicode_comp_table[%u] = {", - tab_ce_len); + total_tables++; + total_table_bytes += tab_ce_len * sizeof(uint16_t); + fprintf(f, "static const uint16_t unicode_comp_table[%u] = {", tab_ce_len); for(i = 0; i < tab_ce_len; i++) { if (i % 8 == 0) fprintf(f, "\n "); @@ -3042,22 +3118,24 @@ void normalization_test(const char *filename) } #endif -int main(int argc, char **argv) +int main(int argc, char *argv[]) { const char *unicode_db_path, *outfilename; char filename[1024]; - - if (argc < 2) { - printf("usage: %s unicode_db_path [output_file]\n" - "\n" - "If no output_file is given, a self test is done using the current unicode library\n", - argv[0]); - exit(1); + int arg = 1; + + if (arg >= argc || (!strcmp(argv[arg], "-h") || !strcmp(argv[arg], "--help"))) { + printf("usage: %s PATH [OUTPUT]\n" + " PATH path to the Unicode database directory\n" + " OUTPUT name of the output file. If omitted, a self test is performed\n" + " using the files from the Unicode library\n" + , argv[0]); + return 1; } - unicode_db_path = argv[1]; + unicode_db_path = argv[arg++]; outfilename = NULL; - if (argc >= 3) - outfilename = argv[2]; + if (arg < argc) + outfilename = argv[arg++]; unicode_db = mallocz(sizeof(unicode_db[0]) * (CHARCODE_MAX + 1)); @@ -3139,6 +3217,8 @@ int main(int argc, char **argv) build_script_ext_table(fo); build_prop_list_table(fo); fprintf(fo, "#endif /* CONFIG_ALL_UNICODE */\n"); + fprintf(fo, "/* %u tables / %u bytes, %u index / %u bytes */\n", + total_tables, total_table_bytes, total_index, total_index_bytes); fclose(fo); } return 0; From 73c2058d6728e07b39001f19f5c3b80f1aa603aa Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Sat, 15 Jun 2024 13:23:36 -0400 Subject: [PATCH 2/5] upgrade emsdk, regen files --- packages/quickjs-emscripten-core/README.md | 32 +++++++++---------- .../Makefile | 4 +-- .../Makefile | 4 +-- .../Makefile | 4 +-- .../Makefile | 4 +-- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- .../Makefile | 4 +-- .../README.md | 2 +- .../src/index.ts | 2 +- templates/Variant.mk | 4 +-- 54 files changed, 90 insertions(+), 90 deletions(-) diff --git a/packages/quickjs-emscripten-core/README.md b/packages/quickjs-emscripten-core/README.md index 1c608d1f..2c99c9b9 100644 --- a/packages/quickjs-emscripten-core/README.md +++ b/packages/quickjs-emscripten-core/README.md @@ -74,7 +74,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -87,7 +87,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -100,7 +100,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -113,7 +113,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -178,7 +178,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -191,7 +191,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -204,7 +204,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -217,7 +217,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -230,7 +230,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -243,7 +243,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -256,7 +256,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -269,7 +269,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -282,7 +282,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -295,7 +295,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -308,7 +308,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -321,7 +321,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-ng-wasmfile-debug-asyncify/Makefile b/packages/variant-quickjs-ng-wasmfile-debug-asyncify/Makefile index 67792b4b..f20a5931 100644 --- a/packages/variant-quickjs-ng-wasmfile-debug-asyncify/Makefile +++ b/packages/variant-quickjs-ng-wasmfile-debug-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-ng-wasmfile-debug-sync/Makefile b/packages/variant-quickjs-ng-wasmfile-debug-sync/Makefile index 942df809..4740eae8 100644 --- a/packages/variant-quickjs-ng-wasmfile-debug-sync/Makefile +++ b/packages/variant-quickjs-ng-wasmfile-debug-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-ng-wasmfile-release-asyncify/Makefile b/packages/variant-quickjs-ng-wasmfile-release-asyncify/Makefile index 6f25e1c4..cf1cbb7e 100644 --- a/packages/variant-quickjs-ng-wasmfile-release-asyncify/Makefile +++ b/packages/variant-quickjs-ng-wasmfile-release-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-ng-wasmfile-release-sync/Makefile b/packages/variant-quickjs-ng-wasmfile-release-sync/Makefile index 845a95f3..612f89d5 100644 --- a/packages/variant-quickjs-ng-wasmfile-release-sync/Makefile +++ b/packages/variant-quickjs-ng-wasmfile-release-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-browser-debug-asyncify/Makefile b/packages/variant-quickjs-singlefile-browser-debug-asyncify/Makefile index 59de665b..ebcf2775 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-browser-debug-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-browser-debug-asyncify/README.md b/packages/variant-quickjs-singlefile-browser-debug-asyncify/README.md index 720fc977..07abec77 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-browser-debug-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-browser-debug-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-browser-debug-asyncify/src/index.ts index 180ffa2c..59ff2c33 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-browser-debug-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-browser-debug-sync/Makefile b/packages/variant-quickjs-singlefile-browser-debug-sync/Makefile index d29394f8..fd6aa97f 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-sync/Makefile +++ b/packages/variant-quickjs-singlefile-browser-debug-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-browser-debug-sync/README.md b/packages/variant-quickjs-singlefile-browser-debug-sync/README.md index b648a766..3b2b72f6 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-sync/README.md +++ b/packages/variant-quickjs-singlefile-browser-debug-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-browser-debug-sync/src/index.ts b/packages/variant-quickjs-singlefile-browser-debug-sync/src/index.ts index 08e88a94..0f73c49b 100644 --- a/packages/variant-quickjs-singlefile-browser-debug-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-browser-debug-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-browser-release-asyncify/Makefile b/packages/variant-quickjs-singlefile-browser-release-asyncify/Makefile index c92cb168..3cd331d6 100644 --- a/packages/variant-quickjs-singlefile-browser-release-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-browser-release-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-browser-release-asyncify/README.md b/packages/variant-quickjs-singlefile-browser-release-asyncify/README.md index de9cccc9..18e25022 100644 --- a/packages/variant-quickjs-singlefile-browser-release-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-browser-release-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-browser-release-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-browser-release-asyncify/src/index.ts index 0d4d822f..19b4d2cd 100644 --- a/packages/variant-quickjs-singlefile-browser-release-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-browser-release-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-browser-release-sync/Makefile b/packages/variant-quickjs-singlefile-browser-release-sync/Makefile index 32a732a2..126d6838 100644 --- a/packages/variant-quickjs-singlefile-browser-release-sync/Makefile +++ b/packages/variant-quickjs-singlefile-browser-release-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-browser-release-sync/README.md b/packages/variant-quickjs-singlefile-browser-release-sync/README.md index ea1425ab..1c708546 100644 --- a/packages/variant-quickjs-singlefile-browser-release-sync/README.md +++ b/packages/variant-quickjs-singlefile-browser-release-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-browser-release-sync/src/index.ts b/packages/variant-quickjs-singlefile-browser-release-sync/src/index.ts index ab0edbbf..7ae2a1ca 100644 --- a/packages/variant-quickjs-singlefile-browser-release-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-browser-release-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/Makefile b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/Makefile index 8f942052..14d3fb0e 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/README.md b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/README.md index 511ee721..4efcd258 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/src/index.ts index 34f4d3aa..25b5a6ce 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-cjs-debug-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-cjs-debug-sync/Makefile b/packages/variant-quickjs-singlefile-cjs-debug-sync/Makefile index 80d58dc3..6ff1adf5 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-sync/Makefile +++ b/packages/variant-quickjs-singlefile-cjs-debug-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-cjs-debug-sync/README.md b/packages/variant-quickjs-singlefile-cjs-debug-sync/README.md index f8359d06..cad502cf 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-sync/README.md +++ b/packages/variant-quickjs-singlefile-cjs-debug-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-cjs-debug-sync/src/index.ts b/packages/variant-quickjs-singlefile-cjs-debug-sync/src/index.ts index 836ac7be..cbd738c3 100644 --- a/packages/variant-quickjs-singlefile-cjs-debug-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-cjs-debug-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-cjs-release-asyncify/Makefile b/packages/variant-quickjs-singlefile-cjs-release-asyncify/Makefile index 60bcde2c..5f255c2d 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-cjs-release-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-cjs-release-asyncify/README.md b/packages/variant-quickjs-singlefile-cjs-release-asyncify/README.md index 4f96dce0..532103c9 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-cjs-release-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-cjs-release-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-cjs-release-asyncify/src/index.ts index f5e41145..5a77d114 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-cjs-release-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-cjs-release-sync/Makefile b/packages/variant-quickjs-singlefile-cjs-release-sync/Makefile index 64b76445..662861c0 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-sync/Makefile +++ b/packages/variant-quickjs-singlefile-cjs-release-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-cjs-release-sync/README.md b/packages/variant-quickjs-singlefile-cjs-release-sync/README.md index 9edd006f..e85c6210 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-sync/README.md +++ b/packages/variant-quickjs-singlefile-cjs-release-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-cjs-release-sync/src/index.ts b/packages/variant-quickjs-singlefile-cjs-release-sync/src/index.ts index 16e59f18..5bf1ea2e 100644 --- a/packages/variant-quickjs-singlefile-cjs-release-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-cjs-release-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/Makefile b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/Makefile index 71ade8d0..183191a1 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/README.md b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/README.md index 88728741..101c3089 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/src/index.ts index b3e2de40..0944812a 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-mjs-debug-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-mjs-debug-sync/Makefile b/packages/variant-quickjs-singlefile-mjs-debug-sync/Makefile index 2f8a6c99..e67720e1 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-sync/Makefile +++ b/packages/variant-quickjs-singlefile-mjs-debug-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-mjs-debug-sync/README.md b/packages/variant-quickjs-singlefile-mjs-debug-sync/README.md index 85c12f7d..18020fa2 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-sync/README.md +++ b/packages/variant-quickjs-singlefile-mjs-debug-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-singlefile-mjs-debug-sync/src/index.ts b/packages/variant-quickjs-singlefile-mjs-debug-sync/src/index.ts index c46bd42f..b77945cd 100644 --- a/packages/variant-quickjs-singlefile-mjs-debug-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-mjs-debug-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-mjs-release-asyncify/Makefile b/packages/variant-quickjs-singlefile-mjs-release-asyncify/Makefile index c6cbe624..da9c34c9 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-asyncify/Makefile +++ b/packages/variant-quickjs-singlefile-mjs-release-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-mjs-release-asyncify/README.md b/packages/variant-quickjs-singlefile-mjs-release-asyncify/README.md index 335e312d..d6b327d4 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-asyncify/README.md +++ b/packages/variant-quickjs-singlefile-mjs-release-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-mjs-release-asyncify/src/index.ts b/packages/variant-quickjs-singlefile-mjs-release-asyncify/src/index.ts index 8daf2f00..9254b8e3 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-asyncify/src/index.ts +++ b/packages/variant-quickjs-singlefile-mjs-release-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-singlefile-mjs-release-sync/Makefile b/packages/variant-quickjs-singlefile-mjs-release-sync/Makefile index 988229f6..61ba3ad5 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-sync/Makefile +++ b/packages/variant-quickjs-singlefile-mjs-release-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-singlefile-mjs-release-sync/README.md b/packages/variant-quickjs-singlefile-mjs-release-sync/README.md index d95daab0..1a1801c2 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-sync/README.md +++ b/packages/variant-quickjs-singlefile-mjs-release-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-singlefile-mjs-release-sync/src/index.ts b/packages/variant-quickjs-singlefile-mjs-release-sync/src/index.ts index 22f9658b..0bfcaa8e 100644 --- a/packages/variant-quickjs-singlefile-mjs-release-sync/src/index.ts +++ b/packages/variant-quickjs-singlefile-mjs-release-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/packages/variant-quickjs-wasmfile-debug-asyncify/Makefile b/packages/variant-quickjs-wasmfile-debug-asyncify/Makefile index c8d4dbc1..b2fa95ed 100644 --- a/packages/variant-quickjs-wasmfile-debug-asyncify/Makefile +++ b/packages/variant-quickjs-wasmfile-debug-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-wasmfile-debug-asyncify/README.md b/packages/variant-quickjs-wasmfile-debug-asyncify/README.md index 9c373882..c2c388c3 100644 --- a/packages/variant-quickjs-wasmfile-debug-asyncify/README.md +++ b/packages/variant-quickjs-wasmfile-debug-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-wasmfile-debug-asyncify/src/index.ts b/packages/variant-quickjs-wasmfile-debug-asyncify/src/index.ts index 477a6b77..17e7e2d7 100644 --- a/packages/variant-quickjs-wasmfile-debug-asyncify/src/index.ts +++ b/packages/variant-quickjs-wasmfile-debug-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/packages/variant-quickjs-wasmfile-debug-sync/Makefile b/packages/variant-quickjs-wasmfile-debug-sync/Makefile index 1f542c14..6901e950 100644 --- a/packages/variant-quickjs-wasmfile-debug-sync/Makefile +++ b/packages/variant-quickjs-wasmfile-debug-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-wasmfile-debug-sync/README.md b/packages/variant-quickjs-wasmfile-debug-sync/README.md index d426fcb8..71b6c86a 100644 --- a/packages/variant-quickjs-wasmfile-debug-sync/README.md +++ b/packages/variant-quickjs-wasmfile-debug-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/packages/variant-quickjs-wasmfile-debug-sync/src/index.ts b/packages/variant-quickjs-wasmfile-debug-sync/src/index.ts index 2d17a6ac..0f31f4ff 100644 --- a/packages/variant-quickjs-wasmfile-debug-sync/src/index.ts +++ b/packages/variant-quickjs-wasmfile-debug-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/packages/variant-quickjs-wasmfile-release-asyncify/Makefile b/packages/variant-quickjs-wasmfile-release-asyncify/Makefile index 8d208230..ff1f372a 100644 --- a/packages/variant-quickjs-wasmfile-release-asyncify/Makefile +++ b/packages/variant-quickjs-wasmfile-release-asyncify/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-wasmfile-release-asyncify/README.md b/packages/variant-quickjs-wasmfile-release-asyncify/README.md index 809fff30..0f41e6cf 100644 --- a/packages/variant-quickjs-wasmfile-release-asyncify/README.md +++ b/packages/variant-quickjs-wasmfile-release-asyncify/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-wasmfile-release-asyncify/src/index.ts b/packages/variant-quickjs-wasmfile-release-asyncify/src/index.ts index df389c43..22098f4a 100644 --- a/packages/variant-quickjs-wasmfile-release-asyncify/src/index.ts +++ b/packages/variant-quickjs-wasmfile-release-asyncify/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSAsyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | * | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/packages/variant-quickjs-wasmfile-release-sync/Makefile b/packages/variant-quickjs-wasmfile-release-sync/Makefile index 59402f6a..638eb8f0 100644 --- a/packages/variant-quickjs-wasmfile-release-sync/Makefile +++ b/packages/variant-quickjs-wasmfile-release-sync/Makefile @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts diff --git a/packages/variant-quickjs-wasmfile-release-sync/README.md b/packages/variant-quickjs-wasmfile-release-sync/README.md index 93436892..a95a36fb 100644 --- a/packages/variant-quickjs-wasmfile-release-sync/README.md +++ b/packages/variant-quickjs-wasmfile-release-sync/README.md @@ -17,7 +17,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/packages/variant-quickjs-wasmfile-release-sync/src/index.ts b/packages/variant-quickjs-wasmfile-release-sync/src/index.ts index 75015bc8..c262e01d 100644 --- a/packages/variant-quickjs-wasmfile-release-sync/src/index.ts +++ b/packages/variant-quickjs-wasmfile-release-sync/src/index.ts @@ -8,7 +8,7 @@ import type { QuickJSSyncVariant } from "@jitl/quickjs-ffi-types" * * | Variable | Setting | Description | * | -- | -- | -- | - * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | + * | library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | * | releaseMode | release | Optimized for performance; use when building/deploying your application. | * | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | * | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/templates/Variant.mk b/templates/Variant.mk index 2f809965..c4bf308b 100644 --- a/templates/Variant.mk +++ b/templates/Variant.mk @@ -1,6 +1,6 @@ # Tools -EMSDK_VERSION=3.1.51 -EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.51 +EMSDK_VERSION=3.1.59 +EMSDK_DOCKER_IMAGE=emscripten/emsdk:3.1.59 EMCC_SRC=../../scripts/emcc.sh EMCC=EMSDK_VERSION=$(EMSDK_VERSION) EMSDK_DOCKER_IMAGE=$(EMSDK_DOCKER_IMAGE) EMSDK_PROJECT_ROOT=$(REPO_ROOT) EMSDK_DOCKER_CACHE=$(REPO_ROOT)/emsdk-cache/$(EMSDK_VERSION) $(EMCC_SRC) GENERATE_TS=$(GENERATE_TS_ENV) ../../scripts/generate.ts From 6bf54e2cca742d43d95663aa90a9419059a04c66 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Sat, 15 Jun 2024 13:27:59 -0400 Subject: [PATCH 3/5] doc updates --- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../quickjs-wasmfile-debug-asyncify/README.md | 2 +- .../exports.md | 2 +- .../quickjs-wasmfile-debug-sync/README.md | 2 +- .../quickjs-wasmfile-debug-sync/exports.md | 2 +- .../README.md | 2 +- .../exports.md | 2 +- .../quickjs-wasmfile-release-sync/README.md | 2 +- .../quickjs-wasmfile-release-sync/exports.md | 2 +- doc/quickjs-emscripten-core/README.md | 32 +++++++++---------- doc/quickjs-emscripten/exports.md | 8 ++--- 34 files changed, 52 insertions(+), 52 deletions(-) diff --git a/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/README.md b/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/README.md index 47ce7706..15d1c0ed 100644 --- a/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/exports.md index 0e6aecfd..7102411b 100644 --- a/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-browser-debug-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-browser-debug-sync/README.md b/doc/@jitl/quickjs-singlefile-browser-debug-sync/README.md index 65c0ecc7..5b4f1aa5 100644 --- a/doc/@jitl/quickjs-singlefile-browser-debug-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-browser-debug-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-browser-debug-sync/exports.md b/doc/@jitl/quickjs-singlefile-browser-debug-sync/exports.md index 6120dff0..29ab609e 100644 --- a/doc/@jitl/quickjs-singlefile-browser-debug-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-browser-debug-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-browser-release-asyncify/README.md b/doc/@jitl/quickjs-singlefile-browser-release-asyncify/README.md index 21e5c6ec..36cd5931 100644 --- a/doc/@jitl/quickjs-singlefile-browser-release-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-browser-release-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-browser-release-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-browser-release-asyncify/exports.md index 162e5bde..ad4bf5dc 100644 --- a/doc/@jitl/quickjs-singlefile-browser-release-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-browser-release-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-browser-release-sync/README.md b/doc/@jitl/quickjs-singlefile-browser-release-sync/README.md index 331d0c39..63480bc7 100644 --- a/doc/@jitl/quickjs-singlefile-browser-release-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-browser-release-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-browser-release-sync/exports.md b/doc/@jitl/quickjs-singlefile-browser-release-sync/exports.md index a5b7d2b5..183ca257 100644 --- a/doc/@jitl/quickjs-singlefile-browser-release-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-browser-release-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/README.md b/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/README.md index 10095a85..35763705 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/exports.md index 33034b8e..1c7f98c0 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-cjs-debug-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-cjs-debug-sync/README.md b/doc/@jitl/quickjs-singlefile-cjs-debug-sync/README.md index 0a78154c..aed65461 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-debug-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-cjs-debug-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-cjs-debug-sync/exports.md b/doc/@jitl/quickjs-singlefile-cjs-debug-sync/exports.md index 2f0bede6..405a750d 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-debug-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-cjs-debug-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/README.md b/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/README.md index 06119796..46778d06 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/exports.md index 5ec6e711..09e98636 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-cjs-release-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-cjs-release-sync/README.md b/doc/@jitl/quickjs-singlefile-cjs-release-sync/README.md index 4af93e8d..830ed202 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-release-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-cjs-release-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-cjs-release-sync/exports.md b/doc/@jitl/quickjs-singlefile-cjs-release-sync/exports.md index 8a5a581e..eae55728 100644 --- a/doc/@jitl/quickjs-singlefile-cjs-release-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-cjs-release-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/README.md b/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/README.md index d06b3636..9e8dd352 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/exports.md index 87da2c1b..29a2b873 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-mjs-debug-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-mjs-debug-sync/README.md b/doc/@jitl/quickjs-singlefile-mjs-debug-sync/README.md index e0f65660..e5335bd3 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-debug-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-mjs-debug-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-singlefile-mjs-debug-sync/exports.md b/doc/@jitl/quickjs-singlefile-mjs-debug-sync/exports.md index 930eb7f9..dbd96da7 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-debug-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-mjs-debug-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/README.md b/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/README.md index e37622fd..4e8e77f0 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/README.md +++ b/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/exports.md b/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/exports.md index 3833131e..b75230fb 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/exports.md +++ b/doc/@jitl/quickjs-singlefile-mjs-release-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-singlefile-mjs-release-sync/README.md b/doc/@jitl/quickjs-singlefile-mjs-release-sync/README.md index 337f5f71..c1f99406 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-release-sync/README.md +++ b/doc/@jitl/quickjs-singlefile-mjs-release-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-singlefile-mjs-release-sync/exports.md b/doc/@jitl/quickjs-singlefile-mjs-release-sync/exports.md index e50c0484..63ae2cc2 100644 --- a/doc/@jitl/quickjs-singlefile-mjs-release-sync/exports.md +++ b/doc/@jitl/quickjs-singlefile-mjs-release-sync/exports.md @@ -25,7 +25,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/@jitl/quickjs-wasmfile-debug-asyncify/README.md b/doc/@jitl/quickjs-wasmfile-debug-asyncify/README.md index 863767c7..82d1fab3 100644 --- a/doc/@jitl/quickjs-wasmfile-debug-asyncify/README.md +++ b/doc/@jitl/quickjs-wasmfile-debug-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-wasmfile-debug-asyncify/exports.md b/doc/@jitl/quickjs-wasmfile-debug-asyncify/exports.md index 7d275db2..0ea386e7 100644 --- a/doc/@jitl/quickjs-wasmfile-debug-asyncify/exports.md +++ b/doc/@jitl/quickjs-wasmfile-debug-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/doc/@jitl/quickjs-wasmfile-debug-sync/README.md b/doc/@jitl/quickjs-wasmfile-debug-sync/README.md index 47487d07..0cdd9d6d 100644 --- a/doc/@jitl/quickjs-wasmfile-debug-sync/README.md +++ b/doc/@jitl/quickjs-wasmfile-debug-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: debug diff --git a/doc/@jitl/quickjs-wasmfile-debug-sync/exports.md b/doc/@jitl/quickjs-wasmfile-debug-sync/exports.md index 1fae5fbd..b370cdaa 100644 --- a/doc/@jitl/quickjs-wasmfile-debug-sync/exports.md +++ b/doc/@jitl/quickjs-wasmfile-debug-sync/exports.md @@ -25,7 +25,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/doc/@jitl/quickjs-wasmfile-release-asyncify/README.md b/doc/@jitl/quickjs-wasmfile-release-asyncify/README.md index 85d3ff64..3e85eec7 100644 --- a/doc/@jitl/quickjs-wasmfile-release-asyncify/README.md +++ b/doc/@jitl/quickjs-wasmfile-release-asyncify/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-wasmfile-release-asyncify/exports.md b/doc/@jitl/quickjs-wasmfile-release-asyncify/exports.md index 9b48ae9f..8c65262f 100644 --- a/doc/@jitl/quickjs-wasmfile-release-asyncify/exports.md +++ b/doc/@jitl/quickjs-wasmfile-release-asyncify/exports.md @@ -25,7 +25,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/doc/@jitl/quickjs-wasmfile-release-sync/README.md b/doc/@jitl/quickjs-wasmfile-release-sync/README.md index 0058bea7..0f5cb10b 100644 --- a/doc/@jitl/quickjs-wasmfile-release-sync/README.md +++ b/doc/@jitl/quickjs-wasmfile-release-sync/README.md @@ -30,7 +30,7 @@ This variant was built with the following settings: The original [bellard/quickjs](https://github.com/bellard/quickjs) library. -Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. +Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. ## Release mode: release diff --git a/doc/@jitl/quickjs-wasmfile-release-sync/exports.md b/doc/@jitl/quickjs-wasmfile-release-sync/exports.md index e1194dcd..9e5f8401 100644 --- a/doc/@jitl/quickjs-wasmfile-release-sync/exports.md +++ b/doc/@jitl/quickjs-wasmfile-release-sync/exports.md @@ -25,7 +25,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | diff --git a/doc/quickjs-emscripten-core/README.md b/doc/quickjs-emscripten-core/README.md index 8cee2e22..c9946214 100644 --- a/doc/quickjs-emscripten-core/README.md +++ b/doc/quickjs-emscripten-core/README.md @@ -104,7 +104,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -117,7 +117,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -130,7 +130,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -143,7 +143,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | ------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -208,7 +208,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -221,7 +221,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -234,7 +234,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -247,7 +247,7 @@ Variant with the WASM data embedded into a universal (Node and Browser compatibl | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -260,7 +260,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -273,7 +273,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -286,7 +286,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -299,7 +299,7 @@ Variant with the WASM data embedded into a NodeJS ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -312,7 +312,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -325,7 +325,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -338,7 +338,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | @@ -351,7 +351,7 @@ Variant with the WASM data embedded into a browser ESModule. | Variable | Setting | Description | | ------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | singlefile | The WASM runtime is included directly in the JS file. Use if you run into issues with missing .wasm files when building or deploying your app. | diff --git a/doc/quickjs-emscripten/exports.md b/doc/quickjs-emscripten/exports.md index f01b0ca6..7105b429 100644 --- a/doc/quickjs-emscripten/exports.md +++ b/doc/quickjs-emscripten/exports.md @@ -798,7 +798,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -821,7 +821,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | debug | Enables assertions and memory sanitizers. Try to run your tests against debug variants, in addition to your preferred production variant, to catch more bugs. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -1072,7 +1072,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | asyncify | Build run through the ASYNCIFY WebAssembly transform. This imposes substantial size (2x the size of sync) and speed penalties (40% the speed of sync). In return, allows synchronous calls from the QuickJS WASM runtime to async functions on the host. The extra magic makes this variant slower than sync variants. Note that both variants support regular async functions. Only adopt ASYNCIFY if you need to! The [QuickJSAsyncRuntime](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncRuntime.md) and [QuickJSAsyncContext](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSAsyncContext.md) classes expose the ASYNCIFY-specific APIs. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | @@ -1095,7 +1095,7 @@ Variant with separate .WASM file. Supports browser ESM, NodeJS ESM, and NodeJS C | Variable | Setting | Description | | -- | -- | -- | -| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-01-13+626e0d4e](https://github.com/bellard/quickjs/commit/626e0d4e60db2b81a0505fa9c61941e608624e7e) vendored to quickjs-emscripten on 2024-02-11. | +| library | quickjs | The original [bellard/quickjs](https://github.com/bellard/quickjs) library. Version [2024-02-14+36911f0d](https://github.com/bellard/quickjs/commit/36911f0d3ab1a4c190a4d5cbe7c2db225a455389) vendored to quickjs-emscripten on 2024-06-15. | | releaseMode | release | Optimized for performance; use when building/deploying your application. | | syncMode | sync | The default, normal build. Note that both variants support regular async functions. | | emscriptenInclusion | wasm | Has a separate .wasm file. May offer better caching in your browser, and reduces the size of your JS bundle. If you have issues, try a 'singlefile' variant. | From d9702716a5d4efc11585ca58e629a00cc4d551bb Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Sat, 15 Jun 2024 13:46:37 -0400 Subject: [PATCH 4/5] auto apply patches after pull --- package.json | 3 ++- vendor/quickjs-patches/0166-webkit-wasm.patch | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 vendor/quickjs-patches/0166-webkit-wasm.patch diff --git a/package.json b/package.json index 802a56da..49d0a381 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,9 @@ "clean": "git clean -dfx ./build && yarn for-each-package clean", "prettier": "prettier --write .", "vendor:quickjs:subtree": "git subtree $ACTION --prefix=vendor/quickjs --squash git@github.com:bellard/quickjs.git master", - "vendor:quickjs:pull": "ACTION=pull yarn vendor:quickjs:subtree", + "vendor:quickjs:pull": "ACTION=pull yarn vendor:quickjs:subtree && yarn vendor:quickjs:patch", "vendor:quickjs:add": "ACTION=add yarn vendor:quickjs:subtree", + "vendor:quickjs:patch": "git apply vendor/quickjs-patches/*", "vendor:ng:subtree": "git subtree $ACTION --prefix=vendor/quickjs-ng --squash git@github.com:quickjs-ng/quickjs.git master", "vendor:ng:pull": "ACTION=pull yarn vendor:ng:subtree", "vendor:ng:add": "ACTION=add yarn vendor:ng:subtree", diff --git a/vendor/quickjs-patches/0166-webkit-wasm.patch b/vendor/quickjs-patches/0166-webkit-wasm.patch new file mode 100644 index 00000000..a8c4da65 --- /dev/null +++ b/vendor/quickjs-patches/0166-webkit-wasm.patch @@ -0,0 +1,20 @@ +diff --git a/vendor/quickjs/quickjs.c b/vendor/quickjs/quickjs.c +index f000ff74..fa7742a2 100644 +--- a/vendor/quickjs/quickjs.c ++++ b/vendor/quickjs/quickjs.c +@@ -32053,6 +32053,7 @@ static void push_short_int(DynBuf *bc_out, int val) + dbuf_putc(bc_out, OP_push_0 + val); + return; + } ++#if !defined(__EMSCRIPTEN__) // Workaround for WebKit WASM https://github.com/justjake/quickjs-emscripten/issues/166 + if (val == (int8_t)val) { + dbuf_putc(bc_out, OP_push_i8); + dbuf_putc(bc_out, val); +@@ -32063,6 +32064,7 @@ static void push_short_int(DynBuf *bc_out, int val) + dbuf_put_u16(bc_out, val); + return; + } ++#endif // !defined(__EMSCRIPTEN__) + #endif + dbuf_putc(bc_out, OP_push_i32); + dbuf_put_u32(bc_out, val); From 0824b996abf1f54e150f821f5be2e02c15c1335e Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Sat, 15 Jun 2024 13:46:45 -0400 Subject: [PATCH 5/5] patch arm issue --- vendor/quickjs/quickjs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vendor/quickjs/quickjs.c b/vendor/quickjs/quickjs.c index f000ff74..fa7742a2 100644 --- a/vendor/quickjs/quickjs.c +++ b/vendor/quickjs/quickjs.c @@ -32053,6 +32053,7 @@ static void push_short_int(DynBuf *bc_out, int val) dbuf_putc(bc_out, OP_push_0 + val); return; } +#if !defined(__EMSCRIPTEN__) // Workaround for WebKit WASM https://github.com/justjake/quickjs-emscripten/issues/166 if (val == (int8_t)val) { dbuf_putc(bc_out, OP_push_i8); dbuf_putc(bc_out, val); @@ -32063,6 +32064,7 @@ static void push_short_int(DynBuf *bc_out, int val) dbuf_put_u16(bc_out, val); return; } +#endif // !defined(__EMSCRIPTEN__) #endif dbuf_putc(bc_out, OP_push_i32); dbuf_put_u32(bc_out, val);