Releases: WebReflection/coincident
v2
Breaking Changes
- there is no CommonJS anymore ... this whole stack is modern Web standards based, no
require
possible also because top-level await is mandatory - both
uhtml
andserver
exports are on hold ... as I think uhtml was unnecessary and I need to better refactor the server-side story too - provided exports are now explicit:
- you refer to
/main
suffix for things needed to bootstrap on the main thread - you refer to
/worker
suffix for things needed to bootstrap on the worker thread
- you refer to
- exports provide slightly different namespaces when
coincident()
is invoked:- it was pointless to have
isWindowProxy
on the main thread as hard-coded() => false
- it was pointless to have a
window
at all on the main thread as it was referring to thewindow
itself - it was ugly and error prone to magic-guess if the
self
or global context was a Worker or not - it was ugly and less powerful to pass along already initialized Worker instances ... the
Worker
class now does bootstrap correctly itself while still extending the nativeWorker
class provided by the environment - the
Worker
class also ensure that worker wasn't already bootstrapped and somehow "ruined" or polluted elsewhere before being passed tocoincident(worker)
utility
- it was pointless to have
- the
Worker
used on the main thread MUST be the one provided by coincident after invoking it. This guarantee a unique and secure crypto CHANNEL for any operation between that constructor and its instances, once created. - the worker bootstrap is now asynchronous and it needs to be awaited. This is a no brainer though, because ...
- the worker is always type module now. Don't bother overriding the
type
with passed options, it will always be a standard module with top level await enabled by default too. - if no window is used, even if the import points at the
coincident/window/worker
, the worker can always expose utilities that can then be consumed by the main thread.
Background
As explained in my previous MR, I was not happy at all about the initial super-hacky way things landed, even if proven to be very robust, and yet very hard to maintain, debug, or improve ... I really needed to do some refactoring!
Despite the intrinsic complexity required and handled by this module though, things are now way cleaner or easier to reason about than before, also easier to document, extend, track or debug in the future ... it's a piece of cake now and I can easily eat it too 😋
Some breaking change was necessary, although the underlying functionality is still in place except it's much better than before:
- cleaner and faster than ever
- better tested and never ambiguous
- SharedArrayBuffer works regardless of mini-coi or server headers (sabayon polyfills all the things, enabling optional ServiceWorker integration that mini-coi couldn't before)
- bootstrap dance is more predictable
- everything is based on ESM due mandatory top level
await
needed to make this module happen
Unfortunately though, for the time being extra exports such as uhtml or server are not in here yet, but arguably nobody cared about the uhtml one and very few understood or used the server one ... my intent is to likely ditch uhtml export but still ship the server/main and server/worker exports after also refactoring that initial PoC that worked wonders but it wasn't nearly as elegant as the current solution.
That's it, that's the TL;DR version of this major update; keep reading if interested in knowing more.
How to test v2
npm install --save coincident@next
This is currently an RC2 but I am confident things will land sooner than later as official v2.
I need to test dozen things before landing this officially but this module is at the core of both Polyscript and PyScript projects, hence things might move fast enough.
How to use v2
This is the raw coincident export:
// main thread
import coincident from 'coincident/main';
const { Worker } = coincident();
const w = new Worker('./worker.js');
w.proxy.test = () => {
console.log('test');
};
// worker thread
import coincident from 'coincident/worker';
const { proxy } = await coincident();
proxy.test();
This is the coincident/window export:
// main thread
import coincident from 'coincident/window/main';
const { Worker } = coincident();
const w = new Worker('./worker.js');
w.proxy.test = () => {
console.log('test');
};
// worker thread
import coincident from 'coincident/window/worker';
const { proxy, window } = await coincident();
proxy.test();
console.log(window.location.href);
The main exports has Worker
, proxy
, polyfill
and transfer
in it, where Worker is the one you should use to bootstrap a coincident Worker, proxy
is where you use or expose utilities, polyfill
is a boolean value that returns true
if the environment has been polyfilled and transfer
is the utility to transfer buffers across worlds.
The worker exports has proxy
, polyfill
and transfer
, where proxy
is where you use or expose utilities, polyfill
is a boolean value that returns true
if the environment has been polyfilled and transfer
is the utility to transfer buffers across worlds.
When it comes to window
exported reference, and isWindowProxy
counter part, it means you are using the coincident/window
export and you can reach any main window
property or class and check for isWindowProxy
too behind the scene, yet only on workers as it has no meaning in the real window
related world.
Refactoring Details
- the window proxy is now elegantly provided by js-proxy which is 100% code covered, tested against memory leaks, wrote to be as fast as possible by design
- the "maybe available" SharedArrayBuffer issue has been fully solved via sabayon which guarantee functionality with or without special headers enabled and it allows people to provide their Service Worker as long as they add sabayon features
Reflect
related traps a part, and secured CHANNELS created at runtime viacrypto.getRandomUUID()
, also increasing both security and portability of the project, all possible value types are now represented as[int32, value]
key/value pairs convention, reducing the amount of memory needed to pass complex structures around and simplifying also bothstringify
andparse
JSON like operations