Open ghost opened 1 year ago
Here's a diagram of this situation, since I was doing it for my own work. I called it a hyperjunction in tests. Importing value
from left, middle, or right shows the condition.
When the arms are stars it works everywhere.
When 1 arm is chopped off it works everywhere.
Do you know if this behaviour is specified? i.e. can we unambiguously say that one or the other of the behaviours is wrong? Or is it a gap in the specification?
By my understanding, it should work. It's kind of awkward to get your head around because it's only there in the implications. I'll give what I think is a correct trace of an import.
This is the traversal that should happen if you import value
from Left. ResolveExport
defines it. The seen list is in []
.
// Left.mjs
export { value } from './Middle.mjs'
// Middle.mjs
export * from './Left.mjs'
export * from './Right.mjs'
export * from './Substance.mjs'
// Right.mjs
export { value } from './Middle.mjs'
// Substance.mjs
export const value = 'value'
When I first raised it someone pointed out to me that a cycle will normally throw at module evaluation time. This happens in InitializeEnvironment
. It pulls all imports to try to create the internal bindings. When one of them is a cycle, it has to fail. In this graph one of the distal
modules will throw.
But star exports on their own don't create bindings and so they never hit this evaluation-time error. There's a certain kind of cycle through stars that is entirely binding free.
If you have a list of star exports where some have these pure star cycles but one of them has a binding, the spec seems to say it should resolve. A list of star exports is kind of like a disjunction operator. It any of these stars gives a binding, that's the one, ignore cycles on the other stars.
Import cycles have some interaction with star exports. Where one star export finds a cycle and another finds a binding, the binding should override and resolve successfully.
It was pointed out to me that typically a cycle will cause a crash elsewhere, when
InitializeEnvironment
detects it. But that shouldn't happen in the case where a star export is in the middle of the cycle. There is inconsistency in implementations on this point. I wonder if it should be in the test suite.There are eshost outputs below, plus browser demos. The browser demos log/error to the console.
Cycle on both sides, wrapped in named exports.
https://bojavou.github.io/star-export-cycle/biname/
https://github.com/bojavou/star-export-cycle/tree/main/biname
Cycle on one side, wrapped in named exports.
https://bojavou.github.io/star-export-cycle/uniname/
https://github.com/bojavou/star-export-cycle/tree/main/uniname
Cycle on both sides, wrapped in star exports.
https://bojavou.github.io/star-export-cycle/bistar/
https://github.com/bojavou/star-export-cycle/tree/main/bistar
Cycle on one side, wrapped in star exports.
This behaves identically to bistar.
https://bojavou.github.io/star-export-cycle/unistar/
https://github.com/bojavou/star-export-cycle/tree/main/unistar