tc39 / proposal-source-phase-imports

Proposal to enable importing modules at the source phase
https://tc39.es/proposal-source-phase-imports/
MIT License
129 stars 9 forks source link

Consider a method-like `import` metaproperty for source phase imports #40

Closed rbuckton closed 1 year ago

rbuckton commented 1 year ago

I've seen arguments for why the syntax should be part of with {}, and also for why the syntax should be a modifier following import, but has there been any consideration for using a method-like import MetaProperty?

For example:

const asset = import.resolve("./path"); // instead of `import asset`
const source = await import.compile("./path"); // instead of `import source`
const instance = await import.instantiate("./path"); // instead of `import instance`

Such calls are just as statically analyzable as the top-level import syntax and don't require shoehorning the result of each operation into the various import binding syntaxes, as you do with the phase modifier syntax. It also avoids encoding what is essentially a method name into a one-off phase property of the import call, especially if import(path, { phase: "asset" }) might be non-promise returning.

ljharb commented 1 year ago

Alternatively, import.phase('./path', 'source', options) or similar.

lucacasonato commented 1 year ago

I would favour the form import.<phase>(specifier).

Is this something you can get onboard with @rbuckton (having the meta-property be the same phase name as the static syntax)?

This would also resolve @ljharb's concern about symmetry between static and dynamic syntax, because we drop uttering phase anywhere:

import <phase> <binding> from "<specifier>";

const <binding> = import.<phase>("<specifier>");
guybedford commented 1 year ago

I've put a change together along these lines in https://github.com/tc39/proposal-import-reflection/pull/45.

nayeemrmn commented 1 year ago

In light of this, do dynamic import attributes still need the with: {} layer?

import("./foo.js", { phase: "source" });
import("./bar.json", { with: { type: "json" } });
// ->
import.source("./foo.js");
import("./bar.json", { type: "json" });

That way we just do import(<cache-key>).

Between changing from assert (not an omittable word) to with, this proposal was introduced which needed another top-level key, so I'm wondering if this wasn't previously considered.

ljharb commented 1 year ago

@nayeemrmn yes, a top-level object key is critical to ensure we aren't preventing all future extensions.

nayeemrmn commented 1 year ago

I guess I thought the attributes+phases harmony seems relatively "complete", maybe it's fine to draw a line at import(<cache-key>) with new Module() for more out-there features.

... But on second thought, the 'error on unknown attributes' behaviour is reason enough to allocate a top-level key.