js_widget_runtime
Run JavaScript widgets as Flutter widgets using QuickJS (VM) or Web Workers (web).
0.4.79
3.6K downloads/mo
#4328 most downloaded on pub.dev
IstiN/flutter_js_widget_runtime
What this package is like to depend on
Last release 4 days ago
19 Aug 2026
Ships fairly regularly
a new release about every 8 days
Nearly every release is documented
notes for 78 of 81 stable releases
Nothing withdrawn
no release was ever pulled
1 months old
81 releases · first in 2026
81 releases in the last 12 months
see the full history below
Release timeline
81 releases · Jul 2026 to Aug 2026Releases
latest 60 of 81-
0.4.7919 Aug 2026Release notes
Open source →The 0.4.75 iid tagging made the bootstrap's __tag helper reference __IID
unconditionally, but the web worker script never declared it — every
widget message threw 'ReferenceError: __IID is not defined' and JS
widgets on the web client hung on the loading spinner (engine loaded,
renderer built, first render never arrived).Fix: inject at the top of the
generated worker script (before sendMessage definition and the shared
bootstrap). Contract test asserts the declaration order and the __tag
reference.Release notes
Open source →- fix(web): declare __IID before the shared bootstrap in the web worker
script — the 0.4.75 iid tagging made
__tagreference__IIDunconditionally, but the web worker never declared it, so every widget message threwReferenceError: __IID is not definedand JS widgets on the web client hung on the loading spinner (engine loaded, renderer built, first render never arrived).
- fix(web): declare __IID before the shared bootstrap in the web worker
script — the 0.4.75 iid tagging made
-
0.4.7819 Aug 2026 -
0.4.7719 Aug 2026 -
0.4.7619 Aug 2026 -
0.4.7519 Aug 2026Release notes
Open source →The default JsWidgetEngine backend (flutter_js) is JavaScriptCore on
macOS but a QuickJS plugin .so on Linux, which CI does not build — the
repro failed there at engine startup. These tests also need live network
(wttr.in), so they stay a local-macOS diagnostic.Release notes
Open source →- fix(engine): cross-engine message routing on macOS JSC — flutter_js
registers the native
sendMessagecallback as a STATIC, so every new runtime overwrites it and ALL live JS contexts dispatch through the LAST runtime's channel map. With several engines alive (a board with multiple widgets), one widget's fetch/render messages were delivered to a neighbour widget — e.g. the weather widget stayed on its loading spinner forever while its data rendered inside another widget (deterministic two-engine repro test included). The bootstrap now tags every message payload with the engineiid; a Dart-side router (installed into every live channel map) delivers each message to its owning engine and strips the tag before handlers run. QuickJS backend (per-engine native routing) only unwraps raw-id channels.
- fix(engine): cross-engine message routing on macOS JSC — flutter_js
registers the native
-
0.4.7419 Aug 2026 -
0.4.7318 Aug 2026 -
0.4.7218 Aug 2026 -
0.4.7118 Aug 2026 -
0.4.7018 Aug 2026Release notes
Open source →- fix(engine): SIGSEGV on widget dispose — native runtime release moved from
scheduleMicrotask(same event-loop turn) toFuture.delayed(Duration.zero)(next turn), with a finalexecutePendingJob()drain before the release. flutter_js resolves promise bridges via microtasks (future.then→evaluate), so a microtask-scheduled release could free the JSContextGroup while a sibling microtask was still about to evaluate into it, crashing inJSValueToStringCopywith a deadJSC::VM. Applies to bothdispose()and the old-runtime release path inrun().
- fix(engine): SIGSEGV on widget dispose — native runtime release moved from
-
0.4.6918 Aug 2026 -
0.4.6818 Aug 2026 -
0.4.6718 Aug 2026 -
0.4.6618 Aug 2026 -
0.4.6518 Aug 2026 -
0.4.6418 Aug 2026 -
0.4.6317 Aug 2026Nothing published for this version
-
0.4.6217 Aug 2026 -
0.4.6115 Aug 2026 -
0.4.6015 Aug 2026 -
0.4.5815 Aug 2026 -
0.4.5715 Aug 2026 -
0.4.5615 Aug 2026 -
0.4.5515 Aug 2026 -
0.4.5414 Aug 2026 -
0.4.5314 Aug 2026 -
0.4.5214 Aug 2026 -
0.4.5014 Aug 2026 -
0.4.4914 Aug 2026 -
0.4.4814 Aug 2026 -
0.4.4714 Aug 2026 -
0.4.4514 Aug 2026Release notes
Open source →- Perf: micro-optimizations in JS bootstrap:
- Monotonic counter for IDs instead of Math.random()+Date.now()
- Reusable argument joiner for console.log (avoids Array.slice alloc)
- setTimeout uses one-shot Timer instead of periodic
- Manual JSON string building for timer/RAF messages (avoids JSON.stringify)
- Perf: micro-optimizations in JS bootstrap:
-
0.4.4412 Aug 2026Release notes
Open source →- Fix JS widget cross-engine leaks on macOS/JSC:
- callEvent is now synchronous (skips __jsr_event_done round-trip)
- Render trees tagged with __iid, routed to correct panel
- requestAnimationFrame tagged with __iid for game loop routing
- _isLive guard + try/catch on callEvent to prevent SIGSEGV on disposed runtime
- Fix JS widget cross-engine leaks on macOS/JSC:
-
0.4.4312 Aug 2026Nothing published for this version
-
0.4.4212 Aug 2026Release notes
Open source →- Fix callEvent deadlock: _handleEventDone was nulling _eventCompleter before _runEvent could complete it. On macOS (merged thread), JSC bridge callback fires DURING rt.evaluate() inside send(). Nulling the completer meant _runEvent's await never completed.
-
0.4.4112 Aug 2026Nothing published for this version
-
0.4.4012 Aug 2026 -
0.4.3912 Aug 2026 -
0.4.3812 Aug 2026 -
0.4.3712 Aug 2026 -
0.4.3612 Aug 2026 -
0.4.3512 Aug 2026Release notes
Open source →- Fix SIGSEGV: defer old runtime release until AFTER new runtime init completes (was releasing during init via scheduleMicrotask, which ran between evaluate() calls and freed the old JSContextGroup out from under in-flight native callbacks).
- Reduce callEvent timeout from 30s to 5s — a single stuck event was blocking ALL widget interactions for 30 seconds.
-
0.4.3412 Aug 2026Release notes
Open source →- Fix dispose: use scheduleMicrotask instead of Future.delayed(Duration.zero) to avoid event-loop ordering issues that caused widgets to get stuck in loading state.
-
0.4.3312 Aug 2026Release notes
Open source →- Fix SIGSEGV: defer native JSContextGroup release to the next event-loop turn. During run() → dispose() → evaluate(), the current stack may still be inside executePendingJob() which holds native JSC callbacks. Releasing the context synchronously freed the JSContextGroup out from under those in-flight callbacks → crash in JSValueToStringCopy.
-
0.4.3211 Aug 2026Release notes
Open source →- Fix 3D host-flip: remember per-sceneId host selection so controllers recreated after a callEvent timeout route to the same host (Flame3dHost stays Flame3dHost) even when the renderer-side config lacks engine/src.
-
0.4.3102 Aug 2026 -
0.4.3002 Aug 2026 -
0.4.2902 Aug 2026 -
0.4.2802 Aug 2026 -
0.4.2702 Aug 2026 -
0.4.2602 Aug 2026 -
0.4.2501 Aug 2026 -
0.4.2429 Jul 2026Release notes
Open source →- feat(3d):
unlit: trueon declarative scene3d model entries — swaps the loaded GLB's SpatialMaterial for an UnlitMaterial with the same albedo, so flat brand marks (logos, UI panels) render at their exact colors instead of being dimmed by the scene light rig.
- feat(3d):
-
0.4.2127 Jul 2026Release notes
Open source →- fix(3d): the 3D host dispatcher reference-counts shared controllers — when a scene3d node unmounts and remounts within the same frame (per-frame scene rebuilds in video pipelines), the new State's initState runs before the old State's dispose; previously the late dispose killed the controller the new State had just acquired, leaving the scene permanently empty for the rest of the export.
-
0.4.2026 Jul 2026Release notes
Open source →- fix(3d): headless capture mounts the game tree manually and renders the world's children directly — an unmounted FlameGame renders and updates nothing (frozen skeletal animations, unregistered lights, invisible scenes), and a vanilla world renderTree never reached Object3D children in offscreen capture (empty GPU pass).
- fix(3d): teardown races — disposed-controller guards and a MediaQuery-free World3D (pixel ratio explicit) so final-frame capture can't crash.
- feat(3d): headless GLB rendering for the flame_3d host — offscreen capture path renders the scene into a GPU render target and composites it into any canvas (video export / board snapshots), replacing the old headless placeholder. Requires Impeller + Flutter GPU enabled by the embedder.
- feat(3d): declarative
scene3dconfigs —models: [{modelId, src, position, rotation, scale, animation}]+camera+timeapplied idempotently on every rebuild (diff-only), so video pipelines that re-render the node tree per frame can drive GLB scenes frame-accurately. - feat(3d):
Js3dCaptureSyncpending-work tracker lets headless renderers wait for GPU init / model loads before capturing a frame. - fix(3d): transparent scene background (Flame's opaque black default no longer covers layers composited behind the 3D scene).
- fix(3d): no more build→apply→notify→rebuild loop when declarative configs are applied on every widget rebuild; disposed-controller release guard; idempotent controller dispose (unmount/remount + final tree teardown).
-
0.4.1926 Jul 2026 -
0.4.1826 Jul 2026 -
0.4.1726 Jul 2026 -
0.4.1626 Jul 2026 -
0.4.1526 Jul 2026