Skip to content

The future of --experimental-json-modules #37141

Description

@targos

The import assertions proposal is in stage 3 and V8 implemented it (the API will be available in V8 8.9).
The JSON modules proposal is in stage 2 and is built on top of import assertions.

I think it's time to discuss about what we are going to do with --experimental-json-modules.
We'll be able to implement the type: "json" assertion soon. Should we aim to replace --experimental-json-modules with it? Should we add a new experimental flag? Should we deprecate the current behavior of --experimental-json-modules?

@nodejs/modules

Activity

  1. added
    discussIssues opened for discussion and feedback.
    esmIssues and PRs related to the ECMAScript Modules implementation.
    on Jan 30, 2021
  2. ljharb commented on Jan 30, 2021

    @ljharb
    SponsorMember

    JSON Modules will be stage 3 once reviewers have finished reviewing it.

  3. devsnek commented on Jan 30, 2021

    @devsnek
    Member

    I would pull the experimental json modules and use the official v8 impl when it lands.

  4. zackschuster commented on Jan 30, 2021

    @zackschuster

    assuming assertions are mandatory, i don't think the flag should "just" be pulled, for the sake of those unable to adopt new syntax (e.g. teams stuck on an older typescript by angular 8). they'd be effectively blocked from updating the platform if they ever relied on importing json. i'd recommend replacing the flag instead with one that allows omitting assertions.

  5. devsnek commented on Jan 30, 2021

    @devsnek
    Member

    @zackschuster importing json does not require type: json, but any import with type: json must be a json module.

  6. zackschuster commented on Jan 30, 2021

    @zackschuster

    @devsnek that's good then. last i heard was that it wasn't certain if the assertion would be mandatory, at least under node. being able to simply drop the flag without code changes is nice :)

  7. bmeck commented on Jan 31, 2021

    @bmeck
    Member

    @zackschuster likely it won't be mandatory under node, but due to some reasons likely it won't have the same cache key between them so you could get 2 different modules if you do or do not include the assertion.

  8. zackschuster commented on Feb 1, 2021

    @zackschuster

    @bmeck would that just mean another read from disk, or is it supposed to be possible to observably mutate the json module?

  9. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    in the context of node's resolver I would not expect it to use type:json as part of the cache key (assertions are specificallynot resolver attributes)

  10. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    Assertions are specifically part of resolution, see tc39/proposal-json-modules#10

  11. ljharb commented on Feb 1, 2021

    @ljharb
    SponsorMember

    They are allowed to be; they are also allowed not to be, and encouraged not to be. The web won’t make them part of the cache key when it can avoid it, for example - which won’t be always.

  12. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    @zackschuster I'm unclear on the question, I would expect if we follow the web spec, it usually wouldn't cause a secondary read due to having a fetch cache (node currently does not have one). In the web if a HREF resolves and it has an existing entry w/ a different type an error is expected to be thrown, I don't think Node would throw that error. So, we could see 2 disk reads if there isn't a cache, same as today; and JSON modules are mutable so mutation is observable.

  13. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    The web won’t make them part of the cache key when it can avoid it, for example - which won’t be always.

    This is 100% false, in the web they will 100% of the time be part of the cache key when they go through the fetch infrastructure.

  14. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    @bmeck my understanding and consensus was on them not being required to be part of the cache key. is that not the case?

  15. 7 remaining items

  16. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    @devsnek that is interpretation not evaluation.

  17. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    @bmeck I'm not following your example about aliasing. an assertion is a local requirement on the resolved module.

  18. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    @devsnek kind of? If the resolution is to a path /foo.json any it loads normally you get an entry /foo.json in the global module map presumably matching /foo.json and type:json(optional?). Then if it is loaded w/ a different type such as missing the type it could instead on disk show that it is meant to load /bar.js after the 2nd resolve. This would no longer match the type:json during a resolve. The HTML approach is a 2 tiered cache where you check for that resolved path /foo.json and would see a map of types that already exist for the HREF and then error if one already exists and isn't what we resolve. So, it is still part of the cache key, but avoids collisions. We could remove the error part of that algorithm (similar to what we did with bare imports), but having it resolve still would now need to deal with situations like above.

  19. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    so in my head canon, our resolver should look like this: (specifier, referrer) -> all the scary resolution and hooks and stuff -> module -> verify assertions. Is this what you meant by being "atomic"?

  20. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    @devsnek by "atomic" I mean that no side effects (such as disk manipulation) can occur during that chain.

  21. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    @bmeck if assertions aren't part of the cache key, the addition or removal of them won't cause the resolver to hit the disk again, so it seems like a moot point?

  22. bmeck commented on Feb 1, 2021

    @bmeck
    Member

    @devsnek the resolver always hits the disk to resolve new specifiers (if they are not simple URL manip) so it should hit disk for a and then b as specifiers and both can resolve to the same location.

  23. devsnek commented on Feb 1, 2021

    @devsnek
    Member

    @bmeck i'm still not following.

  24. Jamesernator commented on Feb 4, 2021

    @Jamesernator

    Regarding the loader, given the intention is purely to assert conditions about the resource, it would make sense to add this as an additional loader hook (that returns nothing, but might throw an error) e.g.:

    const isYaml = Symbol('isYaml');
    
    export default async function load(context, load) {
      const { url, format, content } = await load(context);
      if (format === 'application/yaml' || format === undefined && url.endsWith(".yaml")) {
        context[isYaml] = true;
        // parse yaml and transform into JSON...
        const jsonContent = JSON.stringify(...);
        return { format: 'json', content: jsonContent };
      }
      return { format, content };
    }
    
    export default function validateAssertions(
      context,
      defaultValidateAssertions,
    ) {
      const { assertions, format } = context;
      if (assertions.type === 'yaml' && !context[isYaml]) {
        throw new Error(`Expected yaml but got ${ format } instead`);
      }
    }
  25. devsnek commented on Feb 4, 2021

    @devsnek
    Member

    Might need some bikeshedding but i like the separation 👍

  26. aduh95 commented on Feb 15, 2021

    @aduh95
    Contributor

    JSON Modules are now stage 3: tc39/proposals@eda6da4

  27. GeoffreyBooth commented on Oct 10, 2021

    @GeoffreyBooth
    Member

    I think we can close this now that we have a path forward; @targos please reopen if you feel otherwise.

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

    discussIssues opened for discussion and feedback.esmIssues and PRs related to the ECMAScript Modules implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions