-
Notifications
You must be signed in to change notification settings - Fork 78
Description
What is the Problem Being Solved?
Currently, mapNodeModules()
accepts a policy, which—if present—it uses to omit ModuleDescriptor
s from the resulting CompartmentDescriptor.module
. Specifically, if a package policy exists for the package being crawled, it will only add ModuleDescriptor
entries for those packages (which are dependencies) mentioned in the policy. If no package policy is found, then all dependencies are added.
Compartment Map Transform
I'm proposing a new concept: the Compartment Map Transform.
The Compartment Map Transform accepts a CompartmentMapDescriptor
and options (including policy), performs operations on the CompartmentMapDescriptor
, then returns it (probably easiest to actually mutate it in-place since the object is rather deep). Async transforms can be supported unless there's a specific reason not to.
mapNodeModules()
would accept a new option, compartmentTransforms
of type CompartmentMapTransformFn[]
. Before resolving, mapNodeModules()
would apply each of these in order, returning the final result.
For backwards compatibility, the default value of compartmentTransforms
should be an array containing a new transform which mimics the current behavior (considering package policy) by omitting values from the CompartmentMapDescriptor.modules
objects. We can call this function enforcePolicyCompartmentMapTransform
for lack of a better idea. This function will be included in the public API so that users can concatenate it with other transforms. translateGraph()
would change such that it is no longer in the business of checking policy.
Optional New Transform
While we can omit ModuleDescriptor
s based on policy, it'd be nice to be able to create ModuleDescriptor
s based on policy! Currently, ModuleDescriptor
s are not created without an associated entry in the dependency graph.
In the case of dynamic imports/requires, a situation arises wherein a package A instructed by package B to load package C. There is no other relationship between package A and package C; there is no dependency relationship described in the package descriptor(s).
Example: a legacy ESLint config, where ESLint (B) loads an
.eslintrc
file (A) which is configured to use a the@endo/ses
plugin (C).
I'd like to create a new transform (and maybe even provide it from @endo/compartment-mapper
) which would create ModuleDescriptor
references in the CompartmentMapDescriptor
based on the presence of a canonical name (mapping to an extant CompartmentDescriptor
) within package policy.
This transform would not create new
CompartmentDescriptor
s, because in the example, all of the packages live in the dependency graph somewhere.
Such a transform may be functionally equivalent to the solution in #2893, as I expect it will need to flip retained
bits.
Description of the Design
-
A Compartment Map Transform could look like this:
/** * @template T Base options bag * @template U Specific options bag */ export type CompartmentMapTransformFn<T = MapNodeModulesOptions> = <U extends T = T>(compartmentMap: CompartmentMapDescriptor, options?: U) => CompartmentMapDescriptor | Promise<CompartmentMapDescriptor>;
The generics are here to allow association of a discrete transform with a specific set of options. Put another way, you could define a
CompartmentMapTransformFn
that only works withmapNodeModules()
or functions accepting its options. -
Provide an internal helper function to apply a
CompartmentTranformFn[]
to aCompartmentMapDescriptor
. -
Prior to returning in
mapNodeModules()
, call helper function -
Implement a transform which omits keypairs from
CompartmentDescriptor.modules
based on policy and updatetranslateGraph()
accordingly
Security Considerations
n/a
Scaling Considerations
n/a
Test Plan
Hopefully we have a test that would catch a regression here, as this is intended to be backwards-compatible. Otherwise there should be nothing special about the tests.
Compatibility Considerations
n/a
Upgrade Considerations
- Mention in
NEWS.md
- Consider tutorial or example documentation