esm: add `deregister` method
TBD
- refactor hooks internals – remove
chains
in favor ofloaderInstances
; there is a tiny performance penalty when going through any given chain (since there's a conditional branch now and possibly extra iterations up to the total number of loaders) but i think this is negligible compared to the usability increase – there is now a default loader calleddefault_loader
that is registered like any other as node's internal one and only one array instead of several. the logic for adding/removing loaders is significantly simpler now. - change the return type of
register
– previously it returned whateverinitialize
did. @aduh95 noted that we should return a "loader handle" or a symbol to the loader instead of the initialize result which is what i've done here. i managed to make returning a symbol work across the thread gap. i am not 100% sold on symbol vs some kind of loader object which was also suggested (a thing that had a deregister method); i am still concerned about loader authors being able to pass initialization data back if it's somehow useful to them. N.B. this seems kind of like an 11th hour change now that 20.6.0 is imminent and the loaders API is being marked somewhat stable. - allow hook methods to receive a fourth state argument – so instead of returning the result of
initialize
and discard it, we now keep the result attached to the loader instance. this value is then fed back to hook invocations. after thinking about the comments in https://github.com/nodejs/loaders/issues/147 this actually seems necessary if there can be an arbitrary number of "copies" of any given loader; how can loaders differentiate their internal state from one another? there isn't a good way without something like this. - add
deregister
– this builds on the first two changes; the first one makes it sensible/trivial to remove existing loaders, and the second makes it possible for the user to actually be able to reference an individual loader which is necessary for removal
Suggestion from @GeoffreyBooth.
Adds deregister
method on node:module
that looks like this:
type Deregister = (id: string) => boolean;
Modifies the initialize hook to look like this:
type Initialize = (data: any, meta: {id: opaque}) => Promise<any>;
Internally registered instances of hooks are now tracked. This is so they can be removed later. The id of the registered instance is now passed to the initialize
hook which can then be passed back to the caller of register
.
// Loader
export const initialize = (_data, meta) => {
return meta.id;
}
// Caller
import {register, deregister} from "node:module";
const id = register(...);
// ...
deregister(id);