Skip to content
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

module.children behavior does not match documentation (only tracks first requires) #9371

Closed
codebling opened this issue Oct 30, 2016 · 10 comments
Labels
doc Issues and PRs related to the documentations. good first issue Issues that are suitable for first-time contributors. help wanted Issues that need assistance from volunteers or PRs that need help to proceed. module Issues and PRs related to the module subsystem.

Comments

@codebling
Copy link

codebling commented Oct 30, 2016

TL;DR module.children does not behave according to documentation.

What be the expected behaviour of module.children?

Documentations states that module.children is "the module objects required by this one." This is false, as it only lists the children that were required for the first time by the module. Since module.parent is correctly documented as containing "the module that first required this one", it seems like this may be a documentation bug. If that's the case, we should correct the documentation.

Considering the issue on another level, what is the purpose of module.children and module.parent? Having a full graph of the first requires, or a partial/incomplete graph of all require relationships, does not seem at all useful to me. Why do these exist? I propose the addition of module fields requirers and requirees as respective analogues of parent and children, but ones which will keep track of all requires. The code will be essentially the same as what is currently in place, except that instead of running on module initialisation and pushing this module into the parent module's children structure (which only works the first time it is required, since after that the module is initialised and cached), we run after every require, pushing this module into the child's requirers. This will generally also only run once per uncached module (except for modules with conditional or lazy requires), except still works even if the children are cached.

So, fix options here are:

  1. consider this a documentation bug and fix the documentation
  2. change the behaviour of module.children to match the documentation (fix basically described above)

Possibly related to #7131 and #3933

@Fishrock123 Fishrock123 added the module Issues and PRs related to the module subsystem. label Oct 30, 2016
@codebling
Copy link
Author

codebling commented Oct 30, 2016

Note: I did not (perhaps rudely) fill out the template with version/platform information, since this affects multiple versions and is probably a documentation bug.

Testing this is trivial, however here is a simple example showing the issue.

@targos targos added the doc Issues and PRs related to the documentations. label Jan 8, 2017
@tniessen
Copy link
Member

tniessen commented Jun 2, 2017

This is definitely a good point. I am even more concerned about the fact that modules are not cached if they throw an Error while being require()d, but they are being added to module.children:

try {
  require('./b.js');
} catch(err) {
  try {
    require('./b.js');
  } catch(err) {
  }
}

console.log(`There are ${module.children.length} child modules`);
for(let child of module.children) {
  if(!require.cache[child.id])
    console.log(`${child.id} is not in require.cache!`);
}

This prints something like

There are 2 child modules
E:\node\testing\b.js is not in require.cache!
E:\node\testing\b.js is not in require.cache!

Is this intended behavior? (See also #13386 for a similar topic.)

Which solution would we prefer?

  1. Update the documentation to clearly state that only the first require()-call will add the module to module.children (except if an Error occurred).
  2. Change the implementation to add the module to require.children each time require() is used.

Edit: @bmeck Just made me realize that adding a module as the child of multiple other modules would be inconsistent as well as each module only has one parent module. Or, to put it with his words, "i would say nothing is consistent about module.parent or module.children".

@codebling
Copy link
Author

@tniessen the more useful approach to me is to deprecate module.parent and module.children and create other fields as I've described to address the multiple issues with module.parent and module.children (only first requires are tracked, added to children despite Error, etc). @bmeck is correct, that's why I suggested requirers and requirees.

It's not that much work to fix this, I think I even had a patch kicking around at some point. It's useful for introspection/reflection type behaviours.

@Trott
Copy link
Member

Trott commented May 31, 2018

@nodejs/modules Anything happening with this? Is this still an issue? Is this something that might benefit from a help wanted label?

@benjamingr
Copy link
Member

@Trott the modules team is tasked with ESM integration into Node.js - I think this is something that is out of scope for us - if this is stalled then I think help wanted is appropriate.

@Trott
Copy link
Member

Trott commented May 31, 2018

@benjamingr Sorry about that! I assumed nodejs/modules was the module subsystem and there was a nodejs/es-modules team or something but it looks like I was wrong.

@ljharb
Copy link
Member

ljharb commented May 31, 2018

I think this is definitely in scope for the modules group, because anything supported in CJS has to be explicitly supported, or not, in ESM.

In this case, runtime reflection on the module graph is not a feature I think node should support in either CJS or ESM, so I'd be strongly in favor of deprecating it in CJS.

@benjamingr
Copy link
Member

@ljharb I agree in general though the implementation in this case (module.children) doesn't really have much to do with how esm/cjs interacts in particular.

@ryzokuken
Copy link
Contributor

Couldn't we just make a change in the docs? The behavior seems pretty normal, feel free to change it if you want, but I believe we should just tag this as a "good first issue" with a single doc change.

@benjamingr benjamingr added help wanted Issues that need assistance from volunteers or PRs that need help to proceed. good first issue Issues that are suitable for first-time contributors. labels Jun 1, 2018
@benjamingr
Copy link
Member

Taking @ryzokuken's advice: if anyone wants to tackle this as a first issue and fix the docs - please let us know if you want/need help :)

transitive-bullshit added a commit to transitive-bullshit/node that referenced this issue Jul 5, 2018
Updates the module.children description in the docs to match current
functionality in that it will only contain the modules required for the
first time by this module.

Fixes: nodejs#9371
targos pushed a commit that referenced this issue Jul 12, 2018
Updates the module.children description in the docs to match current
functionality in that it will only contain the modules required for the
first time by this module.

Fixes: #9371

PR-URL: #21672
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Jon Moss <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc Issues and PRs related to the documentations. good first issue Issues that are suitable for first-time contributors. help wanted Issues that need assistance from volunteers or PRs that need help to proceed. module Issues and PRs related to the module subsystem.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants