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
Handle some cases of duplicate export bindings #3575
Conversation
test/form/samples/system-multiple-variable-declaration-export-bindings/_expected.js
Outdated
Show resolved
Hide resolved
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 is an incredible start, thank you for diving into these details @joeljeske.
We will get through these cases I'm sure, we just need to be careful about them.
test/form/samples/system-multiple-variable-declaration-export-bindings/_expected.js
Outdated
Show resolved
Hide resolved
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.
Here are some other edge cases I can think of:
- Destructuring defaults themselves setting live bindings
export var p = 5;
export var q = 10;
({ p = q = 20 } = {});
- Bindings updated in for expressions:
export var p = 5;
for (p of [1,2,3]);
This one is probably entirely unnecessary and I don't even think it's possible to support actually. Maybe just ensuring it outputs valid JS is enough, even if the live bindings don't work.
@joeljeske are there any other cases you think are still missing here? Or refactorings you think still need to be considered?
Thanks again for the great work.
@guybedford Thanks, yea those are good cases to consider. Now that I better understand the expected output, I don't think it'll be too bad to update the AST to render those scenarios. Just a matter of getting some time for it. I'll ping you back here when I'm ready for a more in-depth review. Thanks for the guidance and help |
I've pushed up some updates to those edge cases here - this gets the output correct for default destructuring assignment expressions, while ensuring that we use the IIFE expression as much as possible. Note that the expression IIFE form is better than the statement form as it works inline in expressions - I did some tests with destructuring and can confirm that the binding updates are interleaved with the default expressions, and the semantics implemented here will match that if you happen to call a function in another module that expects the partial binding updates to be available already! I've left out the @lukastaegert all of the rendering cases seem to be worked out here now, but there is still an information flow problem with It seems like we need to separate
If you have any suggestions on how better to pipe this information please let me know - I'm leaving some comments on the appropriate code paths about this. |
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.
@lukastaegert the comments mostly cover the information flow issues left here. Would be great to get these ironed out if you have a moment to share some suggestions. Failing tests are the many chunking-form cases.
Update - to summarize the issue: The implementation in this PR relies on variable.safeExportName
always representing the singular exported binding in a non-public chunk. But the failing chunk test cases demonstrate chunks where safeExportName
is not set to represent the chunk boundary - so the public exportNames
get exported which do not represent the chunk interface. exportNames
also seems to include a mix of the public and private export names.
@guybedford @joeljeske If you search the code, you'll see that |
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.
See my comment, I think getting rid of safeExportName
and always adding the exportNames
property to all variables will already make the code much clearer, then I will take a deeper look at the rest.
If exportNames
are never mutated, you could even use a shared constant, i.e. NO_EXPORTS
with an empty array as the initial value for exportNames
. This mini-optimization would save a little memory as the runtime can use the same array instance everywhere and make it clearer what an empty array means. But just an idea.
@lukastaegert I've updated this PR to remove The form tests are still passing, but as before the chunking tests are not because Note that Further suggestions / help welcome. |
Thanks for the work on this, I appreciate it. I’m a bit confused, how did exportName use to work? Didn’t it already have to keep track of the proper name to use, depending on use in a chunk or entry? |
The problem was not that |
…hunk to avoid interactions between Chunks that export the same variables, and interactions between outputs
Thanks so much @lukastaegert for taking the time to dig into fixing the approach here. Very glad the shared names are finally refactored out entirely. That was a vestige of the pre-code-splitting days! I've gone through and polished up the outputs some more here, paying more attention to whitespace as well. @joeljeske if you feel like throwing some more tests at this PR please do, otherwise I think we are close to being ready to merge here. |
The git hooks really weren't happy with running on my WSL environment so note the commit hooks still need running here. |
Codecov Report
@@ Coverage Diff @@
## master #3575 +/- ##
==========================================
+ Coverage 96.39% 96.48% +0.09%
==========================================
Files 182 182
Lines 6212 6233 +21
Branches 1819 1830 +11
==========================================
+ Hits 5988 6014 +26
+ Misses 111 108 -3
+ Partials 113 111 -2
Continue to review full report at Codecov.
|
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 removed some afaik impossible cases to improve coverage. What I would like to see before this is done:
- Add tests for the few missing bits as indicated by coverage:
- AssignmentExpression in compact mode
- Quite a few cases around UpdateExpression
- Clarify what the return value of
exports({foo: v, bar: v})
is
@guybedford It would be really nice if you pulled before force pushing or used force-with-lease and not overwrite my commits. I will just force-push again over your changes to restore this. |
@lukastaegert I've gone through and made some further careful refinements here:
|
@lukastaegert I did merge in your changes, but made further significant refactorings as well. Can you point me to something from the diff I missed? |
It seems the force push added zero new commits anyway, so I think we are all good here. |
Coverage looking good! Please double check a final review when you can and thanks again for all the help here all, a real collaborative effort. |
Sorry, maybe I also read the commit history wrongly, I was missing my "improve coverage" commits. But it appears everything is fine now, thanks! |
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 this is good to go mostly. I two places I find the code-style micro-optimizations a little over-the-top and making it really hard to read and maintain the code, so I would hope maybe we can go without those?
Good point - I've put a bit more work into the whitespace handling by refactoring it with a The newline handling was mostly to keep the pure comment test cases as before, but instead of special casing this, they are now handled by the same system. Just check that the test cases for that seem ok to you in the latest commit. |
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.
Thanks. I slightly changed the name of the scan
function to make clearer what it does and align better with other naming. Otherwise I would see this fit for release. Any more comments @joeljeske @guybedford ?
Ah, screw that, I want to do a release because I have little time left today and want this in master soon. We can always iterate in patch releases here. |
Thanks so much for working this out! It was educational for me to understand this project better. Thanks! |
Always happy to have new interested contributors here! If you ever feel like fixing something again, just take a shot 😜 |
WIP for #3566