Attachments
Attachments are special objects which are allowed to be moved between app / worker threads.
In Web Workers, there are two types of objects allowed across worker boundaries -- structured cloneables and transferables.
Cloneables are what they sound like -- objects that are copied when being sent to / from the target worker.
Transferables are essentially a performance optimization. Instead of a value being copied, its ownership is passed over to the target worker, and attempts to access the value in the sending script will see a null value.
Kobweb workers push users to use serialization for their messages, which may work fine in most cases, but it can cause a noticeable, even multi-second stutter for very sizable objects (like large bitmaps). By attaching these objects to the message being posted to the worker, we can avoid converting some values to large strings and then back again.
Not every object can be sent between scripts. To constrain users from sending unsupported types, we require users create an Attachment
instance using a Attachments.Builder.
Unlike default JS APIs, which just send an array of transferables, we require the user to specify the name of each object, as an added layer of safety.
// Sender
worker.postMessage(message, Attachments { add("bitmap", bitmap) })
// Receiver
internal class TransferableWorkerFactory : WorkerFactory<String, String> {
override fun createStrategy(postOutput: OutputDispatcher<String> -> Unit) = WorkerStrategy<String> { input ->
val bitmap = attachments.getImageBitmap("bitmap")
...
}
override fun createIOSerializer() = createPassThroughSerializer()
}
Not every object in the web is transferable / cloneable, so the add
methods and get
methods are appropriately typed to constrain what you can register and fetch.
Note that arrays are actually not transferable, but we add support for them here anyway, doing the conversion to their underlying ArrayBuffer
ourselves to avoid the users having to write a bunch of boilerplate to do this themselves.