nodejs / CTC

Node.js Core Technical Committee & Collaborators
80 stars 27 forks source link

TC-39 Discussion: Accessing module metadata #133

Closed jasnell closed 6 years ago

jasnell commented 7 years ago

@domenic led a discussion at TC-39 today on adding the ability to access module relative metadata (e.g. covering the use case for things like __dirname in ES6 modules). The slides are here: https://docs.google.com/presentation/d/1p1BGFY05-iCiop8yV0hNyWU41_wlwwfv6HIDkRNNIBQ/edit?usp=sharing

This is something that we'll need folks here paying attention to and providing feedback on.

cjihrig commented 7 years ago

What was the result of the discussion? Seems like option 1 would be the simplest for Node.

Fishrock123 commented 7 years ago

Seems like option 2 would be more fitting if it could be specced. Particularly from here or some variation of that?

Otherwise, I'd assumed we were going with option 1.


Technically I had a fancier plan for this with the assumption of option 1 but I was kinda hand-wavy.

It would involve appending something similar to the following at the beginning of every file (similar to how we wrap today):

import { module, require, __dirname, __filename } from "internal"
Fishrock123 commented 7 years ago

To my knowledge that wouldn't really break anything ESM-wise.

jasnell commented 7 years ago

Option 1 seemed like the most viable. Option 2 was not popular.

Fishrock123 commented 7 years ago

Unpopular solely based on "spec amend no-no" sentiment or because there is some reason that might not be good?

jasnell commented 7 years ago

Unpopular based on syntax ergonomics, adding a new keyword, etc. There was a third option discussed and ruled out that would allow hosts to do essentially what we're doing currently with require() when injecting __dirname and require() but the consensus was that it had too many potential issues.

I believe (@domenic please correct me if I'm wrong) we landed on somethink like the following two options:

import { foo } from 'js:context'

Or

const { foo } = import.meta;
Fishrock123 commented 7 years ago

@bradleymeck seems to have mentioned import.meta in another issue, which seems aptly appropriate.

bmeck commented 7 years ago

Webkit is pretty hard set against a reserved specifier in https://github.com/whatwg/html/issues/1013 which means pretty much have to do option 2 at this rate.

mhdawson commented 7 years ago

Proposal seems to be: https://github.com/domenic/proposal-import-meta

jasnell commented 7 years ago

So yeah, the proposal on the table is to use import.meta, where the properties on meta are host specific. This will be the place where we can hang things like a module specific import.meta.require() function, or import.meta.__dirname if we want it.

Note, however, that it's going to be far more likely for browsers to use import.meta.url to provide the base URL of the module script rather than anything like __dirname, and I would recommend that we consider doing the same. We can keep __dirname for backwards compatibility, but to help ensure code portability, we really ought to try aligning as much as possible with browsers on meta properties even tho they are fully expected to be host specific.

Also note that the proposal appears to require that import.meta is only available in the Module goal. So we'll need to make sure there is consistency across the two different module types (CommonJS and ES6).

Fishrock123 commented 7 years ago

we really ought to try aligning as much as possible with browsers on meta properties even tho they are fully expected to be host specific.

Erm, did you just describe defeating the point of it?

IMO we need to support the currently injected properties. (Except exports.)

bmeck commented 7 years ago

@Fishrock123 much like aligning with web browsers on ESM semantics which are largely host defined, we need to stay in line enough to create usefulness rather than friction.

We can introduce import.meta.nodejs.* and put w/e on there we want, but the more we put on there the less universal code will be for both people writing for the browser and for node.

I'd rather people use import './cjs.js' to get a hold of CJS magic variables until we figure out exactly which workflows cannot be supported with just url. For example, import() largely removes the need for require() and is universal so preferable. Even if we introduce import.meta.nodejs.__dirname that is still a code change for people so why not have them use import.meta.url?

bmeck commented 7 years ago

ah, to note: module would be super screwy in ESM since it has different semantics and parts of it wouldn't make sense / it wouldn't inherit from CJS's module class

Trott commented 6 years ago

This issue has been inactive for a while and this repository is now obsolete. I'm going to close this, but feel free to open another issue in a relevant active repository (TSC perhaps?) and include a link back to this issue if this is a subject that should receive continued attention.