-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
src,lib: implement import.meta #18368
Conversation
doc/api/esm.md
Outdated
|
||
Available with the flag `--harmony-import-meta`, the `import.meta` metaproperty | ||
is an `Object` that contains the following properties: | ||
* `url` {String} The absolute `file:` URL of the module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit: we usually lowercase primitive types in docs (i.e. {string}
)
Is the idea with |
doc/api/esm.md
Outdated
Available with the flag `--harmony-import-meta`, the `import.meta` metaproperty | ||
is an `Object` that contains the following properties: | ||
* `url` {string} The absolute `file:` URL of the module | ||
* `require` {Function} The same `require` function that is usually available in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you link to the require()
docs here.
@targos can we split out |
@bmeck done. I kept the JS initialization function for later use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this add some tests that import.meta.nothing
is an error, as well as import.meta.toString
?
@ljharb is the following check fine? assert.stictEqual(Object.getPrototypeOf(import.meta), null);
assert.deepEqual(Object.keys(Object.getOwnPropertyDescriptors(import.meta)), ['url']); |
src/module_wrap.cc
Outdated
Local<Object> meta) { | ||
Isolate* isolate = context->GetIsolate(); | ||
Environment* env = Environment::GetCurrent(isolate); | ||
meta->CreateDataProperty(context, env->url_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm wondering if there's any perf hit with moving this to the js callback. if there isn't i would suggest doing that just for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean by passing the URL string to the JS callback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no i mean like
importMetaCallback(wrap, meta) {
// attach wrap.url to meta in a safe way here
}
@bmeck should probably be gOPDs, but sure, that sounds great! |
import assert from 'assert'; | ||
|
||
const urlReg = /^file:\/\/\/.*\/test\/es-module\/test-esm-import-meta\.mjs$/; | ||
assert(import.meta.url.match(urlReg)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per #18368 (review) we can add
assert.stictEqual(Object.getPrototypeOf(import.meta), null);
assert.deepEqual(Object.keys(Object.getOwnPropertyDescriptors(import.meta)), ['url']);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the second line use Reflect.ownKeys(import.meta)
instead? Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change ['urls']
to [{ enumerable: true, writable: false, configurable: false, value: 'url' }]
, eg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reflect.ownKeys
is good because it also covers symbols; but it doesn't cover descriptors.
As |
probs not, we don't do it for import() and the features are still experimental above node's proverbial head. |
@devsnek I plan to open a PR to do the same for import() fwiw edit: both features are shipping in chrome with the flag turned off... the flag currently is only turned on in V8 to embedders from having the apis called without the callback being set (would have an unhandled rejection) |
src/module_wrap.cc
Outdated
void ModuleWrap::HostInitializeImportMetaObjectCallback( | ||
Local<Context> context, Local<Module> module, Local<Object> meta) { | ||
Isolate* isolate = context->GetIsolate(); | ||
Environment* env = Environment::GetCurrent(isolate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiny nit: Can you use Environment::GetCurrent(context)
? Getting it from the isolate only looks up the context on the isolate and takes it from there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks! I didn't know there was a Environment::GetCurrent(context)
Can we add |
@Fishrock123 you can get |
I'm not really sure that means we should force users to always parse the url when there is already a precedent set here. I'd love to know how you can figure out |
personally i'm -1 to dirname/filename. you have your url which is generally enough and to be honest the cases where you need the filename of the file you wrote are imo generally rare enough to warrant you having to parse the url yourself. |
The precedent exists but normalization of
Parsing out |
@jdalton the main attraction to frozen things like that is that you can't bail out of static analysis if it becomes mutable. Bailing out is probably fine if people have to do it for browsers anyway I think, but still a little bit of a question on who is actively wanting to rewrite |
@jdalton I just said it'd be unfortunate; not that i'd "fight" for it. I could ask the same question of browsers - why would they ship a fully unlocked descriptor without consulting with node first? "Interoperable" could also mean that browsers ship a non-writable non-enumerable descriptor, for example. |
I think it's totally fine to bring those things up as additions or changes to proposals/specs/browsers-early-implementations. However, the ship has kinda sailed on the |
src/module_wrap.cc
Outdated
ModuleWrap* module_wrap = ModuleWrap::GetFromModule(env, module); | ||
|
||
if (module_wrap == nullptr) { | ||
env->ThrowError("ModuleWrap object not found in map"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we just return and leave the object empty? The upcoming vm.Module
PR will make it possible to have Modules that are not in the core module map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't the vm.Module
code just delete the property if it is configurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but this line throws an error. We don’t want that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the throw, but we will probably have to come up with a solution to configure import.meta
in vm.Module
@targos Just curious, can you check that For example in Chrome: eval("import.meta")
// throws "SyntaxError: Cannot use 'import.meta' outside a module |
@jdalton This is already tested by V8:
|
@targos Yep. I know Node had to do some extra work to make static |
@jdalton Here is the output: $ cat test.mjs
eval("import.meta");
$ ./node --experimental-modules test.mjs
(node:16949) ExperimentalWarning: The ESM module loader is experimental.
SyntaxError: Cannot use 'import.meta' outside a module
at file:///home/mzasso/git/nodejs/node/test.mjs:2:1
at ModuleJob.run (internal/loader/ModuleJob.js:106:14)
at <anonymous>
|
I had to rebase because of a conflict. |
Thanks! It looks like it's missing the arrow stack decorator. |
Other than the conflict, is there anything preventing this from getting merged? |
Implement the C++ callback that is required to configure the `import.meta` object and add one property: - url: absolute URL of the module
One more CI before landing: https://ci.nodejs.org/job/node-test-pull-request/12877/ |
Landed in 9e1a6f8 |
Implement the C++ callback that is required to configure the `import.meta` object and add one property: - url: absolute URL of the module PR-URL: nodejs#18368 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Implement the C++ callback that is required to configure the `import.meta` object and add one property: - url: absolute URL of the module PR-URL: nodejs#18368 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
The feature is still behind the --harmony-import-meta V8 flag.
This commit implements the C++ callback that is required to configure
the
import.meta
object and addstwo propertiesone property:- require: CommonJSrequire
function/cc @nodejs/esm @MylesBorins @nodejs/tsc
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
ESM