quickjs_runtime 0.4.8
quickjs_runtime: ^0.4.8 copied to clipboard
Pure-Dart QuickJS JavaScript runtime on dart:ffi with synchronous host callbacks. Vendored QuickJS 2024-01-13 + a C bridge with JSON marshaling.
0.4.8 #
- Fix the ubuntu CI isolate flake (silent
undefinedevals): the Dart VM migrates an isolate to a different OS thread once it is not pinned inside an FFI call. QuickJS anchors its stack-overflow limit (rt->stack_top - stack_size) to the thread that created the runtime, so an eval running on a migrated thread compared its stack pointer against an unrelated address range and failed at parse time with a spuriousSyntaxError: stack overflow. Rendering that error overflows again, soJS_ToCStringreturned NULL and the failure surfaced as a silentundefined/nulleval result — the intermittentasync_engine_pool/cross_runtime_conformancefailures on ubuntu-latest. The bridge now callsJS_UpdateStackTopat every JS entry point (qjs_eval,qjs_execute_pending_jobs[_capped]), which Dart's one-runtime-per-isolate discipline makes race-free. Verified via CI instrumentation on the failing runner: the wedged exception readsSyntaxError: stack overflowat eval depth 0.
0.4.7 #
- Windows (MSVC) link fix: called unconditionally, but the decimal support (, i.e. CONFIG_BIGNUM) is not compiled — MS linker fails with LNK2019 (macOS silently tolerates the dangling reference in a dylib, which is why it went unnoticed). The call is now guarded by ; is never TRUE on that path without it (the sole TRUE caller, , is itself guarded). Zero behavior change.
0.4.6 #
- Windows (MSVC) build fix, part 4: use -HUGE_VAL / HUGE_VAL instead of -1.0 / 0.0 and 1.0 / 0.0 in js_math_min_max (C2124). After 0.4.5 the MSVC compile reports exactly this one diagnostic.
0.4.5 #
- Windows (MSVC) build fix, part 3: neutralize the single-trailing-underscore GCC spelling (used by upstream on ) in the shim, and use instead of under (C2124). After 0.4.4 the full MSVC compile is down to these two diagnostics.
0.4.4 #
- Windows (MSVC) build fix, part 2: force
DIRECT_DISPATCH 0for_MSC_VER(quickjs.c) — MSVC has no computed goto / labels-as-values, soJS_CallInternaluses the plainswitchdispatch (same as the Emscripten build; identical semantics, slightly slower interpreter). Addssize_t(intptr_t) to the MSVC shim (msvc_compat.h); MSVC has no POSIXssize_t, which brokeJS_DumpMemoryUsage. - Verification upgraded from a plain-clang
_MSC_VERsimulation (which silently accepts GNU extensions such as labels-as-values) to clang-cl/Zs(MSVC driver mode from Homebrew LLVM) over all six translation units plus a standalone harness for thesys/time.hshim: 0 errors.
0.4.3 #
- Windows (MSVC) build fix:
native_toolchain_cresolvescl.exeon GitHub Actionswindows-latest, which cannot compile the vendored GCC-oriented QuickJS 2024-01-13 sources directly. On Windows only, the build hook now force-includesnative/quickjs/msvc/msvc_compat.h(sys/time.h+gettimeofdayshim,alloca/strdup, GCC atomic builtins on_Interlocked*intrinsics,isnan/isfinite, GNU__attribute__neutralized) and prependsnative/quickjs/msvcto the include path. The vendored sources gained_MSC_VER-guarded branches (compound-literal-freeJS_MKVAL/JS_MKPTR/JS_NANconstructors, packed structs via#pragma pack,clz/ctzvia_BitScanReverse, stack-pointer probe via_AddressOfReturnAddress); clang/GCC builds see zero changes. Tradeoff: on Windows,Atomics.*/SharedArrayBufferfutex-style waiting stays disabled (it requires pthreads), matching single-threaded QuickJS builds.
0.4.2 #
hook/build.dart: pass-Wl,-z,max-page-size=16384on Android (Google Play 16 KB page-size alignment gate) and-headerpad_max_install_names+-install_name @rpath/libquickjs_bridge.dylibon iOS/macOS (App Store Connect / TestFlight framework embedding and codesign reproducibility).
0.4.1 #
- Widen
code_assets(>=1.2.0 <3.0.0) andhooks(>=1.0.0 <3.0.0) constraints so apps pinningcode_assets ^1.2.0(e.g.flutter_gemma_litertlm) resolve cleanly without changing their lockfile.
0.4.0 #
- Dart & Flutter Native Assets (
hook/build.dart):quickjs_runtimenow compilesquickjs_bridge.cand QuickJS 2024-01-13 automatically viacode_assets+native_toolchain_con iOS, Android, macOS, Linux, and Windows, binding symbols via@DefaultAssetand@NativeFFI functions. Apps anddart test/flutter testno longer need manualtool/build_quickjs.shruns ordlopenpath lookups (while keepingJSR_QUICKJS_LIBandDynamicLibrary.open(libraryPath)as fallbacks). - Added
QuickjsFfi.isAvailableto probe whether the native asset or pre-built shared library is ready.
0.3.6 #
- Bytes host functions:
QuickjsRuntime.registerHostBytesFn(name, cb)+qjs_register_bytes_fnin the C bridge — JS callsname(typedArray), Dart receives a zero-copy(name, Uint8List)view with no JSON marshal, no base64, no string copies (the view is valid for the call's duration). Older native libraries degrade:hasBytesFnis false and the call returns false — callers fall back to the JSON/base64 path. - Powering
jsr.hostCallBinary(name, typedArray)in js_widget_runtime (per-frame bulk data: transforms, particles, audio levels).
0.3.4 #
Added #
AsyncEnginePool.attachMainRuntimeaccepts a per-runtimedispatchContextprovider: therunAsyncdispatch path now captures context per main engine (overriding the pool-level default), so a shared pool can serve main engines whose dispatch context differs per engine (script directory, job params, ...). Explicitdispatch( context: ...)still wins over both providers. Consumer-opaque, must be SendPort-safe (plain JSON-ish values).
0.3.3 #
- Conformance fixture v2: byte-identical cross-runtime script with
Buffer/URL/utilExtras/osProcess/events/fetchShapes/parallel sections
plus a timer-protocol family (
actionTimers+drainTimers). util: legacy Node predicates —isArray,isString,isNumber,isBoolean,isNull,isUndefined,isFunction.util.inspect: strings are now always single-quoted (Node semantics).util.format: extra string args inserted raw; non-strings inspected (previously everything was JSON.stringify-ed).
0.3.2 #
Fixes the native-library path join for pub.dev (hosted) checkouts:
the package_config fallback built
<root>native/quickjs/libquickjs_bridge.so without a separator when
rootUri has no trailing slash (hosted) — workers died with
Failed to load dynamic library ...0.3.1native/.... Also mirrors the
stringified-env shim into the async prelude (require('os')). No API
changes.
0.3.1 #
Restores the sync fetch and timers / microtask auto-drain /
require('events') features: their stacked PRs (#7, #8) were merged
out-of-band and their commits were not part of the main tree the
0.3.0 tarball was published from — the 0.3.0 section below documents
the intended surface, but only 0.3.1 actually ships it. Internally the
async surface now lives in its own prelude
(node_compat_async.dart); require('events')/require('os')
registration moved from the core builtin map into that prelude. No
other API or behavior changes.
0.3.0 #
-
Sync
fetch(opt-in):NodeCompatConfig.httpFetchhook + realHeaders/Response(text()/json()/arrayBuffer(),bodyUsed,ok/status/headers); failures surface asTypeError: fetch failedwithcause. Bodies are plain values, soawait res.text()works through them;AbortSignalis not supported (documented deviation). Without the hook,fetchstays a self-documenting stub — the runtime remains I/O-clean. -
Real timers + microtask auto-drain + events: promise reactions,
queueMicrotaskandprocess.nextTicknow actually run — the QuickJS pending-job queue is drained (capped) after every successful eval.setTimeout/setInterval/setImmediate+clear*are real, host-driven callbacks viaNodeCompatHandle.drainTimers()inready(default, UI-safe) /block(sleeps until the nearest reffed timer — CLI "setTimeout as sleep") /nonemodes, withunref(), a callback-count guard and a wall-clock budget.require('events')provides the full synchronousEventEmitter. -
Node parity pack (issue #3 follow-up): real
Buffer(Uint8Array subclass, Node encodings + LE/BE accessors),URL/URLSearchParams(WHATWG subset verified against real Node),console.time/table/group/count/dir/trace, Node-styleutil.inspect,os+url+bufferbuiltin modules,process.argv/pid/hrtime/uptime/memoryUsage/stdout/stderr/on('exit'),__filename/__dirname(+NodeCompatHandle.setScriptPath), typeof-safeIntlstubs. Default text codecs are now real UTF-8 (dart:convert) — the latin-1 approximation is gone;Bufferremoved from tier-2 stubs;installNodeCompatreturns aNodeCompatHandle. -
Node/js compat layer (issue #3), opt-in via
installNodeCompat(rt, cfg):- Tier 1 — real:
global,console.*(pluggable sink),process(env/platform/arch/version/exitCode/cwd/exit),path(posix subset),assert(node-like subset),util(subset),TextEncoder/TextDecoder(utf-8),atob/btoa,performance.now(),crypto.randomUUID()/getRandomValues(),structuredClone(JSON fidelity),require()builtin registry + consumer modules (installNodeCompatModule) + fallback to a pre-existing loader. - Tier 2 — self-documenting stub:
AbortController—typeof-safe, throws the alternative on call (fetch has no signal support yet). - Host hooks: env, cwd, clock, secure random, utf-8/base64 codecs, console sink, exit notification. Without hooks, safe defaults.
- Tier 1 — real:
0.2.0 #
AsyncEnginePool: pre-spawned engine-worker isolates for parallel JavaScript execution over the synchronous host-callback bridge. Consumer owns the worker body (top-levelAsyncWorkerMainwith anAsyncWorkerLinknext/complete protocol, or a simplerAsyncJobExecutorone-engine-per-job hook); the pool owns transport and lifecycle — dispatch/wait mailbox protocol (pthreads condvar vianative_synchronization), FIFO backpressure, fire-and-forget envelope caching, dead-worker error completion.runAsync(fn, args)scripting surface:AsyncEnginePool.attachMainRuntimeregisters the__jsrDispatchHost/__jsrWaitHosthost functions and the prelude exposingrunAsync/AsyncJob/runAsync.allwith a blockingwait().runAsyncJobOnRuntime: runs one dispatched (closure-free) function on a consumer-wired runtime and returns itsAsyncJobEnvelope.
0.1.0 #
- Initial release: QuickJS 2024-01-13 runtime on
dart:ffiwith synchronous host callbacks (NativeCallable). QuickjsRuntime: eval (JSON results),registerHostFunction,setGlobal,executePendingJobs,close.QuickjsFfi: flat C ABI bindings toquickjs_bridge.c(JSON marshaling).tool/build_quickjs.shbuildslibquickjs_bridge.so(gcc); lookup viaJSR_QUICKJS_LIB,.dart_tool/package_config.json, script dir, or cwd.