Let's suppose we have a dependency module graph where more than one module import another at once, something like that: (A) ---> (B) <--- (C)
It seems the ECMAScript specification doesn't guarantee both A and C would get the same instance of an object represents the B module (or its exported entity).
To wit: a JS module is represented by an instance of specification object called Abstract Module Record (its concrete version is Source Text Module Record). An object of this type, in particular, stores bindings for the module (that is, declared variable names with their corresponding values). In the other words, different Module Records have different bindings (it's a pretty simple idea because it's the reason we tend to use modules).
Before code evaluating, a Module Record Link() method is executed and it, in turn, recursively calls the InitializeEnvironment() on each of graph Module Records. The aim of InitializeEnvironment() is to create bindings for every imported module. To obtain the needed Module Record which would represent one of them, this function uses HostResolveImportedModule(). It receives as its argument referencingScriptOrModule (an importing module, that is A or C) and a string specifier (something like b.js).
There is the bottom line starts to appear.
Each time this operation is called with a specific
referencingScriptOrModule,specifierpair as arguments it must return the sameModule Recordinstance if it completes normally.
I can't draw from this excerpt there is a guarantee A and C will get the same instance of Module Record represents B in due to (A, "b.js") and (C, "b.js") are not the same pairs.
Does it all mean, in effect, the ES module system doesn't guarantee a possibility to create a module singleton? There is a good few of advice to export a singleton entity from a module. It is said a module is evaluated once and then cached, so it's an acceptable way to deal with singletons. However, although the statement about caching is true, but still this fact per se doesn't entail an module system impementation would resolve to the same imported module for different importing ones.
Yes, there is no guarantee in ECMAScript - the rules for how to resolve module specifiers are determined by the host.
Multiple different
referencingScriptOrModule,specifierpairs may map to the same Module Record instance. The actual mapping semantic is implementation-defined but typically a normalization process is applied to specifier as part of the mapping process. A typical normalization process would include actions such as alphabetic case folding and expansion of relative and abbreviated path specifiers.
So only your host (like node.js or the browser) will give you the guarantee that it will always resolve certain specifiers to the same module.
There are many examples where (A, "b.js") and (C, "b.js") should not resolve to the same module - e.g. when A is one/a.js, it should return the module one/b.js, while C might be two/c.js and result in the module two/b.js.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With