Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-18 Thread Shu-yu Guo
Good catch and thanks for the correction! The take-home from the example is
that: due to the global lexical scope, a TDZ error could arise later due to
newly introduced bindings.

On Thu, Sep 17, 2015 at 7:34 PM, Boris Zbarsky  wrote:

> On 9/17/15 8:26 PM, Shu-yu Guo wrote:
>
>> ​The first call to f() does not throw.
>>
>
> It actually does, because the bareword lookup for "x" fails.  You get
> "ReferenceError: x is not defined".
>
> If you replaced "x" with "window.x" or "self.x" or "this.x" or something I
> think you'd get the behavior you describe.
>
> -Boris
>
> ___
> dev-platform mailing list
> dev-platform@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform
>



-- 
   shu
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-18 Thread Neil

Shu-yu Guo wrote:


Good catch and thanks for the correction! The take-home from the example is
that: due to the global lexical scope, a TDZ error could arise later due to
newly introduced bindings.


So for that I guess the code would have to look like this?


var x;
function f() { dump(x); }
f(); // prints undefined​
​


f(); // throws TDZ error?
​let x = 42;


--
Warning: May contain traces of nuts.
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-18 Thread Gervase Markham
On 17/09/15 19:59, Shu-yu Guo wrote:
> ​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.

I think someone should make you a "var is the new let" t-shirt...

Gerv

___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-18 Thread Tom Schuster
I think that would fail as well, because the let would be shadowing the
global x, which isn't allowed.
On Sep 18, 2015 2:25 PM, "Neil"  wrote:

> Shu-yu Guo wrote:
>
> Good catch and thanks for the correction! The take-home from the example is
>> that: due to the global lexical scope, a TDZ error could arise later due
>> to
>> newly introduced bindings.
>>
>> So for that I guess the code would have to look like this?
>
> 
> var x;
> function f() { dump(x); }
> f(); // prints undefined​
> ​
>
> 
> f(); // throws TDZ error?
> ​let x = 42;
> 
>
> --
> Warning: May contain traces of nuts.
> ___
> dev-platform mailing list
> dev-platform@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform
>
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Changes in chrome JS code due to ES6 global lexical scope

2015-09-17 Thread Shu-yu Guo
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!):


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


​let x = 42;
f(); // prints 42


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


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-17 Thread Boris Zbarsky

On 9/17/15 8:26 PM, Shu-yu Guo wrote:

​The first call to f() does not throw.


It actually does, because the bareword lookup for "x" fails.  You get 
"ReferenceError: x is not defined".


If you replaced "x" with "window.x" or "self.x" or "this.x" or something 
I think you'd get the behavior you describe.


-Boris
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-17 Thread Neil

Shu-yu Guo wrote:


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


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


​let x = 42;
f(); // prints 42


Would you mind clarifying what this is supposed to demonstrate? It looks 
to me that this is demonstrating TDZ semantics, and under ES6 the first 
call to f() will throw.


--
Warning: May contain traces of nuts.
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Changes in chrome JS code due to ES6 global lexical scope

2015-09-17 Thread Shu-yu Guo
On Thu, Sep 17, 2015 at 5:18 PM, Neil  wrote:

> Shu-yu Guo wrote:
>
> 4. The global lexical scope is extensible. This means dynamic scope (lol!):
>>
>> 
>> function f() { dump(x); }
>> f(); // prints undefined​
>> ​
>>
>> 
>> ​let x = 42;
>> f(); // prints 42
>> 
>>
>> Would you mind clarifying what this is supposed to demonstrate? It looks
> to me that this is demonstrating TDZ semantics, and under ES6 the first
> call to f() will throw.
>

​The first call to f() does not throw. These are two separate 
tags, and during the execution of the first