-
Notifications
You must be signed in to change notification settings - Fork 12.8k
In "declare global" blocks, allow access of block-scoped variables in globalThis #56442
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
Comments
Maybe someone will discover a reason that Iβm wrong, but I think this is just a bug. |
|
Shouldnβt the second case (where the variables are accessed without |
Module scopes are child scopes of script scopes (which are a.k.a. the global scope). |
That doesn't really make sense to me - there's no analog for that kind of nesting (i.e. a module nested in a script scope such that it has access to the script's |
I'm not sure what you mean by "native ECMAScript". ModuleEvaluation and ScriptEvaluation are both top-level operations invoked by the host only, so you need a host to test them out, let it be Node or HTML. You never have access to the script scope in Node, but you can easily do this in HTML: <script>
const a = 1;
</script>
<script type="module">
console.log(a);
</script> If it interests you: https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#sec-runtime-semantics-scriptevaluation, https://tc39.es/ecma262/multipage/ecmascript-language-scripts-and-modules.html#sec-source-text-module-record-initialize-environment BTW, the "nesting" does not happen in a lexical sense. It's merely that each time a script is evaluated, it directly uses the global scope, while when each module is evaluated, it creates a new scope that inherits from the global scope. There's no closures. |
Oh, I was reading it as, the |
Cross-script boundaries are totally weird: a declaration will be visible for any subsequent script, but it is only visible to preceding code within its current script. <script>
console.log(a); // Cannot find variable
</script>
<script>
console.log(a); // undefined
var a = 2;
</script>
<script>
console.log(a); // 2
</script> |
@Josh-Cena I'm in the process of writing a response to your first reply, but it may take a few days before I have the time to complete it.
Same! That's blowing my mind. I thought I also expected the following to "blow up," but it logs <!DOCTYPE html>
<html>
<head>
<script>
const a = 1;
</script>
<script type="module">
const a = 5;
console.log(a); // logs `5`
console.log(globalThis.a); // logs `undefined`
</script>
</head>
<body></body>
</html> I assume this works because of what @Josh-Cena mentioned earlier:
That said, even though this runs (on Firefox, at least), Visual Studio code complains about the second This code, on the other hand, errors at runtime: <!DOCTYPE html>
<html>
<head>
<script>
const a = 1;
</script>
<script type="module">
const a = 5;
const a = 6; // error! Uncaught SyntaxError: redeclaration of const a
console.log(a);
console.log(globalThis.a);
</script>
</head>
<body></body>
</html>
I knew this was possible in TypeScript after finding this StackOverflow post, and it certainly surprised me. But until now, I didn't realize that applied to JavaScript too. |
Yeah, TS is just JS with compile-time types (plus a few value-add runtime features that got grandfathered in). So |
Ah, I meant something slightly different. From that SO post:
Although the ts compiler complains about |
TIL, thanks @Josh-Cena |
For For what it's worth, I found this comment by @mhegazy that says:
This was written in 2016 so I'm not sure if it's still accurate. If the decision were made today, I wonder if I'll close this issue. Thanks again for taking the time to explain this! |
I think "script" is closer-to-the-metal while "global" is more abstract and fits user intuitions better. Most people won't run into the tiny nuancesβand in no world would a "global const" become a property on |
I was thinking this could have worked if the property was made non-writable (and non-configurable), but I guess yeah, the weird control-flow sensitive TDZ semantics would make implementing things that way unrealistic. |
I stand corrected.
People tell me this but I wonder... Could it be that people run into these issues more than it seems, but they lack the knowledge to bring it up? I'm not asking rhetorically, but I'll offer my own experience:
After reading it, I thought I had a solid grasp on what was going on. But it turned out I was mistaken. It wasn't until this post that I learned it has more to do with JavaScript and "global" than TypeScript. If I had the pressure of a deadline, I'd probably use This was kind of a rant, but it's not directed toward you. I'm trying to learn why my experience feels like the opposite of "Most people won't run into the tiny nuances." (It will probably be explained by "Your experience is not the norm," and I'm fine with that explanation, but I want to confirm with others before going with that assumption.) @fatcerberus Sorry for reposting this comment. I made such a large edit it felt like a different reply. |
This might be the reason why ECMAScript didn't have a standard |
π Search Terms
globalThis, declare global block, let, const, var, property
β Viability Checklist
β Suggestion
This wouldn't be a breaking change in existing JavaScript code. When it comes to TypeScript code, I'm not as sure...
Before my request, here's an excerpt of #30477 for context:
The example and fix makes sense to me and I'm not requesting a change for that. But is there any chance #30510 / #30477 could work the way it used to within
declare global
blocks? In other words, I'm requesting for all of this code to compile:π Motivating Example
The examples in the #30477 excerpt make sense to me because they're analogous to runtime behavior. e.g., I can intuit
const foo: number = 42;
shouldn't exist onglobalThis
.But
declare global { ... }
doesn't exist at runtime in at all. It's a part of TypeScript that's erased at transpile. So if this is TypeScript-only, and it's named "declare global," I would assume myconst
s andlet
s apply to global scope.Well it does.
Sometimes.
As a newb, it feels kind of arbitrary. For example, this code compiles like I would expect:
And if I remove
globalThis
from my first example, it behaves the way I would expect:So, it's conditionally global?
This stack overflow post shows some conversation around this topic..
π» Use Cases
The text was updated successfully, but these errors were encountered: