-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Remove unreachable code in InnerModuleEvaluation #3584
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
Conversation
I just checked in engine262, and indeed replacing the EDIT: I'm trying to understand if the "Set requriedModule to requiredModule.[[CycleRoot]] step" is useful/correct. EDIT 2: Yes, that step is necessary, and there is no test262 coverage for it. I'll open a test262 PR. |
42c7d5c
to
d8b8baa
Compare
I think it is actually possible for this not to be the case. And the reason for this is that since the very first iteration of this Tarjan algorithm in the spec, error states don't get transitioned across the whole strongly connected component of the cycle due to the early exit that applies here. In fact I think it's an early limitation that that is not the case as it leads to this kind of in-between state behaviour with extra checks needed. So I believe what is written today is correct though and necessary because of this, short of a refactoring of error states to transition in alignment across a whole strongly connected component. Here is a counter example:
Where all of the above are synchronous - this case isn't about async graphs but sync ones. Consider that the error module is Then consider executing
Then if I import This is just on a very quick review though so please do let me know if I'm missing anything further though. |
@guybedford There is probably some typo somewhere with your example, where you wrote Anyway, assuming that there is no typo, the first time you execute
So there is no [[CycleRoot]] set, because we always return from InnerModuleEvaluation before getting to step 16. When then you import again one of B or C (either directly, or through an other entrypoint such as E->D->B), InnerModuleEvaluation(B/C) returns early at step 2.b, thus without ever looking at their dependencies and thus they are never considered again to be in a cycle. |
Thanks I've corrected the first example last listing item for E. Your response is certainly correct though - because the The only cases then would be async cases, but I think there might still be a possibility of this happening in the async case as well. Consider:
Where C is now async and has an async error. In this case, after the error happens async we have graph states:
In this example, D was not in the async parent modules set of C, therefore D does not have an evaluation error set. When I later import E, it will not see an evaluation error on D, and therefore we need the cycle root check that D does on B to verify there is no evaluation errors. This is since in async error cases evaluation errors only propogate upwards to the cycle root and not out to the entire strongly connected component. So while you have convinced me we don't need this check in the sync case I'm pretty sure we do still need it in the async case. |
You are right. I didn't realize I was implicitly assuming that if a member of a SCC has an [[EvaluationError]] then the whole SCC has the same [[EvaluationError]] (which is guaranteed for sync cases due the cleanup logic in Evaluation(), but not for async cases). It is a property that I would like to restore also for the async case, but I'm not sure there is a simple way to do it. I will add your example as a test262 test case, since we had no coverage for this line. |
@guybedford Wdyt about making the It would reduce the possible combinations of states that modules can have in a graph. I would like to get to a point where these assertions are all true, all the time (except for the couple steps where you first change one module and then immediately after the other module):
In other words:
Currently (1)/(2)/(3) are true, and (4)/(5) are only true for sync graphs. |
I think the contents of the
If
are unreachable, so it can be removed.My reasoning is that:
~empty~
, then requiredModule(cycle root).[[Status]] must be~evaluated~
~empty~
, InnerModuleEvaluation(requiredModule(not the root)) would have returned that throw completion, and thus we would have returned early due to the ? before the InnerModuleEvaluation call.