<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hello all,<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​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.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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).<br></div><br><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​In ES6, this changes.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">1. Global 'let' and 'const' are no longer properties on the global object. They go into a separate global lexical scope.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">2. Global 'let' and 'const' may not be redeclared at the global level with 'let', 'const', or 'var'.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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,<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">dump(x); // will throw instead of print undefined.<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">let x = 42;<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">4. The global lexical scope is extensible. This means dynamic scope (lol!):<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><script><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">function f() { dump(x); }<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">f(); // prints undefined​</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​</script><br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><script><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​let x = 42;<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">f(); // prints 42<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"></script><br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">As you can imagine, these changes break all our chrome code. Almost all the errors are due to 1) and 2).<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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:<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Foo.jsm:<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">const SOME_CONSTANT = 42;<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">foo.js:<br> // SOME_CONSTANT isn't a property on the global scope returned by Cu.import<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">const { SOME_CONSTANT } = Cu.import("Foo.jsm", {})<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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'.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>I am in the process of slowly fixing the world.<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​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.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Because there is no direct syntactic replacement for 'const', I am combing through the code on a case by case basis.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">For Firefox devs, I ask 2 things:<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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'.<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">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:<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">... executes script pointed to path ...<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">for (symbol of jsmGlobalScope.EXPORTED_SYMBOLS) {<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​  targetObj[symbol] = jsmGlobalScope[symbol];<br>}<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​return jsmGlobalScope;<br>​</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">​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.​<br><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">The relevant bugs are bug 1202902 and bug 589199.<span class=""><span style="display:block" class=""><span class=""><span title="Bug 589199 - Fix up the global lexical scope when merging off-thread compiled scripts. (r=bhackett)"><span class=""><em></em></span></span></span></span></span></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>Please reach out on IRC if you have questions.<br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><font face="monospace">       shu</font><br></div></div></div></div>
</div>