-
Notifications
You must be signed in to change notification settings - Fork 16
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
Add hook for manifest loading #44
base: main
Are you sure you want to change the base?
Conversation
I think in general the issue was that we needed to keep the total number of hooks minimal in order to make chaining work, hence the big PR to collapse what we had before to |
I think I'd need to see what this helper API would look like - I'm worried if every loader has to reimplement the whole |
It sounds like we're describing sub-hooks of |
I’m not saying the decision has been made; it’s just that that’s my assumption of the direction we’re going based on the last big PR and on #26. I think there are arguments for the “lots of little hooks” approach too, but we would need a way to make it work with chaining. What would it mean to chain a theoretical |
Updated this PR to be mentioned in the chaining proposals, as per #48 (comment). Should be ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a bit of preamble is needed describing the somewhat unique challenges this attempts to solve. Without, these seem like extra hooks.
Co-authored-by: Derek Lewis <DerekNonGeneric@inf.is>
Co-authored-by: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com>
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thank you!
@GeoffreyBooth should there be an example of each of these and how they might work together in a chain? (resolve and load have them)
Speaking of that, I wonder if there's perhaps some redundancy in the way the chaining doc is written. Given that hooks all share the same "pattern" for a given proposal, whether it's for middleware or iterative approach, shouldn't the design overview list what are the general input/output of each hook (without taking the chaining into account), and the chaining docs describe how hooks are composed on a generic level? In its current state, it feels like there aren't many significant differences between the |
I think the reason we did that for For instance, what if package |
The chaining doc was written to just have two full examples, of a chain of One thing we do have to spec out is how hooks connect to each other. I was recently working on import assertions, which currently happen inside the This is one way to add a new hook without breaking the ability for hooks to be chainable. Being completely separate from this pipeline, the way |
Can you detail why that would be a bad thing? In my mind, hooks like |
Maybe it wouldn’t be, but it would certainly complicate users’ ability to order their loaders. Say you have loaders A, B, and C, where A is first. When A’s |
I opened an implementation draft on the Node repository: nodejs/node#41076 |
@arcanis I finally reviewed nodejs/node#41076. Sorry for delay, and I look forward to discussing it tomorrow. A few general notes:
As I wrote in nodejs/node#41076 (comment), I think the next step would be a PR against this repo with some more Markdown files: some background about monkey-patching |
Can you write one such loader, that we have a baseline for comparison? As far as I know, the
Isn't it documented in this very PR? There aren't that many other examples due to the lack of simple primitives (Electron & PnP are the main ones I have in mind, because our projects are amongst the rare to have the bandwidth to maintain our own virtual fs implementations), but those capabilities are foundational in both cases. |
This should work: export function resolve(specifier, context, next) {
if(specifier.endsWith('?sha512') || specifier.endsWith('-sha512.mjs')) {
const hash = calculateHash(specifier);
return { url:`data:text/javascript,export%20default${encodeURI(JSON.stringify(hash)}`, format:'module' };
}
return next(specifier, context);
} Maybe a loader that supports resolving inside a |
@aduh95 as far as I can tell this loader isn't sufficient; since the result is a data-url, Node won't treat it the same as regular files. For instance, if you have an import hash from 'pkg/hash'; {
"name": "pkg",
"exports": {
"./hash": "./index-sha512.mjs"
}
}
Basically, the use case is that from Node's perspective, nothing should separate the virtual files from true files, they should have the exact same semantic, and go through the exact same code path. Failing that, they'll be guaranteed to have diverging resolution behaviors and edge cases. |
I would like for this to work: export function resolve(specifier, context, defaultResolve) {
const nextResult = defaultResolve(specifier, context);
if (nextResult.url.endsWith('?sha512') || nextResult.url.endsWith('-sha512.mjs')) {
const hash = calculateHash(nextResult.url);
return {
url: `data:text/javascript,export%20default${encodeURI(JSON.stringify(hash))}`,
format: 'module',
};
}
return nextResult;
} But unfortunately
Not sure how you mean, it's still a module with a default export that contains the information you seek (Node.js should treat data-url modules same as regular files imo).
I believe that, I'm still not convinced a hashing loader is the best example for the use case though. |
The |
But it's not: turning a path into a data url is a lossy process, since you go from location + data to just data. Here's another easy way to break it: imagine we return a virtual file that contains Perhaps it could be workaround by encoding special types of URL (so that instead of returning a data url with the file content, we instead return a data url with a special payload containing the missing information), but it'd be very fragile and prone to break. Footnotes
|
@arcanis that is not correct 🙂 See test-esm-loader.mjs → virtual file (which uses this loader). |
During the September meeting I mentioned how we would benefit from having a way to tell Node how to load package.json files, as in our case they don't necessarily exist on the disk. I think it was reasonably well received, so I open this PR to try to see what would be the next step (cc @bmeck who raised some points around security).