Scopes as objects

52 views
Skip to first unread message

johnjbarton

unread,
Feb 27, 2013, 12:00:24 PM2/27/13
to js-t...@googlegroups.com
In some ways,
   var x = 1;
resembles
   theScope.x = 1;
where theScope is a compiler-invented object representing the current scope.

For analysis tools it might be advantageous to transcode variables to properties of scope objects. Scope objects arise naturally anyway and such a transcoding would mean a dramatic reduction in analysis code complexity.

But could it be correct?  

jjb

John Lenz

unread,
Feb 27, 2013, 12:18:35 PM2/27/13
to js-t...@googlegroups.com
The problems areas you want to look at are:

catch expressions (which introduce a scope)
with blocks (which introduces an object as a scope)
global scope (which is complex blending of browser properties, window
object properties, and global variables)
> --
> --
> http://clausreinke.github.com/js-tools/resources.html - tool information
> http://groups.google.com/group/js-tools - mailing list information
>
> ---
> You received this message because you are subscribed to the Google Groups
> "js-tools" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to js-tools+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Yusuke SUZUKI

unread,
Feb 27, 2013, 12:20:47 PM2/27/13
to js-t...@googlegroups.com
The problems areas you want to look at are:

And I suggest adding FunctionExpression name scope to this list.
--
Regards,
Yusuke Suzuki

Peter van der Zee

unread,
Feb 27, 2013, 12:36:43 PM2/27/13
to js-t...@googlegroups.com
On Wed, Feb 27, 2013 at 6:20 PM, Yusuke SUZUKI <utata...@gmail.com> wrote:
>> The problems areas you want to look at are:

All of the above.

Additionally, when doing this at runtime, keep in mind that you have
no way of telling whether a scope is garbage collected. So every time
you create a new function, and a new scope object, it will never
disappear (unless you do the hard work for it as well, of course).

Statically, it's fine of course, since you only have to create one
scope object per scope (globla/function/catch). I'm not sure how you
could do with safely (statically), though.

- peter

johnjbarton

unread,
Feb 27, 2013, 3:33:03 PM2/27/13
to js-t...@googlegroups.com


On Wednesday, February 27, 2013 9:20:47 AM UTC-8, Yusuke SUZUKI wrote:
The problems areas you want to look at are:

And I suggest adding FunctionExpression name scope to this list.

I think this one is a matter of which scope gets the function name. That is, if my internal compiler scope object is correct for function expressions vs function declarations, then my reified scope object should also be correct.
 

On Thu, Feb 28, 2013 at 2:18 AM, John Lenz <conca...@gmail.com> wrote:
The problems areas you want to look at are:

catch expressions (which introduce a scope) 
with blocks (which introduces an object as a scope)
Thanks, looks like traceur misses this one.
 
global scope (which is complex blending of browser properties, window
object properties, and global variables)
 
Yes, maybe only experiment will tell the tale here...

substack

unread,
Feb 27, 2013, 5:10:52 PM2/27/13
to js-t...@googlegroups.com
https://github.com/substack/scoper will let you modify scope at runtime from the outside, but the indexing is more complicated than just `theScope.x = `.

https://github.com/substack/lexical-scope gives you a data structure similar to scoper, but not modifiable and broken down into global and local variables

John J Barton

unread,
Feb 27, 2013, 6:07:16 PM2/27/13
to js-t...@googlegroups.com
On Wed, Feb 27, 2013 at 9:36 AM, Peter van der Zee <qfo...@gmail.com> wrote:
On Wed, Feb 27, 2013 at 6:20 PM, Yusuke SUZUKI <utata...@gmail.com> wrote:
>> The problems areas you want to look at are:

All of the above.

Additionally, when doing this at runtime, keep in mind that you have
no way of telling whether a scope is garbage collected. So every time
you create a new function, and a new scope object, it will never
disappear (unless you do the hard work for it as well, of course).

I was imagining creating the scope-representation object upon entering the scope, as a (transcoded) local. Then the lifetime of this object should match the lifetime of the scope. 
 

Statically, it's fine of course, since you only have to create one
scope object per scope (globla/function/catch). I'm not sure how you
could do with safely (statically), though.

Please elaborate on this last comment, I'm not following you.

jjb

Peter van der Zee

unread,
Feb 27, 2013, 6:11:17 PM2/27/13
to js-t...@googlegroups.com
On Thu, Feb 28, 2013 at 12:07 AM, John J Barton
<johnj...@johnjbarton.com> wrote:
>> Statically, it's fine of course, since you only have to create one
>> scope object per scope (globla/function/catch). I'm not sure how you
>> could do with safely (statically), though.
>
>
> Please elaborate on this last comment, I'm not following you.
>

Just saying that for static analysis there's just one object per
scope, ever, since you don't actually run the code in that case. The
`with` statement is hard to do statically that way though.

- peter

Ariya Hidayat

unread,
Feb 27, 2013, 9:48:39 PM2/27/13
to js-t...@googlegroups.com

Yusuke SUZUKI

unread,
Feb 27, 2013, 11:49:38 PM2/27/13
to js-t...@googlegroups.com
Yusuke's project can be useful as well: https://github.com/Constellation/escope.

escope is used to implement esmangle minifier / optimizier[1], it handles ECMA262 scope precisely (example[2]).
And it is also used by keeyipchan's estoggles[3], JavaScript scope information viewer (demo[4])



--
--
http://clausreinke.github.com/js-tools/resources.html - tool information
http://groups.google.com/group/js-tools - mailing list information

---
You received this message because you are subscribed to the Google Groups "js-tools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to js-tools+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
Regards,
Yusuke Suzuki

Yusuke SUZUKI

unread,
Feb 27, 2013, 11:57:30 PM2/27/13
to js-t...@googlegroups.com

John J Barton

unread,
Feb 28, 2013, 11:59:04 AM2/28/13
to js-t...@googlegroups.com
On Wed, Feb 27, 2013 at 8:49 PM, Yusuke SUZUKI <utata...@gmail.com> wrote:
Yusuke's project can be useful as well: https://github.com/Constellation/escope.

escope is used to implement esmangle minifier / optimizier[1], it handles ECMA262 scope precisely (example[2]).
And it is also used by keeyipchan's estoggles[3], JavaScript scope information viewer (demo[4])


I'm a bit confused by the discussion on that issue.  For the function expression:
Bear.prototype.attack = function attack() {
    function rage() {
    }
    return 'claw'
}
it seems like we have three scopes:
  1 Global, -- contains Bear
  2) attack, -- contains attack, rage
  3) rage -- empty
So the surprise here is that function name 'attack' appears in the function scope attack(), not in Global. But the issue refers to a functionExpressionScope as special. Why?

jjb

Rick Waldron

unread,
Feb 28, 2013, 12:12:04 PM2/28/13
to js-t...@googlegroups.com
I believe that's covered in the "NOTE" that is not included in the ticket thread:


NOTE The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

Rick
 

jjb

John J Barton

unread,
Feb 28, 2013, 12:46:33 PM2/28/13
to js-t...@googlegroups.com
I would say the same thing using two scopes: The Identifier in a FunctionExpression binds the function in the scope of the function itself; the identifier is not bound in the scope enclosing the FunctionExpression. 

Which is to say: there are only two scopes here and the scope of the FunctionExpression is only different from the scope of a FunctionDeclaration through this one addition entry. I guess that explains what is meant in the referenced issue thread by functionExpressionScope. It's not a separate scope, just a name for a function scope that has this extra rule.

Thanks,
jjb

Yusuke SUZUKI

unread,
Feb 28, 2013, 2:17:29 PM2/28/13
to js-t...@googlegroups.com
it seems like we have three scopes:
  1 Global, -- contains Bear
  2) attack, -- contains attack, rage
  3) rage -- empty

No. According to section 13,

The production
    FunctionExpression : function Identifier ( FormalParameterListopt ) { FunctionBody }
is evaluated as follows:
    1. Let funcEnv be the result of calling NewDeclarativeEnvironment passing the running execution context’sLexical Environment as the argument
    2. Let envRec be funcEnv’s environment record.
    3. Call the CreateImmutableBinding concrete method of envRec passing the String value of Identifier as the argument.
    4. Let closure be the result of creating a new Function object as specified in 13.2 with parameters specified by FormalParameterListopt and body specified by FunctionBody. Pass in funcEnv as the Scope. Pass intrue as the Strict flag if the FunctionExpression is contained in strict code or if its FunctionBody is strict code.
    5. Call the InitializeImmutableBinding concrete method of envRec passing the String value of Identifier andclosure as the arguments.
    6. Return closure. 
 
special `funcEnv` is constructed for function name, so we have four scopes,

1) Global, -- contains Bear
2) attack funcEnv,  -- contains attack
3) attack,  -- contains rage
4) rage, -- empty

This behavior unifies FunctionExpression / FunctionDeclaration scope and bindings instantiation code (10.4.3 and 10.5)

And this difference is observed following code,

    'use strict';
    var i = function attack() {
        var attack = 'test';
    };
    i();  // Error not raised

Function name binding is immutable (section 13 step 3), but above script doesn't raise TypeError because function name `attack` is not instantiated normal function's scope.

Regards,
Yusuke Suzuki

Peter van der Zee

unread,
Feb 28, 2013, 2:31:09 PM2/28/13
to js-t...@googlegroups.com
On Thu, Feb 28, 2013 at 8:17 PM, Yusuke SUZUKI <utata...@gmail.com> wrote:
> 'use strict';
> var i = function attack() {
> var attack = 'test';
> };
> i(); // Error not raised

o_0

You just blew my mind. Thanks.

I was under the strong impression that the name was just an immutable
local variable. Seems I was wrong.

- peter

John J Barton

unread,
Feb 28, 2013, 2:46:39 PM2/28/13
to js-t...@googlegroups.com
Thanks! But ... is this really just a theoretical explanation or do we really need to create this extra scope?
How can we detect the immutability of the binding in 13.3? The only place we can physically write on the binding is in the inner scope where we can rebind, eg var attack = 'test';
If I don't rebind 'attack' then it's mutability does not matter; if I do, then it does not matter either since I can't use it after that.

jjb

Yusuke SUZUKI

unread,
Feb 28, 2013, 3:05:29 PM2/28/13
to js-t...@googlegroups.com
How can we detect the immutability of the binding in 13.3?

We can detect this immutability by using following code[1],


(function () {
'use strict';
var i = function attack() {
attack = 'test';
};
i(); // Error should be raised
}());

Caution: SpiderMonkey, JSC and my engine[2] handles it correctly, but V8 doesn't. It's V8 bug.

is this really just a theoretical explanation or do we really need to create this extra scope?

Practically we can remove extra scope creation in scope analyzer tools - instantiating inner scope, and at the end instantiate immutable function name binding to inner scope only when inner scope doesn't have binding which name is the same to function name.
But one of escope project purposes is constructing scope analyzer that is extremely precise to ECMA262 5.1th spec, so we handle these edge cases completely.



--
--
http://clausreinke.github.com/js-tools/resources.html - tool information
http://groups.google.com/group/js-tools - mailing list information
 
---
You received this message because you are subscribed to the Google Groups "js-tools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to js-tools+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Regards,
Yusuke Suzuki

John J Barton

unread,
Feb 28, 2013, 3:19:34 PM2/28/13
to js-t...@googlegroups.com
On Thu, Feb 28, 2013 at 12:05 PM, Yusuke SUZUKI <utata...@gmail.com> wrote:
How can we detect the immutability of the binding in 13.3?

We can detect this immutability by using following code[1],

(function () {
'use strict';
var i = function attack() {
attack = 'test';
};
i(); // Error should be raised
}());

Caution: SpiderMonkey, JSC and my engine[2] handles it correctly, but V8 doesn't. It's V8 bug.

Oh! I tested this case exactly ... in V8 ;-) 
 

is this really just a theoretical explanation or do we really need to create this extra scope?

Practically we can remove extra scope creation in scope analyzer tools - instantiating inner scope, and at the end instantiate immutable function name binding to inner scope only when inner scope doesn't have binding which name is the same to function name.
But one of escope project purposes is constructing scope analyzer that is extremely precise to ECMA262 5.1th spec, so we handle these edge cases completely.

Thanks for your patient explanations,

jjb

Ian Bicking

unread,
Feb 28, 2013, 4:46:10 PM2/28/13
to js-t...@googlegroups.com
You should check out this project: https://github.com/toolness/slowmo-js

It translates Javascript code to monitor its execution, including scoping like you describe.


--

John J Barton

unread,
Feb 28, 2013, 11:16:34 PM2/28/13
to js-t...@googlegroups.com
Ok thanks, that's encouraging. 

I'll start a new thread about that UI.

jjb
Reply all
Reply to author
Forward
0 new messages