Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose underlying hooks #215

Closed
ghost opened this issue Jul 14, 2024 · 2 comments
Closed

Expose underlying hooks #215

ghost opened this issue Jul 14, 2024 · 2 comments

Comments

@ghost
Copy link

ghost commented Jul 14, 2024

Issue

My loader analyzes a full module graph during load to determine module shape (the set of exported names). Walking the whole graph is necessary because wildcard exports can add unspecified names. You've got to walk the full graph to determine the names for one module.

export const value = 1
export * from './source.mjs'

To ensure I'm using the full semantics of active CLI options, feature changes across versions, etc plus semantics changes provided by underlying loaders (such as TypeScript transpilation), I use the nextResolve and nextLoad routines in the analysis. They're extracted by the resolve and load hooks.

async function resolve (specifier, context, next) {
  // Retain resolver for analysis
  gear.resolve ??= next
  ...
async function load (locator, context, next) {
  // Retain loader for analysis
  gear.load ??= next
  ...

I see in the code that these routines actually mutate internal state for the particular import operation they were extracted from. Analysis for a single load may apply these routines to hundreds of modules with all different URLs and context properties. Analysis runs concurrently so many operations are in flight together. So far this doesn't seem to be causing problems, but I'm concerned it's an unsupported use and may break in the future.

When attributes come into use, I wonder if they'll start to drift across concurrent operations.

 * @param {object} meta Properties that change as the current hook advances
 * along the chain.
ObjectAssign(meta.context, context);
if (output?.shortCircuit === true) { meta.shortCircuited = true; }

Solution

My loader would like a supported way to run resolve and load of the underlying loaders, independent of any import operations, and capable of running concurrently. Maybe they could be passed to initialize.

function initialize (port, resolve, load) {
  gear.resolve = resolve
  gear.load = load
  ...
@GeoffreyBooth
Copy link
Member

Would the startGraph hook as described in #205 suit your use case?

@ghost
Copy link
Author

ghost commented Jul 14, 2024

Amazing. Yes, it seems to handle everything, even conditions. I was also hoping to get access to the CJS load and it would even provide that. Currently I have that piece fudged.

I'm closing these since they both seem covered.

@ghost ghost closed this as completed Jul 14, 2024
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant