Hello all,

​We are in the process of implementing the global lexical scope per ES6.
This changes the semantics of global level 'let' and 'const' bindings from
our non-standard semantics to standard semantics.

Currently, global 'let' and 'const' bindings ​introduce properties onto the
global object. Global 'let' behaves identically to 'var', and global
'const' is like 'var', with the exception that the property it introduces
is read-only. Since they behave essentially like 'var', they can be
redeclared and there is no TDZ (i.e., you can use them before their
declarator is reached, resulting in an undefined).

​In ES6, this changes.

1. Global 'let' and 'const' are no longer properties on the global object.
They go into a separate global lexical scope.

2. Global 'let' and 'const' may not be redeclared at the global level with
'let', 'const', or 'var'.

3. Global 'let' and 'const' are subject to temporal dead zone (TDZ)
semantics. If they are referenced before their declarator is executed, a
ReferenceError is thrown. For example,

dump(x); // will throw instead of print undefined.
let x = 42;

4. The global lexical scope is extensible. This means dynamic scope (lol!):

<script>
function f() { dump(x); }
f(); // prints undefined​
​</script>

<script>
​let x = 42;
f(); // prints 42
</script>

As you can imagine, these changes break all our chrome code. Almost all the
errors are due to 1) and 2).

Due to 1), there are many places where code expects 'let' and 'const'
bindings are expected to be properties. Cu.import is a common offender:

Foo.jsm:
const SOME_CONSTANT = 42;

foo.js:
// SOME_CONSTANT isn't a property on the global scope returned by Cu.import
const { SOME_CONSTANT } = Cu.import("Foo.jsm", {})

Due to 2), there are thousands of places where we redeclare Ci, Cc, Cu,
etc. Many tests redeclare 'let' and 'const' bindings. Test harnesses also
like to inject code with 'let'.


I am in the process of slowly fixing the world.

​Because ​until now, our global 'let' semantics have been identical to
those of 'var', I have already landed a patch that mass replaces global
'let' with 'var' as part of bug 1202902.

Because there is no direct syntactic replacement for 'const', I am combing
through the code on a case by case basis.

For Firefox devs, I ask 2 things:

1) For bindings expected to be properties on the global scope, please do
that explicitly with |this.foo = ...| or 'var' and stop using 'let' and
'const'.

2) Understand the semantics of Cu.import. From reading the code, this seems
commonly misunderstood. The API is |Cu.import(path, targetObj)|. In
pseudocode, what Cu.import does is:

... executes script pointed to path ...

for (symbol of jsmGlobalScope.EXPORTED_SYMBOLS) {
​  targetObj[symbol] = jsmGlobalScope[symbol];
}
​
​return jsmGlobalScope;
​
​That is, Cu.import's return value is the *entire global scope* of the JSM.
It isn't targetObj. It doesn't respect EXPORTED_SYMBOLS. You can get
anything you want out of the global scope of the JSM.​

The relevant bugs are bug 1202902 and bug 589199.

Please reach out on IRC if you have questions.
-- 
       shu
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to