Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

Feature: Conditional imports #113

Closed
GeoffreyBooth opened this issue May 20, 2018 · 20 comments
Closed

Feature: Conditional imports #113

GeoffreyBooth opened this issue May 20, 2018 · 20 comments
Labels

Comments

@GeoffreyBooth
Copy link
Member

Node should provide an ESM equivalent of:

if (process.env.DEBUG)
  var { inspect } = require('util');

In other words, let users tell Node to potentially not load modules or module exports into memory, if they might not be used.

Use case 41.

@benjamingr
Copy link
Member

Note that from reading about it it doesn't look like top-level await which is what we discussed last time is going to happen.

Then again, this can be done with dynamic import syntax. The problem is dynamic imports are contagious.

@MylesBorins
Copy link
Contributor

MylesBorins commented May 20, 2018 via email

@devsnek
Copy link
Member

devsnek commented May 20, 2018

there are also some other plans for conditional imports which don't rely on top-level await and some other interesting things like import fallbacks and stuff. afaik no one has made any official proposals yet but its definitely being discussed.

@benjamingr
Copy link
Member

@MylesBorins

What gave you the impression that top level await is not going to happen?

Well, I was the under the impression it means late bindings for modules which I thought were a no-go.

Would love to learn more about the current status.

Spec text is being worked on and it is being brought to tc39 again this week

That's awesome 🎉

@ljharb
Copy link
Member

ljharb commented May 20, 2018

The relevant thing tho is that if it becomes possible in the language, it will automatically be possible in nade - and if it doesn’t, it will be impossible. I’m not sure this issue is directly actionable in node (beyond pursuing changes in TC39)

@benjamingr
Copy link
Member

The relevant thing tho is that if it becomes possible in the language, it will automatically be possible in nade - and if it doesn’t, it will be impossible. I’m not sure this issue is directly actionable in node (beyond pursuing changes in TC39)

If it becomes possible in the language - then by definition JS will have late bindings which resolves both the CommonJS named exports issue and the "conditional imports" issue.

That's a huge fundamental impact for modules IMO.

Moreover, this gives the commitee a chance to find a solution that's a middle-way, for example the proposal's "no exports from modules with top-level await" or "no exports after an await in modules with top-level await" which would solve one issue but not the other.

@ljharb
Copy link
Member

ljharb commented May 21, 2018

I don’t see how top-level await enables late bindings such that named imports from CJS could work; could you elaborate?

@benjamingr
Copy link
Member

I don’t see how top-level await enables late bindings such that named imports from CJS could work; could you elaborate?

First of all - Keep in mind that it's entirely possible I'm misunderstanding the issue entirely 😅

import foo from './somefile'

await somePromiseThatMightNeverSettle();

export const bar = 5;

Here, bar is only exported if the promise settles IIUC.

@ljharb
Copy link
Member

ljharb commented May 21, 2018

I’m pretty sure the 5 is only exported then; but the name “bar” would be exported immediately with a value of undefined, just like a hoisted variable.

@benjamingr
Copy link
Member

I’m pretty sure the 5 is only exported then; but the name “bar” would be exported immediately with a value of undefined, just like a hoisted variable.

Ah, so just to clarify - all the exports from top-level-awaited code would be exported immediately regardless but their values would only be updated at a later point?

@devsnek
Copy link
Member

devsnek commented May 21, 2018

@benjamingr es modules already do that. they populate exports during instantiation and then evaluation actually defines the values of those exports. (except for functions, those are available right after instantiate) but anywau the only difference with top level await is that evaluation might take a bit longer.

@ljharb iirc trying to access bar before it gets its value should throw a reference error. (but a var would be undefined)

@ljharb
Copy link
Member

ljharb commented May 21, 2018

@devsnek sure, I’ll buy the tdz error :-) but that’s still an early static binding, like everything else.

@benjamingr
Copy link
Member

@benjamingr es modules already do that. they populate exports during instantiation and then evaluation actually defines the values of those exports.

Right, but without top-level await is there a way to tell the difference between the two?

Thanks a lot for explaining by the way @ljharb @devsnek, this makes a lot more sense now that I understand it's hoisting rather than late bindings.

@ljharb
Copy link
Member

ljharb commented May 21, 2018

export let foo;
setTimeout(() => { foo = 3; });

altho that wouldn’t give a tdz, i believe.

@devsnek
Copy link
Member

devsnek commented May 21, 2018

@ljharb i get tdz testing that

> const x = new vm.Module('export let foo; setTimeout(() => { foo = 3; });');
undefined
> void x.link(() => 0)
undefined
> x.instantiate()
undefined
> x.namespace
[Module] { foo: <uninitialized> }
> x.namespace.foo
ReferenceError: foo is not defined

@guybedford
Copy link
Contributor

guybedford commented May 21, 2018 via email

@guybedford
Copy link
Contributor

guybedford commented May 21, 2018 via email

@devsnek
Copy link
Member

devsnek commented May 21, 2018

@guybedford ah sorry I thought we were taking about pre-evaluate. nice example.

@ljharb
Copy link
Member

ljharb commented May 21, 2018

No JS in that graph can run pre-evaluate, that’s the whole point/problem :-p

@guybedford
Copy link
Contributor

guybedford commented May 21, 2018 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants