Skip to content

no way to programmatically discover node:test #42785

Description

@ljharb

Version

18.0.0

Platform

No response

Subsystem

No response

What steps will reproduce the bug?

require('module').builtinModules

How often does it reproduce? Is there a required condition?

No response

What is the expected behavior?

Everything that's requireable that ships with node is listed (or, the listed items are requireable with node: added).

What do you see instead?

node:test is not listed.

Additional information

There needs to be a way to programmatically discover all builtin modules. require('module').builtinModules is supposed to be it.

This broke assumptions in my tests for https://npmjs.com/is-core-module - specifically, CIGTM should have failed prior to node 18 going out, because node:test wasn't part of is-core-module, but by making it effectively "secret", my tests didn't know about it.

Activity

  1. ljharb commented on Apr 19, 2022

    @ljharb
    SponsorMemberAuthor

    cc @nodejs/modules @cjihrig @nodejs/test_runner

  2. aduh95 commented on Apr 19, 2022

    @aduh95
    Contributor

    import("node:test").then(()=>true, ()=>false)?

  3. ljharb commented on Apr 19, 2022

    @ljharb
    SponsorMemberAuthor

    That's not synchronous, and requires that I hardcode the identifier in advance.

    I should be able to write code that works for all future prefix-only core modules without ever needing to hardcode their names.

  4. jasnell commented on Apr 19, 2022

    @jasnell
    Member

    @cjihrig ... Looking through the code it appears that not listing node:test in builtinModules was intentional ... though it's not clear why. I agree with @ljharb that it likely should be there. Adding it, however, does break a handful of tests so I wanted to check to see what needs to be considered there first.

  5. aduh95 commented on Apr 19, 2022

    @aduh95
    Contributor

    @ljharb there's a workaround, but it requires to use --expose-internals, sharing in case that unblocks you:

    'use strict';
    
    const { internalBinding } = require('internal/test/binding');
    const {
      moduleCategories: { canBeRequired },
    } = internalBinding('native_module');
    
    console.log(canBeRequired.has('test')); // true
  6. ljharb commented on Apr 19, 2022

    @ljharb
    SponsorMemberAuthor

    @aduh95 thanks; good to know, but i don't think it suffices.

    I think that the solutions here are either:

    1. add node:test to builtinModules
    2. make test requireable
    3. add a new list of prefix-only core modules

    My preference is the second one, the first is the simplest, and the third imo would be more of an argument for the second one because of the user confusion it furthers.

  7. devsnek commented on Apr 19, 2022

    @devsnek
    Member

    I would prefer option 1, it seems acceptable as an opaque string.

  8. jasnell commented on Apr 19, 2022

    @jasnell
    Member

    Option 2 has already been settled by the TSC vote. That makes options 1 and 3 the viable paths forward here. My preference would be for option 1. As far as I can tell, that shouldn't actually break anyone except a couple of our tests.

  9. cjihrig commented on Apr 19, 2022

    @cjihrig
    Contributor

    I'm also in favor of option 1 (only because option 2 is off the table).

  10. aduh95 commented on Apr 19, 2022

    @aduh95
    Contributor

    An option 4 would be to freeze and expose the canBeRequired set. I agree that option 1 and 3 are also viable paths, and option 1 is probably the simplest (although it might still be a breaking change?)

  11. ljharb commented on Apr 19, 2022

    @ljharb
    SponsorMemberAuthor

    I'm not sure why it would be - was it ever communicated that the API of this list is that nothing has a node prefix?

    My tests were doing "builtinModule item", and "builtinModule item with a node prefix" - so i did have to change the logic to "only add the node prefix if it's not already there". That's a pretty minimal change tho, and arguably i shouldn't have hardcoded the assumption that things in that list don't have the prefix. So option 1 does seem like it'd be fine.

  12. ljharb commented on Apr 19, 2022

    @ljharb
    SponsorMemberAuthor

    another oddity i noticed is that most all the builtin modules are available as globals in the repl - except for ones like module that are shadowed by the CJS module - and test is not available there. Should I file a separate issue for that? It seems like there'll be a bunch of unaccounted-for edge cases with the "prefix-only" approach the TSC vote unfortunately settled on.

  13. jasnell commented on Apr 19, 2022

    @jasnell
    Member

    The repl limitation is known already. It's not worth opening an issue, I think. Prefix only modules just won't be available as globals in the repl.

  14. 20 remaining items

  15. avivkeller commented on Jul 13, 2024

    @avivkeller
    Member

    This issue also masks the existence of node:sea and node:sqlite.

    And it's likely that more will follow. For my 2 cents, the most logical approach IMO is to populate the builtinModules list with all modules, each labeled with the node: prefix (since having node:sea alongside fs (not node:fs) wouldn't make sense IMO).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    moduleIssues and PRs related to the module subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions