tc39 / proposal-global

ECMAScript Proposal, specs, and reference implementation for `global`
http://tc39.github.io/proposal-global/
MIT License
349 stars 18 forks source link

Add a "use global" directive #41

Closed RohanTalip closed 5 years ago

RohanTalip commented 5 years ago

Why not let developers decide a) whether to use the exposed global object and b) what to name it in their code?

My suggestion: allow a "use global" / 'use global' directive in directive prologues, similar to the “use strict” / 'use strict' directive (note the use of both single and double quotes, similar to use strict). The directive would expose the global object, and similar to the “use strict” directive, the “use global” directive would only apply to the current scope. If no directive is present, JavaScript engines should not expose the global object (yet, see below).

The default for the global object name could be global. Since the actual name appears to be controversial with multiple alternate suggestions put forward and also has restrictions as well as node and web compatibility issues and pushback for the current name of globalThis, allow for the name to be changed via “use global as X”. For example “use global as globalThis” or “use global as globals” should be valid. (Renaming via as can already done in import statements, so should be familiar to many developers.)

So, rather than enforcing a name on all developers and causing compatibility issues, maybe empower the developers instead to choose whether to even use this language change and what to call it in their code?

Optionally, global could be made the default name after Y years, where Y could be 2, 5, 10 etc, i.e. after everyone has had time to change their code and gotten used to it being the default.

I couldn't find any similar suggestions in the existing issues in this repository. Please point me to them if I missed them.

ljharb commented 5 years ago

That’s for the suggestion!

It is required to be a shadowable identifier; see the constraints here: https://github.com/tc39/proposal-global/blob/master/NAMING.md#constraints

Separately, the strict mode pragma was largely considered a mistake, and the general reaction is “no new modes”, so that approach would have received a large amount of pushback.

Unfortunately global will never be able to be the default name, since there’s too much code that never gets updated, and none of it can ever be allowed to break.

RohanTalip commented 5 years ago

Thanks for the quick response! 😃

It is required to be a shadowable identifier; see the constraints here: https://github.com/tc39/proposal-global/blob/master/NAMING.md#constraints

I don't see the word "shadowable" on the NAMING page. What does it mean for a global to be "shadowable"? Are you referring to constraint 2? :

Must be a global identifier, so that it can be "deniable" per compartment - meaning, that two conceptual "compartments" in the same realm must be able to be provided two different objects for the global. This means it can't be stored on any object that's accessible via syntax (ie, undeniable) - so it can't be a property on Object, or Function, or Error, etc. ...

Pardon my lack of knowledge in this area, but how would my suggestion not work with that constraint? The ECMAScript/JavaScript engines could inject the global object into each realm, and it could also be a different one for each realm. (From my research today into ECMAScript realms, I found this Stack Overflow Q&A that indicates a realm is associated with a window/frame/tab or a web/service worker.)

As an aside, again from my research today into compartments and realms, it seems that at least with regards to Mozilla's JavaScript engine (1 2 3), there are multiple realms per compartment.

Is there a different definition of compartment that you are using? (The current ECMAScript Language Specification doesn't mention compartments at all.)

Are you instead referring to the Realms API proposal (which references this gist) and is only in stage 2? The main GitHub page for that proposal mentions compartment twice, but seems to be implying that a compartment is a nested realm (if I'm reading it right).

Is there a different constraint that you are referring to?

Separately, the strict mode pragma was largely considered a mistake, and the general reaction is “no new modes”, so that approach would have received a large amount of pushback.

Acknowledged.

How about something like Python's from __future__ import X (used for writing Python code that is compatible with both Python 2 and Python 3, or for transitioning Python 2 code to Python 3).

i.e. In ECMAScript/JavaScript it might be something like: import global from "__future__"

Or renaming the module: import global from "global"

With an alias: import { global as globalThis } from "global"

(Obviously the module name could be different.)

The module could be synthetic, i.e. not backed by a real file, but instead provided by the ECMAScript/JavaScript engine. Alternatively, this could also provide a way for this functionality to be provided by a shim or polyfill.

The downside is that the import will have to be done at the top level of a file/module, until the proposal for dynamic imports is approved or until implemented by one's ECMAScript/JavaScript engine of choice.

An alternative might be to do const global = require("global") for Node / CommonJS.

If this approach is at all interesting and viable, I can write up a separate suggestion as a new issue.

Unfortunately global will never be able to be the default name, since there’s too much code that never gets updated, and none of it can ever be allowed to break.

That's why I was thinking something developers can opt in for (only when needed) would be best.

ljharb commented 5 years ago

By "shadowable", i mean the same concept as variables:

const a = 3;
{
  const a = 4;
  assert.equal(a, 4); // the outer "a" is "shadowed" by the inner one
}

Additionally, I think having a non-global identifier in scope be magically "injected" would be pretty confusing.

Regarding built-in modules: 1) those don't exist yet, 2) it's not clear that they'll ever be viable; 3) in order to exist, they'd need the same ability to alter their meaning per-scope to meet the constraints; 4) import doesn't work in Scripts, only Modules.

graingert commented 5 years ago

can't you just replace: "use global";, with const global = globalThis;

ljharb commented 5 years ago

Closing as answered: https://github.com/tc39/proposal-global/issues/41#issuecomment-460000645