Hi, @jdalton, it's me again馃槀
I just found that a module involving circular require would be evaluated twice as in this repro repo: Mensu/std-esm-repro-issue-217
index.js, top.js and sub.js in the same directory.
const topModule = require('./top');
// topModule.subModule is expected to contain methodOfSub
console.log(topModule.subModule);
console.log('evaluating top module');
// this 'exports = module.exports = ...' pattern might be confusing to your compiler
// but it does exist in our project...
exports = module.exports = {
methodOfTop,
};
// requires sub module
exports.subModule = require('./sub');
function methodOfTop() {
}
console.log('evaluating sub module');
// requires top module back
const topModule = require('./top');
module.exports = {
methodOfSub,
};
function methodOfSub() {
// using topModule.methodOfTop
}
running node -r @std/esm index.js
@std/esm version: 0.19.1node version: 9.2 on macOS and 9.3 on Ubuntu 16.04vars option turned on: "vars": truewhich is the same as raw node
evaluating top module
evaluating sub module
{ methodOfSub: [Function: methodOfSub] }
evaluating top module
evaluating sub module
evaluating top module
{}
exports.methodOfTop = methodOfTop instead of exports = module.exports = { methodOfTop }methodOfTop would be repeated twice, so when there are many names to export, export.name = name would be annoying"vars": true from package.jsonnpm i @std/[email protected]node -e 'console.log(require("./index").subModule)' -r @std/esm or cat index.js | node -r @std/esmIn light of the fact that @std/[email protected] would not have this problem, I assume this might be a bug introduced in v0.19.0 and v0.19.1, which might be somehow related to #209
Considering the first workaround, I could understand it if this will become a won't fix due to the confusing exports = module.exports = ..., but I would still be glad if you could check it out with the repro repo when available. Thanks in advance!
If we add some console.log like this (with // ADDED), the output may be more helpful for debugging
console.log('evaluating top module');
// this 'exports = module.exports = ...' pattern might be confusing to your compiler
// but it does exist in our project...
exports = module.exports = {
methodOfTop,
};
// requires sub module
console.log('[top]', 'before requiring sub module'); // ADDED
exports.subModule = require('./sub');
console.log('[top]', 'after requiring sub module'); // ADDED
function methodOfTop() {
}
console.log('evaluating sub module');
// requires top module back
const topModule = require('./top');
console.log('[sub]', 'top module is', topModule); // ADDED
module.exports = {
methodOfSub,
};
function methodOfSub() {
// using topModule.methodOfTop
}
evaluating top module
[top] before requiring sub module
evaluating sub module
[sub] top module is { methodOfTop: [Function: methodOfTop] }
[top] after requiring sub module
{ methodOfSub: [Function: methodOfSub] }
evaluating top module
[top] before requiring sub module
evaluating sub module
evaluating top module
[top] before requiring sub module
[top] after requiring sub module
[sub] top module is { methodOfTop: [Function: methodOfTop], subModule: {} }
[top] after requiring sub module
{}
Update:
make expected output and actual output in the correct section
Thank you for filing the issues and creating the repro repos @Mensu!
You're a big help here. I can repro the issue on master branch too.
Update:
I found the issue. It's how we track state associated with module entries. Sometimes a miss can happen (if the module.export is replaced) causing the loader to think it's a new module.
Patched https://github.com/standard-things/esm/commit/bdc676fddc758ca76752ccc5054750d3b3df35ed.
Update:
v0.19.2 is released 馃帀