TLDR;
-
I propose dropping the
onEventName
-style event handling in Node library bindings in favor of usingeventNameHandle
-style event handling (covered below) -
I’m announcing bindings to the
http2
NPM module, whichs build on top of the above idea.
onEventName
vs eventNameHandle
Many of the types we use in Node extend EventEmitter
and operate via callbacks: Stream
, ChildProcess
, HttpServer
, etc. The way we typically write FFI for these events is solely via the on
function.
-- PureScript code
onEventName
:: EventEmitterType
-> (Maybe Error -> String -> Effect Unit)
-> Effect Unit
onEventName v cb = runEffectFn2 onEventNameImpl v $ mkEffectFn2 \err s ->
cb (toMaybe err) s
foreign import onEventNameImpl :: EffectFn2 (EventEmitterType) (EffectFn2 (Nullable Error) String Unit) (Unit)
// JavaScript code
export const onEventName = (value, cb) => value.on("eventName", cb);
This approach comes with two downsides that affect all current Node bindings
-
we prevent users from removing these callback at a later time, either after their first call (e.g.
once
) or programmatically (e.g.off
) -
we force users to add listeners to the end of the underlying listeners array
In purescript-node-event-emitter
, I wrote bindings that allow library authors to provide an idiomatic PureScript interface to the underlying JavaScript callback while allowing end-users to decide which callback-adding function to use: on
, once
, prependListener
, or prependOnceListener
. Moreover, end-users can remove added listeners via the subscribe
variants. Since these callbacks tend to follow a pattern, I defined some utility types like EventHandle2
Here are some examples of this approach:
- Library author:
node-streams
library implementing its events - End-users: tests using both
node-streams
andnode-net
events - the current test in
http2
I propose updating all Node libraries to use the eventHandle
API for handling events. This would be a breaking change (albeit a small one) across all Node libraries.
For those using the Node.js backend to build things, would this change be desired?
HTTP2 bindings
I’ve also written bindings to the the http2
module (excluding only the Compatibility API) based on the above eventNameHandle
-style. The purescript-node-http2 repo (not yet published) uses custom forks of node-streams
, node-net
, and bindings I wrote for node-tls
that all use the eventNameHandle
-style above. While the tests for the http2
repo are still lacking, the bindings should otherwise be sound.
Any feedback on the http2
bindings and my above proposal would be appreciated.