NodeJS's __filename/__dirname in ES6 Modules

# Gil Tayar (3 months ago)

While reading Dominic Denicola's spec for dynamic import() at tc39/proposal-dynamic-import, I read his rational for not having import be a regular function, but rather a "syntactic form". The idea is that import() needs to be "in the scope" of the current module, as it needs to resolve the module path it is given relative to the current module's. Thinking about it some more, I thought it would be a pity for import to be so "special", and asked myself whether there will be more features that will need to be "module-aware" like import().

And there are! (I think...) - __filename and __dirname in NodeJS are exactly such features. Actually, anything passed to the function wrapping each NodeJS module is such a feature, but going over them, only __filename and __dirname are not immediately related to the module mechanism.

So my question is this (and it is specifically addressed to the NodeJS implementors in the group): in NodeJS's implementation of ES6 modules, how will __dirname and __filename be implemented? Will there still be a function wrapper like in the current module implementation? Or will __dirname and __filename be a "syntactic form" like import()? Or something else?

Thanks, Gil Tayar

# Bradley Meck (3 months ago)

The current trend is towards the nodejs/node-eps#39 rewrite which does not have magic variables bmeck/node-eps/blob/b14276ca093fac9cbc3b72ff5433df35ae67fb59/002-es-modules.md#341-environment-variables

There are ideas about exposing the URL of the current ESM via something like docs.google.com/presentation/d/1aq_QjBUQTovj9aQZQrVzS7l1aiOs3ZNlk7wgNTUEMy0/edit#slide=id.g16ab11d101_0_22

# Gil Tayar (3 months ago)

Thanks!

Makes total sense. So why not have Domenic's "import" be a real function that comes from this "js:context", thus obviating the need for a new JavaScript operator?

While I realize that "js:context" will a Node thing, we could have a special import (e.g. import {...} from "js:system") that enables the system to expose real functions, of which one is "dynamicImport" and others would be "currentDir()" and "currentFile()".

In other words - Domenic exposed a real need, but it seems that this need is more general, and not specific only to dynamic import, and should be added to the spec as a special import, just like it may be in Node.

# Bradley Meck (3 months ago)

Please see tc39/proposal-dynamic-import#an-actual-function

As per "currentDir()" and "currentFile()" this may not make sense for all URLs. Please use url.spec.whatwg.org which ships in Node v7+ under require('url').URL and the proposal to bring it into the language itself jasnell/proposal-url . Getting the "directory" of a URL would be ~= new URL('.', file_url).

# Andrea Giammarchi (3 months ago)

FWIW I have both __filename and __dirname implemented in common-js package runtime, and these are resolved as absolute path from the root, unless imported externally where these are resolved as absolute URLs.

Although I must say beside providing some debuggable information, without a core path module I don't see much added value in having these two references.

I still load relatively via module.import('./lib') or module.import('../js/file')

# Gil Tayar (3 months ago)

Bradley,

My point was not file path vs URL (if that was what you were referring to), but rather the fact that the special "import", which needs the current location to operate, is not special, but that it may be a family of functions that need this information, and I gave as an example __dirname/__filename in Node.

What I propose is to find a common way for the developer to import those module-specific functions like import/dirname/filename/fileurl.

As why they can't be regular functions (per tc39/proposal-dynamic-import#an-actual-function) - it is* true* that they need to be something "special". But they can, alternatively, *be imported *from someplace special, e.g. my idea of import {import} from 'js:system'.

While I suspect that for a phase 3 suggestion it is a bit too late to change it wholesale (and the current import spec is phase 3, AFAIK), I just thought to drop it here to see if it sticks.

But thanks for the info on __dirname/__filename in ESMs.

# Gil Tayar (3 months ago)

Andrea,

While it is true that "filename/URL" and "dirname" are not really important in the browser world, they are used a lot in the Node world to read various resources that reside in the same directory (or near the same directory) as the module.

# Andrea Giammarchi (3 months ago)

Absolutely, and same could be done through the browser if these info are available and the server grants reading/listing options, which is why I am exposing exactly the same way NodeJS is doing, through __filename and __dirname, both constants and different per each imported module.

On NodeJS world, and overall in CommonJS environments, these are also de-facto standard and already there. While a bit ugly, name convention speaking, I wouldn't mind having the same via import(). It would be nothing new to learn.

# Isiah Meadows (3 months ago)

IMHO it might be better to have import.filename and import.dirname as meta properties, to fit in with the language better and to avoid creating yet another global (for an admittedly niche use case). It could easily be compiled down via Babel and the likes, and the current import() is at stage 3 already IIRC.

(FWIW ES6 modules are sufficiently different enough that I feel it'd be okay to keep a different syntax for it, and to make it a syntactic form, to fit with the syntactic nature of ES modules.)

Isiah Meadows me at isiahmeadows.com