In my case I was using Webpack+babel-loader. I guess that makes sense, about the run-time dependencies. After solving the problem by wrapping the module logic for A and B in functions then calling those functions in main.js. I then encountered another problem: package C imports the default from package B, and at initialization-time B is undefined in C even though there's no circular dependency there. I was able to solve that problem by wrapping init-time logic in a function and again executing that in main.js. So, basically, moving all to calls in main.js solved both of these problems. I can follow what you're saying about the circular dep between A and B, but I'm not at all sure why B would be undefined in C after having moved A and B logic to main.js, leaving C logic still in the C module.
On Mon, Dec 21, 2015 at 8:05 PM, Logan Smyth <[email protected]> wrote: > To start, an object is definitely not what I'd expect. The core thing to > remember with ES6 modules is that while imports are live bindings, you still > need to write your code in such a way that it has no run-time circular > dependencies. > > In your specific examples, you are importing `A` first, which will begin `B` > loading. Since `A` has not finished executing yet, and B will be attempting > to access the the `A` import before the `A.js` file has begin executing. I'm > not 100% sure off the top of my head, but in a real ES6 environment, that > would either result in the `A` import being `undefined`, or attempting to > access it would throw a temporal dead zone error due to you accessing a > variable before it has been initialized. > > If your `A.js` file comment "// modify the A object adding methods that > reference B." adds those references without actually accessing `B` in any > way, then the solution to your issue (in a real environment anyway) would be > to import `B.js` _first_ so that you do not have circular > initialization-time dependencies. > > In this case, are you using Babel's ES6 module syntax transpiling, or > Webpack with another transpiler? > > > On Mon, Dec 21, 2015 at 7:25 PM, /#!/JoePea <[email protected]> wrote: >> >> I'm curious, what should happen when module A imports the default from >> module B which imports the default from module A? Should the exported >> A object exist inside of module B? >> >> Here's two modules A and B (simplified from some real code that I >> have), which have a circular dependency: >> >> ```js >> // A.js >> import B from './B' >> let A = window.globalThing >> export default A >> >> // modify the A object adding methods that reference B. >> ``` >> >> ```js >> // B.js >> import A from './A' >> let B = new window.OtherThing >> export default B >> >> console.log(A) // an empty object, {} >> >> // modify the B object which depends on A existing (not being some >> temporary >> // object like I get with Webpack) while the module is evaluated. >> ``` >> >> When using Webpack, this code fails because the reference to A in B is >> some empty object. If I import both A and B into main.js, then A is >> defined as epected: >> >> ```js >> // main.js >> import A from './A' >> import B from './B' >> >> console.log(A) // An object with a bunch of properties, as expected. >> ``` >> >> I can fix my problem by exporting functions to do setup of A and B, >> and running those functions in main.js, like this: >> >> ```js >> // A.js >> import B from './B' >> let A = window.globalThing >> export default A >> >> A.setup = () => { >> // modify the A object adding methods that reference B. >> } >> ``` >> >> ```js >> // B.js >> import A from './A' >> let B = new window.OtherThing >> export default B >> >> console.log(A) // an empty object, {} >> >> B.setup = () => { >> console.log(A) // the expected object!! Why? >> >> // modify the B object which depends on A existing (not being some >> temporary >> // object like I get with Webpack) while the module is evaluated. >> } >> ``` >> >> When using Webpack, this code fails because the reference to A in B is >> just `{}`, some empty object. If I import both A and B into main.js, >> then A is defined as epected: >> >> ```js >> // main.js >> import A from './A' >> import B from './B' >> >> A.setup() >> B.setup() >> >> // no more problems! >> >> console.log(A) // An object with a bunch of properties, as expected. >> ``` >> >> So, if I run the setup for A and B in main.js instead of in the module >> evaluation, everything works perfectly. >> >> This led me to wonder: What is the expected behavior of circular >> dependencies in ES2015? Have you had this 'empty object' problem >> before? Is that expected to happen, or might there be a bug in >> Webpack? >> >> I guess the problem makes sense: How can the first method (running >> relying on module evaluation for setting up A and B exports) work if >> module B depends on the evaluation of module A which depends on the >> evaluation of module B? >> _______________________________________________ >> es-discuss mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/es-discuss > > _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

