Closed
Description
ECMAScript Module Blocks Proposal
https://github.com/tc39/proposal-js-module-blocks
@RyanCavanaugh's notes
- For web workers projects you have an entry point that is a separate file
- Typically there is tight coupling between the invoker and the worker
- Proposal: Instead of a filename, you can have a "module block"
- This block is not lexically scoped (from a value perspective)
- So what does TS do with scoping here?
- Web workers are already a pain in TS because you need two (or more likely three, for shared types) "projects"
- Can we implement this reasonably?
- Q: Why do you need two projects?
- A: WebWorker is on webworker context, "main" is on DOM. These have conflicting globals
- The crux is what "script" (nonmodule) files contribute to each area's globals
- Today, all script files constitute your global environment
- What if you could configure this on a per-area basis?
- Package scopes #4913
- https://gist.github.com/RyanCavanaugh/702ebd1ca2fc060e58e634b4e30c1c1c
- Challenge is making this not too complex
- Technically these module blocks can participate in multiple contexts
- Maybe we need a concept of a "type" of the global scope, that could be even a union
- Is that a real use case?
- Downleveling - technically possible in Node?
- We need to establish some boundaries on what you can and cannot use this for, e.g. multiple envs vs just single-env configurability
- Questions
- Could we tool this?
- Do we support this proposal broadly?
- Mixed opinions. Analogues in other languages are... not great
- Some people like the tooling side effects
- (joke about "side effects tho")
- The scoping is confusing
- But the scenario is compelling
- Is the configurability desirable in other contexts?
- Is this a blocking concern?
- 🤷♂️
- Concerns about complexity vs. value calculation
- The configurability here is potentially very complex
- (Sidebar: Discussion of implementation of program and symbol table incrementality)
My notes from when I forgot Ryan was also taking notes:
- One idea is multiple global scopes, merged in different ways.
- Ideally, each of these modules would be able to tell you when you're going to run it in an incompatible context.
- Need to represent modules as functions from global scope to themselves.
- Yes... that's why this proposal feels strange to some on the team. A new type of deferred code block.
- That seems potentially fine.
- Need to represent modules as functions from global scope to themselves.
- This is very similar to the idea of "strict global environments" that Ryan was playing with a while back.
- Problem then and now: how are two utterances of the same type from different global scopes compatible?
- From a compilation perspective, there needs to be some place where you specify what exactly you wanted.
- Likely we won't do the enforcement of "only allow this module to run in this context". You have to know what context you're going to run the module in, use it responsibly.
- Could support
module {}
blocks, but not separate checking contexts.// @ts-nocheck
at top ofmodule {}
😅- But the proposal champions seem interested in the "can we tool this correctly in TypeScript" case.
- Backing up - what is the general feedback about the proposal itself?
- Not a fan of new scoping rules
- Reminded by blocks, procs confusion from Ruby?
- "It's kinda like AppDomains"
- "Yeah I didn't like AppDomains either"
- Seems like this solves real problems though - "split your project into multiple" seems like a bad solution.
- Want to communicate that module blocks will introduce a fair bit of complexity in how users will think about both their global and lexical environments - same applies to tooling authors. Unclear if it's really a net benefit in mental model.
- Web workers are really not a simple scenario or API - a novice user who reaches for it might not realize it's overkill. A user who really understands might be building a full project anyway.
- We are still interested in supporting multiple global environments.
Emit Change For Imports
- Polyfill for
promise.allsettled
package.- Does something different depending on the
this
context.
- Does something different depending on the
- If you write
import allSettled from "promise.allsettled"
- we transform references to that to
promiseallsettled.default(...)
- Babel transforms it to
(0, promiseallsettled).default(...)
- we transform references to that to
- Point of
(0, obj).method(...)
is to avoid bindingthis
incorrectly. - Editor's note:
this
is so annoying. - This is also an issue with namespaces.
- Editor's note: 🙄
- Perf impact?
- Adds a very small amount of time to emit.
- Non-zero but negligible
- Only hits CommonJS, namespace code.
- Pack the PR, get some partner teams to try it out.