You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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?
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.
@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 :)
@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.
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.
@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.
@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.
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"?
@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?
@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.
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.:
constisYaml=Symbol('isYaml');exportdefaultasyncfunctionload(context,load){const{ url, format, content }=awaitload(context);if(format==='application/yaml'||format===undefined&&url.endsWith(".yaml")){context[isYaml]=true;// parse yaml and transform into JSON...constjsonContent=JSON.stringify(...);return{format: 'json',content: jsonContent};}return{ format, content };}exportdefaultfunctionvalidateAssertions(context,defaultValidateAssertions,){const{ assertions, format }=context;if(assertions.type==='yaml'&&!context[isYaml]){thrownewError(`Expected yaml but got ${format} instead`);}}
Activity
ljharb commentedon Jan 30, 2021
JSON Modules will be stage 3 once reviewers have finished reviewing it.
devsnek commentedon Jan 30, 2021
I would pull the experimental json modules and use the official v8 impl when it lands.
zackschuster commentedon Jan 30, 2021
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.
devsnek commentedon Jan 30, 2021
@zackschuster importing json does not require
type: json, but any import withtype: jsonmust be a json module.zackschuster commentedon Jan 30, 2021
@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 :)
bmeck commentedon Jan 31, 2021
@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.
zackschuster commentedon Feb 1, 2021
@bmeck would that just mean another read from disk, or is it supposed to be possible to observably mutate the json module?
devsnek commentedon Feb 1, 2021
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)
bmeck commentedon Feb 1, 2021
Assertions are specifically part of resolution, see tc39/proposal-json-modules#10
ljharb commentedon Feb 1, 2021
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.
bmeck commentedon Feb 1, 2021
@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.
bmeck commentedon Feb 1, 2021
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.
devsnek commentedon Feb 1, 2021
@bmeck my understanding and consensus was on them not being required to be part of the cache key. is that not the case?
7 remaining items
bmeck commentedon Feb 1, 2021
@devsnek that is interpretation not evaluation.
devsnek commentedon Feb 1, 2021
@bmeck I'm not following your example about aliasing. an assertion is a local requirement on the resolved module.
bmeck commentedon Feb 1, 2021
@devsnek kind of? If the resolution is to a path
/foo.jsonany it loads normally you get an entry/foo.jsonin the global module map presumably matching/foo.jsonandtype:json(optional?). Then if it is loaded w/ a differenttypesuch as missing the type it could instead on disk show that it is meant to load/bar.jsafter the 2nd resolve. This would no longer match thetype:jsonduring a resolve. The HTML approach is a 2 tiered cache where you check for that resolved path/foo.jsonand 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.devsnek commentedon Feb 1, 2021
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"?bmeck commentedon Feb 1, 2021
@devsnek by "atomic" I mean that no side effects (such as disk manipulation) can occur during that chain.
devsnek commentedon Feb 1, 2021
@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?
bmeck commentedon Feb 1, 2021
@devsnek the resolver always hits the disk to resolve new specifiers (if they are not simple URL manip) so it should hit disk for
aand thenbas specifiers and both can resolve to the same location.devsnek commentedon Feb 1, 2021
@bmeck i'm still not following.
Jamesernator commentedon Feb 4, 2021
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.:
devsnek commentedon Feb 4, 2021
Might need some bikeshedding but i like the separation 👍
aduh95 commentedon Feb 15, 2021
JSON Modules are now stage 3: tc39/proposals@eda6da4
GeoffreyBooth commentedon Oct 10, 2021
I think we can close this now that we have a path forward; @targos please reopen if you feel otherwise.