spawn 0.1.1
spawn: ^0.1.1 copied to clipboard
Background execution for Dart that works everywhere - isolates on native, Web Workers on the web, one API. The missing web half of dart:isolate.
Changelog #
0.1.1 #
Three ways a message could go missing, and the response direction learning to transfer.
-
Native transfer never actually transferred. The payload matcher compared
ByteBuffers withidentical, and on the VM every.bufferaccess on internal typed data allocates a fresh wrapper — soidentical(u.buffer, u.buffer)is false and no match ever fired. The designed transfer machinery had been dead code since it shipped, silently: the fallback delivers identical bytes, so every test asserting content passed. Now compared with==, which on the VM asks about the backing store's identity — the question actually being asked — and on the web degrades toidenticalunchanged. -
Native now transfers one level into a Map, which is the shape every worker returning bytes actually produces (
{'rgba': bytes, ...}). The web backend had always walked a Map's values; native only matched a whole-payload buffer, so the same worker transferred on web and took the plain isolate-send path on native, per frame, with nothing to show for it. -
New
SpawnReply: a request handler can now name buffers to move rather than clone on the way BACK. The request direction has hadtransfer:from the start; the response direction had none, so a worker returning a decoded frame paid a full W×H×4 structured clone on the receiving thread — 3.7 MB at 720p, 29.5 MB at 5K. -
Web: a message the worker cannot deserialize is no longer lost in silence. The browser fires
messageerroron the worker's global scope instead ofmessage, with no data at all, so the request simply never arrived — no reply, no error, and the host waited out its timeout. Seen on an iPad, where every request carrying a transferredVideoFramevanished this way while every other request was answered. The correlation id is inside the data the browser could not clone, so the report cannot name the request: every request in flight fails with the reason and the worker is KEPT, because the worker is fine and the next portable message will be delivered as usual. -
Web: an error AFTER the worker loaded is no longer dropped. Only failure to START was handled, so an uncaught throw inside a running worker left the request it was serving unanswered with no diagnosis anywhere. It is now treated like a clone failure — fail what is in flight with the browser's message, keep the worker.
0.1.0 #
First release.
spawn(entry)starts a worker on an isolate (native) or a compiled Web Worker payload (web) behind one API, and completes only once the handler is running.Worker/WorkerClient:post,request, a broadcasteventsstream buffered until its first listener, graceful and forcedclose, andattach()for additional clients of one worker.WorkerChannel:messages,send,handleRequests,initialMessage,onClose.- One portability contract on every platform — the portable set, or
WireMessage— so a message that works on the VM works in a browser. - A documented 12-byte wire envelope with a
WireRegistry, andSpawnEntry.protocolto register a protocol's decoders on both ends. transfer:lists: a real move on the web, and a skipped copy on native for byte payloads.SpawnCaps.zeroCopyTransferreports which you got.SpawnServicelifetimes with pluggable, reference-countedServiceProviders and an error at spawn time that names the missing registration.spawnLocalruns a handler in process behind a realWorker, for tests and as the web debug fallback when a payload has not been built.dart run spawn:buildcompileslib/workers/*.dartto web payloads, with content-hash skipping. No code generation and no build_runner.JobEntryparses and validates;Jobs.enqueuethrows until deferred, OS-scheduled work lands.SpawnEntry.nativeis reserved for a C- or wasm-hosted worker and throws.PlatformValuecarries an opaque platform object - aVideoFrame,AudioData,ImageBitmap,OffscreenCanvas- through a channel untouched. It always transfers rather than clones, including from a request response, because most of those types cannot be cloned at all. This is what lets a decode worker hand finished frames to the main thread.spawn:buildskips files in the worker directory that declare nomain, so a worker can sit next to its conditional-import stubs and helpers, and its up-to-date check now covers path dependencies. A payload that ignored changes to a sibling package under active development is worse than no caching at all: the tests pass against code that is no longer there.