-
-
Notifications
You must be signed in to change notification settings - Fork 599
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
fix(node-resolve): do not ignore exceptions #564
fix(node-resolve): do not ignore exceptions #564
Conversation
as not being able to resolve the id is a valid output
this was passing before because the real error was being ignored
packages/node-resolve/src/index.js
Outdated
if (/\0/.test(importer)) { | ||
// handle cases like common-js plugin which has form | ||
// \u0000<id>?commonjs-proxy | ||
importer = importer.slice(1); |
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.
not sure if there's a better way to handle this case?
If you remove this change you'll see the pkg.browser with mapping to prevent bundle by specifying a value of false
test fail because the call to resolveId
with the null byte is not allowed
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.
That one is a really good question that got overlooked so far. I do not agree with the solution, though. Files starting with \0
are under the sole maintenance of some plugin, and we should not make assumptions about what the part behind the \0
means.
I think a valid approach might be to treat the importer like undefined
, which is the value that gets passed for entry points. At least for the commonjs plugin, this should work nicely as all imports from those proxy files are fully resolved absolute paths anyway, and I would expect the same from other plugins as well.
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 valid approach might be to treat the importer like undefined, which is the value that gets passed for entry points
@lukastaegert I pushed a commit to do this
test('deduplicates modules from the given root directory', async (t) => { | ||
const bundle = await rollup({ | ||
input: 'index.js', | ||
input: './packages/package-a/index.js', |
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.
this was causing an error because the input could not be found. It should be relative to the rootDir
right?
I'm a bit confused. I didn't see anywhere that you presented a specific use case, or your specific frontal-accident with this plugin... Was it trying to somehow resolve modules that are actually internal commonjs proxies? Or was it just the importer being a commonjs proxy that broke things? And are you now throwing the errors, failing the whole pipeline - or emitting warnings? (Because I see you removed the original try-catch, instead of altering it) |
Hi @danielgindi
The thing I was trying to do which caused me to stumble into this was the linked PR. I was looking to make builtin modules be treated as external.
Maybe I should have been clearer in the description, but the exact cause of the problem was that a builtin module id would currently cause
There isn't the global handler anymore that converts errors to null. IMO |
@tjenkinson so basically avoid having to specify extra About the exceptions- I'm not sure I agree. Also- removing the catch is a BREAKING CHANGE in that manner, and you did not mark it as one in the intro ;) |
yep this was the idea (but I decided to keep that separate to this PR)
Happy to put the catch back and log a warning in there if people would prefer that. However IMO as a developer I'd want there to be a blocker if something unexpected went wrong. Especially when some of the options like
Yeh I wasn't sure on this. I'm fine with it being breaking (or putting the catch back but with at least a warning log :) ). Also disabling that catch for tests would be nice. |
I guess we need more opinions here
Btw, if only addings warnings to rollup, you could look at other test (i.e in commonjs) - some of them test for the existing of a warning. |
In my opinion a failure to resolve a module should result in an error and not into making the module an external, that's something that confuses users a lot currently. However this is not something that should be handled by the node resolve plugin, it should be on the level of rollup. There could be multiple plugins who resolve an id, and node-resolve shouldn't block further resolving. |
AFAIK this becomes a warning from rollup if all Also by "failure to resolve a module" do you mean a controlled failure such as the module not existing, or both controlled and uncontrolled failures like the file system throwing an error?
Also agree. The question is if an unexpected error occurs internally to the plugin, should we propagate this up to rollup, or convert this to |
An unexpected error should result in a failure, but I thought the try/catch catches errors thrown by the |
Yep it looks that way, but IMO it's clearer to handle a module not being found in the main code path as an expected case (which is what this PR does), not the exception path. When I started my PR to support automatically making builtins external, I was surprised when my code wasn't running because we were silently ending up in that catch block as the result of trying to read I guess I could take a different approach, and put the logic in the catch block to see if it's a builtin module, but that doesn't feel nice. |
I agree that this big catch was really bad for testing, but the general idea of course was that when this plugin cannot resolve a module, other resolvers should get a chance to do so before throwing. So the question to me is that is not entirely clear to me from looking at the code: Will this still be the case for all "relevant" cases? And by that I mean it is definitely ok to throw if there is a weird file system error or some error that results from data in an unexpected format being passed to this plugin. If you think this is the case, we could try to release this fix but be prepared to do a quick rollback in case we missed something important here.
@LarsDenBakker If you say so, we can talk about this, could be a change in the next major version. Personally, I like this behaviour for quick prototyping, but if it confuses newcomers, then that is bad. Rollup could augment the error with instructions on how to mark the specific import as external to solve the issue. I also think a lot of the woes that make this feature helpful is that builtins are not marked as external when using the |
From my understanding yes it will. I've gone through everything that was in the try block looking at what could throw and nothing jumps out. The one I'd like confirmation on is if (options.modulesOnly) {
const code = await readFile(resolved, 'utf-8');
if (isModule(code)) {
return {
id: `${resolved}${importSuffix}`,
moduleSideEffects: hasModuleSideEffects(resolved)
};
}
return null;
} Do we need to check a file at
Yeh that's what I started here but thought I'd defer that until after this one. |
Looking at what this option is supposed to be doing and the current implementation, I am leaning towards file-not-found errors should also return |
Done. Wondering if if (/\0/.test(importer)) {
importer = undefined;
} is a breaking change? |
Hard to say. I am not aware of any official plugins for which this would be breaking, but it is possible for third party plugins. |
Soooooo. I think this PR is ready to go? Don't see any other suggestions/concerns atm. |
Here is the next PR to make builtins external :) |
Rollup Plugin Name:
node-resolve
This PR contains:
Are tests included?
Breaking Changes?
If yes, then include "BREAKING CHANGES:" in the first commit message body, followed by a description of what is breaking.
Description
recommend viewing with indentation disabled on github
I was looking to add a feature to return
false
fromresolveId
for builtins whenpreferBuiltins
was enabled but noticed code wasn't running that I was expecting. I will follow up with this in a different PR (which I'll rebase that when this PR is finished).There was a
try/catch
which was ignoring any exception and returningnull
fromresolveId
. I tried removing that block and it caused test failures, and was why my changes weren't working 😱.I fixed the hidden issues to make the tests pass again. The 'root-dir' test looked like it was a bug in the test itself so I updated that test.
I think it would be better to let any unexpected errors throw out from
resolveId
and fail a build instead of silently converting them to anull
return. If you'd like that back maybe we can figure out a way to have that logic disabled for tests.