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

Reserved specifiers after import maps #101

Closed
hiroshige-g opened this issue Feb 1, 2019 · 12 comments
Closed

Reserved specifiers after import maps #101

hiroshige-g opened this issue Feb 1, 2019 · 12 comments
Milestone

Comments

@hiroshige-g
Copy link
Collaborator

IIUC current reference implementation allow any string as bare specifier (except for the empty string) and thus uses up the entire space of reserved module specifiers.

Can/should we leave a chance to extend the specifier semantics again after import maps is introduced, by reserving some patterns of bare specifiers?

@eliasvasylenko
Copy link

eliasvasylenko commented Feb 1, 2019

Leaving the opportunity to extend resolution semantics is a valuable goal, but I think it makes more sense to do this based on the content of the import map so everything is still declared in the same place and under user control. For example by adding support for new forms of address, or even new top-level entries #80.

(Bear in mind also FWIW that bare addresses are already reserved according to the current spec #94.)

I think what you're suggesting is essentially to reserve the opportunity to prescribe new global semantics for interpreting the meaning of a specifier. But I think it's more valuable to reserve the opportunity to allow the user to declare such semantics in the import map.

For any new semantics you could dream up add to reserved specifier patterns, it would also be possible to add new rules to the map such that the semantics could be expressed there.

@guybedford
Copy link
Collaborator

This sounds like a great suggestion to me.

The following represents a valid package name on npm (worked out from https://github.com/npm/validate-npm-package-name, although which seems to have higher complexity rules than necessary for the cases):

/^(@[-_\.a-zA-Z\d]+\/)?[-_\.a-zA-Z\d]+$/

I tend to disagree with the restriction to latin characters, but given this is effectively the ecosystem standard for bare specifiers currently, such a whitelist may well make said.

Perhaps it would maintain specific symbols as invalid like in filenames - #$%'?><.;{}|: sort of thing? (list completely arbitrary there)

That way such symbols could introduce new semantics in future.

@domenic
Copy link
Collaborator

domenic commented Feb 22, 2019

I'm not sure we should ever introduce "un-mappable" specifiers. Given that the import maps proposal explicitly wants to allow mapping over built-in module specifiers, I can't imagine what we would want to add to the platform that cannot be mapped over.

@guybedford
Copy link
Collaborator

Here are some examples of the sorts of things that could be added to specifiers. I don't personally support any of these, just throwing out ideas. In fact, most of these are terrible ideas:

  1. import { x } from "@feature:name ? ./moduleA : ./moduleB" conditional module loading based on browser feature availability, where @feature is a builtin module with named exports corresponding to boolean feature support.
  2. import "polyfill|@feature:name" like the above, but for loading a polyfill if the feature detection fails.
  3. import "<pkg>" could be defined to support a registry lookup in the browser, where the package registry could be something like DNS (as in configuration free).
  4. import { name } from "pkg#name" could be defined to support some kind of partial module delivery protocol (say header-based), where we indicate we only need the name export from the module, and that the source returned just covers that case. There would be a caching loss here.
  5. import { name } from "moduleA, moduleB" effectively sugar for importing from export * from 'moduleA'; export * from 'moduleB'.

The argument simply being, we don't know what we might want in future, and reserving syntax doesn't seem like it comes at any cost.

@guybedford
Copy link
Collaborator

(and that there might be an actually good idea yet to be found...)

@domenic
Copy link
Collaborator

domenic commented Feb 25, 2019

Sure, but we could add any or all of those and still allow import maps to override them. There's no need to reserve or prevent import maps from working in those cases.

@guybedford
Copy link
Collaborator

Yes exactly, we would be forced to allow import maps to override any future syntax. There may be circularity issues with that since many of the above definitions assume import maps running on modules specified there. But I will rest my argument here.

@littledan
Copy link
Contributor

I share @guybedford's skepticism that, if we want to support these features in specifier strings, it would just work out if we don't reserve it. However, I am not really excited about defining new syntaxes within the specifier string; I think these examples would be better handled by a more complex object in JSON in the import map itself, when explaining what the string specifier translates to. The fallback list will let us add more of these over time in a graceful degradation-friendly way.

@eliasvasylenko
Copy link

eliasvasylenko commented Feb 28, 2019

Exactly, like I said, express it with new forms of address instead, or other additions to the map. New forms of address would compose better too, for example you wouldn't be left with the parsing problem of encountering a specifier like e.g. "@feature:name ? <pkg> : pkg#name".

Which also makes me think, even if you do want to express new semantics with new syntax at the specifier use-site, why embed that syntax within the specifier string in the first place? Just add new forms of import statement.

@guybedford
Copy link
Collaborator

I'm glad, if anything, that the terrible examples managed to become a convincing argument against any syntax in the specifier :)

@dcleao
Copy link

dcleao commented Mar 4, 2019

For the sake of completion, there's the classic AMD/SystemJS syntax for loader plugins:

import name from "plugin-package!argument-package";

This could very conveniently desugar into some top-level await form, such as:

import plugin from "plugin-package";
let name = await plugin(argument-package, import.meta);

@domenic
Copy link
Collaborator

domenic commented Jul 22, 2019

Given the lack of movement here and in #139, I will close this. Remember that nothing prevents us from using syntax in the specifier (e.g. the AMD/SystemJS loader plugin syntax); we're just making a decision that import maps should still be able to remap strings using that syntax. That said, most people seem un-enthused about syntax in the specifier strings regardless.

Personally, this together with #139 made me think maybe we should reserve something. (I.e., we had two weak reasons, plus a general caution toward choosing more restrictive defaults we can loosen later.) But there hasn't been a lot of movement in either, so I'll close. Let me know if I'm misreading.

@domenic domenic closed this as completed Jul 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants