Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions deps/quickjs-release.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
QUICKJS_NG_REPO="quickjs-ng/quickjs"
QUICKJS_NG_TAG="v0.16.2"
QUICKJS_NG_TARBALL_URL="https://api.github.com/repos/quickjs-ng/quickjs/tarball/v0.16.2"
QUICKJS_NG_RELEASE_URL="https://github.com/quickjs-ng/quickjs/releases/tag/v0.16.2"
QUICKJS_NG_RELEASED_AT="2026-08-20T12:22:52Z"
QUICKJS_NG_TAG="v0.17.0"
QUICKJS_NG_TARBALL_URL="https://api.github.com/repos/quickjs-ng/quickjs/tarball/v0.17.0"
QUICKJS_NG_RELEASE_URL="https://github.com/quickjs-ng/quickjs/releases/tag/v0.17.0"
QUICKJS_NG_RELEASED_AT="2026-09-18T21:39:55Z"
5 changes: 4 additions & 1 deletion deps/quickjs/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ jobs:

- name: Setup Alpine
if: ${{ matrix.config.arch != '' }}
uses: jirutka/setup-alpine@v1
uses: quickjs-ng/setup-alpine@master
with:
arch: ${{ matrix.config.arch }}
packages: "build-base make cmake git"
apk-tools-url: https://raw.githubusercontent.com/quickjs-ng/apk-for-ci/refs/heads/master/apk.static#!sha256!34bb1a96f0258982377a289392d4ea9f3f4b767a4bb5806b1b87179b79ad8a1c

- name: uname
run: uname -a
Expand Down Expand Up @@ -469,6 +470,8 @@ jobs:
wasmtime run build/qjs -qd
echo "console.log('hello wasi!');" > t.js
wasmtime run --dir . build/qjs t.js
wasmtime run --dir . build/qjs --stack-size 64K tests/wasi-stack-limit.js
wasmtime run --dir . build/qjs tests/wasi-stack-limit.js
- name: build wasi reactor
run: |
cmake -B build -DQJS_BUILD_WERROR=ON -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake -DQJS_WASI_REACTOR=ON
Expand Down
3 changes: 2 additions & 1 deletion deps/quickjs/.github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
arch: [aarch64, armv7, riscv64, x86, x86_64]
steps:
- uses: actions/checkout@v7
- uses: jirutka/setup-alpine@v1
- uses: quickjs-ng/setup-alpine@master
with:
# mimalloc v3 (mimalloc3-dev) lives in the edge testing repo; enable it.
# riscv64 has no v3 build there, so it falls back to mimalloc2-dev.
Expand All @@ -37,6 +37,7 @@ jobs:
extra-repositories: |
http://dl-cdn.alpinelinux.org/alpine/edge/testing
packages: "build-base make cmake ${{ matrix.arch == 'riscv64' && 'mimalloc2-dev' || 'mimalloc3-dev' }}"
apk-tools-url: https://raw.githubusercontent.com/quickjs-ng/apk-for-ci/refs/heads/master/apk.static#!sha256!34bb1a96f0258982377a289392d4ea9f3f4b767a4bb5806b1b87179b79ad8a1c
- name: build
shell: alpine.sh {0}
run: |
Expand Down
13 changes: 6 additions & 7 deletions deps/quickjs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
_WASI_EMULATED_SIGNAL
)
add_link_options(
-Wl,-z,stack-size=2097152
-lwasi-emulated-process-clocks
-lwasi-emulated-signal
)
Expand Down Expand Up @@ -285,6 +286,9 @@ list(APPEND qjs_defines _GNU_SOURCE)
if(WIN32)
# NB: Windows 7 is EOL and we are only supporting in so far as it doesn't interfere with progress.
list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0601)
else()
# UNIX-y platforms.
list(APPEND qjs_libs m)
endif()
if(TVOS)
list(APPEND qjs_defines _TVOS)
Expand All @@ -298,12 +302,6 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "WASI")
list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT})
endif()

# try to find libm
find_library(M_LIBRARIES m)
if(M_LIBRARIES OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC")
list(APPEND qjs_libs m)
endif()

add_library(qjs ${qjs_sources})
target_compile_definitions(qjs PRIVATE ${qjs_defines})
target_include_directories(qjs PUBLIC
Expand Down Expand Up @@ -448,14 +446,15 @@ if(NOT EMSCRIPTEN)
target_link_libraries(run-test262 PRIVATE qjs)
endif()

# Interrupt test
# C API tests
#

add_executable(api-test
api-test.c
)
target_compile_definitions(api-test PRIVATE ${qjs_defines})
target_link_libraries(api-test PRIVATE qjs)
add_qjs_libc_if_needed(api-test)

add_executable(lre-test
lre-test.c
Expand Down
2 changes: 1 addition & 1 deletion deps/quickjs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

BUILD_DIR=build
BUILD_DIR?=build
BUILD_TYPE?=Release
INSTALL_PREFIX?=/usr/local

Expand Down
153 changes: 150 additions & 3 deletions deps/quickjs/api-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include "quickjs.h"
#include "quickjs-libc.h"
#include "cutils.h"

static JSRuntime *new_runtime(void)
Expand Down Expand Up @@ -175,9 +176,7 @@ static void cfunctions(void)
static int timeout_interrupt_handler(JSRuntime *rt, void *opaque)
{
int *time = (int *)opaque;
if (*time <= MAX_TIME)
*time += 1;
return *time > MAX_TIME;
return (*time)++ > MAX_TIME;
}

static void sync_call(void)
Expand Down Expand Up @@ -238,6 +237,38 @@ static void async_call(void)
JS_FreeRuntime(rt);
}

static void std_eval_interrupt_handler(void)
{
static const char code[] =
"import * as std from 'std'; std.evalScript('for(;;){}')";
JSRuntime *rt = new_runtime();
js_std_init_handlers(rt);
JSContext *ctx = JS_NewContext(rt);
js_init_module_std(ctx, "std");
int time = 0;
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
JSValue ret =
JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
ret = js_std_await(ctx, ret);
assert(time > MAX_TIME);
assert(JS_IsException(ret));
ret = JS_GetException(ctx);
assert(JS_IsError(ret));
// uncatchable "interrupted" exception is turned into a regular exception
assert(!JS_IsUncatchableError(ret));
const char *str = JS_ToCString(ctx, ret);
assert(str != NULL);
assert(strstr(str, "InternalError: interrupted"));
JS_FreeCString(ctx, str);
JS_FreeValue(ctx, ret);
uintptr_t interrupt_handler = js_std_cmd(/*GetInterruptHandler*/5, rt);
uintptr_t interrupt_opaque = js_std_cmd(/*GetInterruptOpaque*/6, rt);
assert(interrupt_handler == (uintptr_t)timeout_interrupt_handler);
assert(interrupt_opaque == (uintptr_t)&time);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}

static JSValue save_value(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
Expand Down Expand Up @@ -650,6 +681,19 @@ static void utf16_string(void)
JS_FreeCString(ctx, s);
JS_FreeValue(ctx, e);
}
{
// create wide char slice string, see JS_STRING_SLICE_LEN_MAX
JSValue v = eval(ctx, "`\\uD800\\uDC00`.repeat(8192).slice(0, -1)");
assert(!JS_IsException(v));
size_t n;
const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v);
assert(u);
assert(n == 2*8192-1);
assert(u[0] == 0xD800);
assert(u[1] == 0xDC00);
JS_FreeCStringUTF16(ctx, u);
JS_FreeValue(ctx, v);
}
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}
Expand Down Expand Up @@ -1019,6 +1063,47 @@ static void backtrace_oom_callsite_array(void)
JS_FreeRuntime(rt);
}

static void large_allocation_accounting(void)
{
static const size_t block_size = 1024 * 1024;
JSMemoryUsage before, after;
JSValue ret, exception;
JSRuntime *rt;
JSContext *ctx;
const char *str;

rt = new_runtime();
ctx = JS_NewContext(rt);

JS_ComputeMemoryUsage(rt, &before);
ret = eval(ctx, "globalThis.a = new Uint8Array(1024 * 1024)");
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
JS_ComputeMemoryUsage(rt, &after);
assert(after.malloc_size - before.malloc_size >= (int64_t)block_size);

JS_ComputeMemoryUsage(rt, &before);
JS_SetMemoryLimit(rt, (size_t)before.malloc_size + 4 * block_size);
ret = eval(ctx, "globalThis.a = [];\n"
"for (let i = 0; i < 64; i++)\n"
" a.push(new Uint8Array(1024 * 1024));");
assert(JS_IsException(ret));
JS_SetMemoryLimit(rt, 0);
JS_ComputeMemoryUsage(rt, &after);
assert(after.malloc_size - before.malloc_size < (int64_t)(8 * block_size));

exception = JS_GetException(ctx);
assert(JS_IsError(exception));
str = JS_ToCString(ctx, exception);
assert(str);
assert(!strcmp(str, "InternalError: out of memory"));
JS_FreeCString(ctx, str);
JS_FreeValue(ctx, exception);

JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}

static void backtrace_oom_current_exception(void)
{
static const char setup_code[] =
Expand Down Expand Up @@ -2052,6 +2137,64 @@ void add_intrinsic_bigint(void)
JS_FreeRuntime(rt);
}

void new_typed_array(void)
{
JSValueConst argv[4];
JSRuntime *rt = new_runtime();
JSContext *ctx = JS_NewContext(rt);
uint8_t *buf = js_malloc(ctx, 8);
JSValue ab = JS_NewArrayBuffer(ctx, buf, 8, /*max_len*/0, NULL, NULL, false);
assert(JS_IsArrayBuffer(ab));
for (int argc = 0; argc < (int)countof(argv); argc++) {
JSValue ret = JS_NewTypedArray(ctx, argc, argv, JS_TYPED_ARRAY_UINT8);
assert(!JS_IsException(ret));
assert(JS_IsObject(ret));
JS_FreeValue(ctx, ret);
argv[argc] = JS_UNDEFINED;
argv[0] = ab;
}
JS_FreeValue(ctx, ab);
js_free(ctx, buf);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}

void private_symbols(void)
{
JSRuntime *rt = new_runtime();
JSContext *ctx = JS_NewContext(rt);
JSValue pub = JS_NewSymbol(ctx, "public", /*is_global*/false);
JSValue priv = JS_NewPrivateSymbol(ctx, "private");
assert(JS_IsSymbol(pub));
assert(JS_IsSymbol(priv));
JSValue obj = JS_NewObject(ctx);
assert(JS_IsObject(obj));
assert(true == JS_SetPropertyValue(ctx, obj, pub, JS_TRUE, JS_PROP_C_W_E));
assert(true == JS_SetPropertyValue(ctx, obj, priv, JS_FALSE, JS_PROP_C_W_E));
JSValue global_object = JS_GetGlobalObject(ctx);
assert(true == JS_SetPropertyStr(ctx, global_object, "o", JS_DupValue(ctx, obj)));
JS_FreeValue(ctx, global_object);
JSValue result = eval(ctx, "Object.getOwnPropertySymbols(o)");
assert(JS_IsArray(result));
int64_t length = -1;
assert(0 == JS_GetLength(ctx, result, &length));
assert(length == 1);
JSValue item = JS_GetPropertyUint32(ctx, result, 0);
assert(JS_IsSymbol(item));
assert(JS_IsSameValue(ctx, item, pub));
JS_FreeValue(ctx, item);
JS_FreeValue(ctx, result);
result = JS_GetPropertyValue(ctx, obj, JS_DupValue(ctx, pub));
assert(JS_IsBool(result));
assert(JS_IsSameValue(ctx, result, JS_TRUE));
result = JS_GetPropertyValue(ctx, obj, JS_DupValue(ctx, priv));
assert(JS_IsBool(result));
assert(JS_IsSameValue(ctx, result, JS_FALSE));
JS_FreeValue(ctx, obj);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}

int main(void)
{
cfunctions();
Expand All @@ -2071,6 +2214,7 @@ int main(void)
dump_memory_usage();
new_errors();
dom_exception_added_twice();
large_allocation_accounting();
backtrace_oom_current_exception();
backtrace_oom_callsite_array();
proxy_own_keys_huge_length();
Expand All @@ -2089,5 +2233,8 @@ int main(void)
get_class_name();
object_from();
add_intrinsic_bigint();
new_typed_array();
std_eval_interrupt_handler();
private_symbols();
return 0;
}
2 changes: 1 addition & 1 deletion deps/quickjs/builtin-array-fromasync.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_builtin_array_fromasync_size = 888;

const uint8_t qjsc_builtin_array_fromasync[888] = {
0x1b, 0xc5, 0x39, 0x53, 0x3c, 0x0e, 0x01, 0x28,
0x1c, 0xc5, 0x39, 0x53, 0x3c, 0x0e, 0x01, 0x28,
0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0xb7, 0x61,
0x73, 0x79, 0x6e, 0x63, 0x49, 0x74, 0x65, 0x72,
0x61, 0x74, 0x6f, 0x72, 0x01, 0x2a, 0x4f, 0x62,
Expand Down
Loading
Loading