-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
fixes #933 : JSPackager deduplication now accounts for differences in absolute dependency paths #1011
fixes #933 : JSPackager deduplication now accounts for differences in absolute dependency paths #1011
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1011 +/- ##
==========================================
+ Coverage 86.35% 88.53% +2.17%
==========================================
Files 68 68
Lines 3541 3366 -175
==========================================
- Hits 3058 2980 -78
+ Misses 483 386 -97
Continue to review full report at Codecov.
|
src/packagers/JSPackager.js
Outdated
const dedupKey = asset => { | ||
// cannot rely only on generated JS for deduplication as paths like `../` can | ||
// cause 2 identical JS files to be different depending on filesystem locations | ||
return { |
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.
We cannot use objects as keys for the dedupe map - they will never match since JS compares keys by object identity. You'll need to generate a string key.
@devongovett addressed your review comments and refactored to use |
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.
Would be awesome if you could add a test. Let me know if you would like any help with that!
src/packagers/JSPackager.js
Outdated
// cannot rely *only* on generated JS for deduplication because paths like | ||
// `../` can cause 2 identical JS files to behave differently depending on | ||
// where they are located on the filesystem | ||
let deps = Array.from(asset.dependencies.keys()).map(dep => |
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.
Instead of using asset.dependencies
here, you could use asset.depAssets
which is a list of resolved assets rather than dependencies. So you won't even need to call resolveFilename
, it will already have the resolved filename as its name
property.
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.
@devongovett I think it still needs resolveFilename
as the name
property contains only the relative file name.
But something like this should work:
let deps = Array.from(asset.depAssets.keys(), dep =>
this.bundler.resolver.resolveFilename(dep.name, asset.name)
);
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.
@henri-hulski It should probably be ...resolveFilename(dep, asset.name)
in your suggestion as dep
is a string.
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.
@felixrabe here dep
is not a string. I've logged it out and also tested this fix. It works fine.
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.
Ah right, depAssets is a Map, and its key is not a string but a dep (see Bundler.js where it does asset.depAssets.set(...)
). Still need to get used to Maps having non-string keys it seems :)
Regarding tests, my plan would be to have the following 3 tests:
@devongovett I can definitely make the quick change to use |
Fixes also the bug in #1152. |
@pcattori Are you still planning to finish this PR? |
@henri-hulski unfortunately, I have not had time to work on this recently. I do intend on continuing work on this this weekend,
|
@pcattori For me the PR looks good. Just switch to |
Bump. The underlying issues with the dedupe logic that this PR fixes are important. I'm seeing module require ids being incorrectly re-used for multiple dependencies that are not the same when using parcel I think also fixes #793 |
@olizilla @henri-hulski just writing to let you know that I haven't forgotten about this and have some time set aside this week to get this in. I did some work last weekend to get robust tests for this up and almost have those ready. |
Another datapoint for this PR. I've tracked down why the existing dedupe logic breaks when bundling IPFS as a dependency; two of it's deps have identical index.js files, as they follow a pattern of requiring the same two files and deferring the differences to other files. See: See: and https://github.com/ipld/js-ipld-git/blob/20f7a66c2fc916aeb4d7e6c7141bfe275033472f/src/index.js When these two unrelated files are used as keys in the dedupe map, they are the same, so they get deduped, even though they come from different modules. As they are the entry point to a dep, that means the whole require is swapped out for the wrong module. |
Alright! This now includes the 3 tests I mentioned before as well as all the suggestions left by reviewers so far. Note that the 2nd test is the important one here ( @henri-hulski let me know if it looks good to you 😄 |
@pcattori Looks good to me, but in Windows (AppVeyor) one test is failing:
|
Maybe a problem with slashes vs. backslashes. |
Yep, looks like making the paths xplatform did the trick. Now the only tests that are failing are some flakey |
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.
Looks ready to me. Great work!
@devongovett could you review?
It'd be great to get this merged. The "files as Map key" issue causes imports to incorrectly resolve to unrelated modules which happen to have the same shaped index.js file as any other dependency in your tree, which is causing hard to debug errors, and only for production builds. |
@devongovett just a friendly ping 😄 |
Any idea when this will be merged? |
Is there a reason why this doesn't get merged? |
Is it the test failure that's blocking this? It looks like it's unrelated
|
@olizilla yea definitely unrelated. those tests were sporadically failing before I made my changes as well. like @henri-hulski mentions, i think the only thing blocking this is @devongovett 's change request |
Please unlock this PR @devongovett. Your requests for changes seems to be blocking. |
src/packagers/JSPackager.js
Outdated
// `../` can cause 2 identical JS files to behave differently depending on | ||
// where they are located on the filesystem | ||
let deps = Array.from(asset.depAssets.keys(), dep => | ||
this.bundler.resolver.resolveFilename(dep.name, asset.name) |
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.
if you use depAssets.values()
, you can just map to dep.name
which is already resolved
Updated to fix the last comment (use pre-resolved deps), and switched it to use objectHash instead of JSON.stringify (seemed slightly faster in my tests due to shorter string keys). |
sorry for the delay! |
…differences in absolute dependency paths (parcel-bundler#1011)
… absolute dependency paths (#1011)
… absolute dependency paths (#1011)
fixes #933 #1152