Title: [194251] trunk
Revision
194251
Author
[email protected]
Date
2015-12-17 17:09:13 -0800 (Thu, 17 Dec 2015)

Log Message

Provide a way to distinguish a nested lexical block from a function's lexical block
https://bugs.webkit.org/show_bug.cgi?id=152361

Reviewed by Saam Barati.

Source/_javascript_Core:

* bytecompiler/BytecodeGenerator.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::emitPushFunctionNameScope):
(JSC::BytecodeGenerator::emitPushCatchScope):
Each of these are specialized scopes. They are not nested lexical scopes.

(JSC::BytecodeGenerator::pushLexicalScope):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
Include an extra parameter to mark the SymbolTable as a nested lexical or not.

* bytecompiler/NodesCodegen.cpp:
(JSC::BlockNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ForInNode::emitMultiLoopBytecode):
(JSC::ForOfNode::emitBytecode):
(JSC::SwitchNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):
Each of these are cases of non-function nested lexical scopes.
So mark the SymbolTable as nested.

* inspector/protocol/Debugger.json:
* inspector/InjectedScriptSource.js:
Include a new scope type.

* inspector/JSJavaScriptCallFrame.h:
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::scopeType):
Use the new "NestedLexical" scope type for nested, non-function,
lexical scopes. The Inspector can use this to better describe
this scope in the frontend.

* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::isNestedLexicalScope):
* debugger/DebuggerScope.h:
* runtime/JSScope.cpp:
(JSC::JSScope::isNestedLexicalScope):
* runtime/JSScope.h:
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::SymbolTable):
(JSC::SymbolTable::cloneScopePart):
* runtime/SymbolTable.h:
Access the isNestedLexicalScope bit.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
(WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection):
New "Block Variables" string.

* UserInterface/Models/ScopeChainNode.js:
New "Block" scope type, and update existing types.

* UserInterface/Controllers/DebuggerManager.js:
(WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload):
Parse the protocol type to frontend types. Use the protocol generated enum.

LayoutTests:

* inspector/debugger/breakpoint-scope-expected.txt:
We will soon remove the backend sending a "Local" scope.
The backend was just marking the first closure scope as local.
The frontend can do this itself and do a better job of it.

* inspector/model/resources/all-scopes.js: Added.
(testAllScopes.innerScope):
(testAllScopes):
* inspector/model/resources/block-scopes.js: Added.
(testBlockScopes):
(testBlockScopes.method):
* inspector/model/resources/function-name-scopes.js: Added.
(testFunctionNameScope1):
* inspector/model/scope-chain-node-expected.txt: Added.
* inspector/model/scope-chain-node.html: Added.
Tests for ways to get all the different scope types and
specific cases of certain scope types.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (194250 => 194251)


--- trunk/LayoutTests/ChangeLog	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/LayoutTests/ChangeLog	2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,3 +1,28 @@
+2015-12-17  Joseph Pecoraro  <[email protected]>
+
+        Provide a way to distinguish a nested lexical block from a function's lexical block
+        https://bugs.webkit.org/show_bug.cgi?id=152361
+
+        Reviewed by Saam Barati.
+
+        * inspector/debugger/breakpoint-scope-expected.txt:
+        We will soon remove the backend sending a "Local" scope.
+        The backend was just marking the first closure scope as local.
+        The frontend can do this itself and do a better job of it.
+
+        * inspector/model/resources/all-scopes.js: Added.
+        (testAllScopes.innerScope):
+        (testAllScopes):
+        * inspector/model/resources/block-scopes.js: Added.
+        (testBlockScopes):
+        (testBlockScopes.method):
+        * inspector/model/resources/function-name-scopes.js: Added.
+        (testFunctionNameScope1):
+        * inspector/model/scope-chain-node-expected.txt: Added.
+        * inspector/model/scope-chain-node.html: Added.
+        Tests for ways to get all the different scope types and
+        specific cases of certain scope types.
+
 2015-12-17  Keith Miller  <[email protected]>
 
         [ES6] Add support for Symbol.hasInstance

Modified: trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt (194250 => 194251)


--- trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt	2015-12-18 01:09:13 UTC (rev 194251)
@@ -3,12 +3,12 @@
 
 Starting Test
 Hit breakpoint at line: 4, column: 8
-scope-chain-type-local properties:
+scope-chain-type-closure properties:
     resolve
     reject
 scope-chain-type-closure properties:
     p
-scope-chain-type-globalLexicalEnvironment properties:
+scope-chain-type-global-lexical-environment properties:
     lexicalVariable
 scope-chain-type-global (properties not listed)
 Tests done

Added: trunk/LayoutTests/inspector/model/resources/all-scopes.js (0 => 194251)


--- trunk/LayoutTests/inspector/model/resources/all-scopes.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/all-scopes.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,55 @@
+// Global
+var globalVariable = 1;
+
+// GlobalLexicalEnvironment
+let lexicalGlobalVariable = 2;
+
+function testAllScopes() {
+    // Closure
+    var closureVariable1 = 3;
+    let closureVariable2 = 4;
+
+    function innerScope() {
+        // Closure
+        var innerClosureVariable1 = 5;
+        let innerClosureVariable2 = 6;
+
+        // With (the object)
+        with ({withObjectProperty: 7, __proto__: null}) {
+            // Block
+            let withBlockVariable = 8;
+
+            // Catch (the `e` object)
+            try {
+                throw 9;
+            } catch (exceptionVariable) {
+                // Block
+                let catchBlockVariable = 10;
+
+                // Function Name
+                (function functionName() {
+
+                    // Closure ("Local")
+                    var localVariable1 = 11;
+                    let localVariable2 = 12;
+
+                    console.log("Variables",
+                        globalVariable,
+                        lexicalGlobalVariable,
+                        closureVariable1, closureVariable2,
+                        innerClosureVariable1, innerClosureVariable2,
+                        withBlockVariable,
+                        exceptionVariable,
+                        catchBlockVariable,
+                        functionName.name,
+                        localVariable1, localVariable2);
+
+                    // Pause.
+                    debugger;
+                })();
+            }
+        }
+    }
+
+    innerScope();
+}

Added: trunk/LayoutTests/inspector/model/resources/block-scopes.js (0 => 194251)


--- trunk/LayoutTests/inspector/model/resources/block-scopes.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/block-scopes.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,147 @@
+function testBlockScopes() {
+    // Normal (not Block)
+    let a = 1;
+    console.log("normal", a);
+    debugger; // 1
+    
+    // If
+    if (true) {
+        let a = 990;
+        console.log("if", a);
+        debugger; // 2
+    }
+
+    // Else
+    if (false) {}
+    else {
+        let a = 991;
+        console.log("else", a);
+        debugger; // 3
+    }
+
+    // While
+    while (true) {
+        let a = 992;
+        console.log("while", a);
+        debugger; // 4
+        break;
+    }
+
+    // Do/While
+    do {
+        let a = 993;
+        console.log("do", a);
+        debugger; // 5
+    } while (false);
+
+    // For
+    for (let a = 994; true; ++a) {
+        console.log("for", a);
+        debugger; // 6
+        break;
+    }
+
+    // ForIn
+    for (let a in ({"995":1})) {
+        console.log("for-in", a);
+        debugger; // 7
+        break;
+    }
+
+    // ForOf
+    for (let a of [996]) {
+        console.log("for-of", a);
+        debugger; // 8
+        break;
+    }
+
+    // Switch
+    switch ("test") {
+    case "test":
+        let a = 997;
+        console.log("case", a);
+        debugger; // 9
+        // fallthrough
+    default:
+        a += 0.5;
+        console.log("default", a);
+        debugger; // 10
+        break;
+    }
+
+    // Try
+    try {
+        let a = 998;
+        console.log("try", a);
+        debugger; // 11
+    } catch (e) {}
+
+    // Catch
+    try {
+        throw "Error";
+    } catch (e) {
+        let a = 999;
+        console.log("catch", a);
+        debugger; // 12
+    }
+
+    // Finally
+    try {}
+    finally {
+        let a = 1000;
+        console.log("finally", a);
+        debugger; // 13
+    }
+
+    // Anonymous block.
+    {
+        let a = 1001;
+        console.log("block", a);
+        debugger; // 14
+    }
+
+    // With block.
+    with ({something:true,__proto__:null}) {
+        let a = 1002;
+        console.log("with", a);
+        debugger; // 15
+    }
+
+    // Nested blocks.
+    {
+        let a = 1003;
+        {
+            let a = 1004;
+            {
+                let a = 1005;
+                {
+                    let a = 1006;
+                    console.log("nested blocks", a);
+                    debugger; // 16
+                }
+            }
+        }
+    }
+
+    // Class (method)
+    (new (class MyClass {
+        method() {
+            // Block Variable scope containing the Class identifier `MyClass`.
+            console.log("class (method)");
+            debugger; // 17
+        }
+    })).method();
+
+    // Class (static method)
+    (class MyClassWithStaticMethod {
+        static staticMethod() {
+            // Block Variable scope containing the Class identifier `MyClass`.
+            console.log("class (static)");
+            debugger; // 18
+        }
+    }).staticMethod();
+
+    // Normal (not Block)
+    console.log("normal", a);
+    debugger; // 19
+}

Added: trunk/LayoutTests/inspector/model/resources/function-name-scopes.js (0 => 194251)


--- trunk/LayoutTests/inspector/model/resources/function-name-scopes.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/function-name-scopes.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,13 @@
+function testFunctionNameScope1() {
+    (function functionName() {
+        debugger;
+    })();
+}
+
+function testFunctionNameScope2() {
+    (class MyClass {
+        static staticMethod() {
+            debugger;
+        }
+    }).staticMethod();
+}

Added: trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt (0 => 194251)


--- trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt	2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,136 @@
+CONSOLE MESSAGE: line 36: Variables
+CONSOLE MESSAGE: line 4: normal
+CONSOLE MESSAGE: line 10: if
+CONSOLE MESSAGE: line 18: else
+CONSOLE MESSAGE: line 25: while
+CONSOLE MESSAGE: line 33: do
+CONSOLE MESSAGE: line 39: for
+CONSOLE MESSAGE: line 46: for-in
+CONSOLE MESSAGE: line 53: for-of
+CONSOLE MESSAGE: line 62: case
+CONSOLE MESSAGE: line 67: default
+CONSOLE MESSAGE: line 75: try
+CONSOLE MESSAGE: line 84: catch
+CONSOLE MESSAGE: line 92: finally
+CONSOLE MESSAGE: line 99: block
+CONSOLE MESSAGE: line 106: with
+CONSOLE MESSAGE: line 119: nested blocks
+CONSOLE MESSAGE: line 130: class (method)
+CONSOLE MESSAGE: line 139: class (static)
+CONSOLE MESSAGE: line 145: normal
+Tests for the WebInspector.ScopeChainNode model object.
+
+
+== Running test suite: WebInspector.ScopeChainNode
+-- Running test case: WebInspector.ScopeChainNode.AllTypes
+PASS: ScopeChain should have 13 scopes.
+SCOPE CHAIN:
+    Closure
+      - localVariable2: 12
+    Closure
+      - localVariable1: 11
+    FunctionName
+      - functionName: function functionName() {
+    Block
+      - catchBlockVariable: 10
+    Catch
+      - exceptionVariable: 9
+    Block
+      - withBlockVariable: 8
+    With
+      - withObjectProperty: 7
+    Closure
+      - innerClosureVariable2: 6
+    Closure
+      - innerClosureVariable1: 5
+    Closure
+      - closureVariable2: 4
+    Closure
+      - closureVariable1: 3
+      - innerScope: function innerScope() {
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+
+-- Running test case: WebInspector.ScopeChainNode.FunctionNameInFunctionExpression
+SCOPE CHAIN:
+    Closure
+    FunctionName
+      - functionName: function functionName() {
+    Closure
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+
+-- Running test case: WebInspector.ScopeChainNode.FunctionNameInClassMethod
+SCOPE CHAIN:
+    Closure
+    FunctionName
+      - staticMethod: function staticMethod() {
+    Block
+      - MyClass: class MyClass
+    Closure
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+
+-- Running test case: WebInspector.ScopeChainNode.BlockScopes
+PASS: Pause #1 - Top scope should be normal function Closure/Local scope.
+PASS: Pause #2 - Top scope should be Block scope.
+PASS: Pause #3 - Top scope should be Block scope.
+PASS: Pause #4 - Top scope should be Block scope.
+PASS: Pause #5 - Top scope should be Block scope.
+PASS: Pause #6 - Top scope should be Block scope.
+PASS: Pause #7 - Top scope should be Block scope.
+PASS: Pause #8 - Top scope should be Block scope.
+PASS: Pause #9 - Top scope should be Block scope.
+PASS: Pause #10 - Top scope should be Block scope.
+PASS: Pause #11 - Top scope should be Block scope.
+PASS: Pause #12 - Top scope should be Block scope.
+PASS: Pause #13 - Top scope should be Block scope.
+PASS: Pause #14 - Top scope should be Block scope.
+PASS: Pause #15 - Top scope should be Block scope.
+PASS: Pause #16 - Contains a Block scope.
+SCOPE CHAIN:
+    Block
+      - a: 1006
+    Block
+      - a: 1005
+    Block
+      - a: 1004
+    Block
+      - a: 1003
+    Closure
+      - a: 1
+    Closure
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+PASS: Pause #17 - Contains a Block scope.
+SCOPE CHAIN:
+    Closure
+    FunctionName
+      - method: function method() {
+    Block
+      - MyClass: class MyClass
+    Closure
+      - a: 1
+    Closure
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+PASS: Pause #18 - Contains a Block scope.
+SCOPE CHAIN:
+    Closure
+    FunctionName
+      - staticMethod: function staticMethod() {
+    Block
+      - MyClassWithStaticMethod: class MyClassWithStaticMethod
+    Closure
+      - a: 1
+    Closure
+    GlobalLexicalEnvironment
+      - lexicalGlobalVariable: 2
+    Global
+PASS: Pause #19 - Top scope should be normal function Closure/Local scope.
+

Added: trunk/LayoutTests/inspector/model/scope-chain-node.html (0 => 194251)


--- trunk/LayoutTests/inspector/model/scope-chain-node.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/model/scope-chain-node.html	2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,160 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script>
+function test()
+{
+    function firstLine(str) {
+        let newlineIndex = str.indexOf("\n");
+        if (newlineIndex !== -1)
+            return str.substr(0, newlineIndex);
+        return str;
+    }
+
+    function scopeTypeToString(type) {
+        for (let key in WebInspector.ScopeChainNode.Type) {
+            if (WebInspector.ScopeChainNode.Type[key] === type)
+                return key;
+        }
+        return "Unexpected Scope Type";
+    }
+
+    function harvestScopeChain(scopeChain) {        
+        let promises = [];
+        for (let scope of scopeChain) {
+            promises.push(new Promise((resolve, reject) => {
+                if (scope.type === WebInspector.ScopeChainNode.Type.Global)
+                    resolve({scope, propertyDescriptors: []});
+                else {
+                    scope.object.getDisplayablePropertyDescriptors((propertyDescriptors) => {
+                        resolve({scope, propertyDescriptors});
+                    });
+                }
+            }));
+        }
+        return Promise.all(promises);
+    }
+
+    function logScopeChain(scopeChain) {
+        return harvestScopeChain(scopeChain).then((results) => {
+            InspectorTest.log("SCOPE CHAIN:");
+            for (let {scope, propertyDescriptors} of results) {
+                InspectorTest.log(`    ${scopeTypeToString(scope.type)}`);
+                if (scope.type !== WebInspector.ScopeChainNode.Type.Global) {
+                    for (let descriptor of propertyDescriptors)
+                        InspectorTest.log(`      - ${descriptor.name}: ${firstLine(descriptor.value.description)}`);
+                }
+            }
+            return results;
+        });
+    }
+
+
+    let suite = InspectorTest.createAsyncSuite("WebInspector.ScopeChainNode");
+
+    InspectorTest.dumpActivityToSystemConsole = true;
+    InspectorBackend.dumpInspectorProtocolMessages = true;
+
+    suite.addTestCase({
+        name: "WebInspector.ScopeChainNode.AllTypes",
+        description: "Tests for each of the different scope chain node types.",
+        test: (resolve, reject) => {
+            InspectorTest.evaluateInPage("setTimeout(testAllScopes)");
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+                let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+                InspectorTest.expectThat(scopeChain.length === 13, "ScopeChain should have 13 scopes.");
+                logScopeChain(scopeChain).then((result) => {
+                    WebInspector.debuggerManager.resume();
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.ScopeChainNode.FunctionNameInFunctionExpression",
+        description: "Tests that there should be a FunctionName scope inside a function _expression_.",
+        test: (resolve, reject) => {
+            InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope1)");
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+                let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+                logScopeChain(scopeChain).then((result) => {
+                    WebInspector.debuggerManager.resume();
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.ScopeChainNode.FunctionNameInClassMethod",
+        description: "Tests that there should be a FunctionName scope inside a class method.",
+        test: (resolve, reject) => {
+            InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope2)");
+            WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+                let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+                logScopeChain(scopeChain).then((result) => {
+                    WebInspector.debuggerManager.resume();
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: "WebInspector.ScopeChainNode.BlockScopes",
+        description: "Tests for a Block scope inside all the different types of blocks.",
+        test: (resolve, reject) => {
+            InspectorTest.evaluateInPage("setTimeout(testBlockScopes)");
+            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
+
+            let pauseCount = 0;
+            let pauseEventsExpected = 19;
+            function callFramesDidChangeListener(event) {
+                pauseCount++;
+                let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+
+                // First, normal function scope.
+                if (pauseCount === 1) {
+                    InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Closure, "Pause #1 - Top scope should be normal function Closure/Local scope.");
+                    WebInspector.debuggerManager.resume();
+                    return;
+                }
+
+                // Last, normal function scope.
+                if (pauseCount === pauseEventsExpected) {
+                    InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Closure, `Pause #${pauseCount} - Top scope should be normal function Closure/Local scope.`);
+                    WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
+                    WebInspector.debuggerManager.resume();
+                    resolve();
+                    return;
+                }
+
+                // The first 15 cases the top scope should be a Block scope.
+                if (pauseCount <= 15) {
+                    InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Block, `Pause #${pauseCount} - Top scope should be Block scope.`);
+                    WebInspector.debuggerManager.resume();
+                    return;
+                }
+
+                // Print out the full scope of the last few where there are nested or buried block scopes.
+                InspectorTest.expectThat(scopeChain.some((scopeChain) => scopeChain.type === WebInspector.ScopeChainNode.Type.Block), `Pause #${pauseCount} - Contains a Block scope.`);
+                logScopeChain(scopeChain).then((result) => {
+                    WebInspector.debuggerManager.resume();
+                });
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests for the WebInspector.ScopeChainNode model object.</p>
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (194250 => 194251)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,5 +1,57 @@
 2015-12-17  Joseph Pecoraro  <[email protected]>
 
+        Provide a way to distinguish a nested lexical block from a function's lexical block
+        https://bugs.webkit.org/show_bug.cgi?id=152361
+
+        Reviewed by Saam Barati.
+
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
+        (JSC::BytecodeGenerator::emitPushFunctionNameScope):
+        (JSC::BytecodeGenerator::emitPushCatchScope):
+        Each of these are specialized scopes. They are not nested lexical scopes.
+        
+        (JSC::BytecodeGenerator::pushLexicalScope):
+        (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+        Include an extra parameter to mark the SymbolTable as a nested lexical or not.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BlockNode::emitBytecode):
+        (JSC::ForNode::emitBytecode):
+        (JSC::ForInNode::emitMultiLoopBytecode):
+        (JSC::ForOfNode::emitBytecode):
+        (JSC::SwitchNode::emitBytecode):
+        (JSC::ClassExprNode::emitBytecode):
+        Each of these are cases of non-function nested lexical scopes.
+        So mark the SymbolTable as nested.
+
+        * inspector/protocol/Debugger.json:
+        * inspector/InjectedScriptSource.js:
+        Include a new scope type.
+
+        * inspector/JSJavaScriptCallFrame.h:
+        * inspector/JSJavaScriptCallFrame.cpp:
+        (Inspector::JSJavaScriptCallFrame::scopeType):
+        Use the new "NestedLexical" scope type for nested, non-function,
+        lexical scopes. The Inspector can use this to better describe
+        this scope in the frontend.
+
+        * debugger/DebuggerScope.cpp:
+        (JSC::DebuggerScope::isNestedLexicalScope):
+        * debugger/DebuggerScope.h:
+        * runtime/JSScope.cpp:
+        (JSC::JSScope::isNestedLexicalScope):
+        * runtime/JSScope.h:
+        * runtime/SymbolTable.cpp:
+        (JSC::SymbolTable::SymbolTable):
+        (JSC::SymbolTable::cloneScopePart):
+        * runtime/SymbolTable.h:
+        Access the isNestedLexicalScope bit.
+
+2015-12-17  Joseph Pecoraro  <[email protected]>
+
         Unreviewed EFL Build Fix after r194247.
 
         * interpreter/CallFrame.cpp:

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -809,7 +809,7 @@
         }
         
         // This implements step 25 of section 9.2.12.
-        pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+        pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
 
         RefPtr<RegisterID> temp = newTemporary();
         for (unsigned i = 0; i < parameters.size(); i++) {
@@ -927,7 +927,7 @@
     }
 
     size_t size = m_symbolTableStack.size();
-    pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+    pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
 
     ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1);
 
@@ -1797,13 +1797,13 @@
     }
 }
 
-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult)
 {
     VariableEnvironment& environment = node->lexicalVariables();
-    pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+    pushLexicalScopeInternal(environment, canOptimizeTDZChecks, isNestedLexicalScope, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
 }
 
-void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, 
+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, bool isNestedLexicalScope,
     RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
 {
     if (!environment.size())
@@ -1825,6 +1825,9 @@
         break;
     }
 
+    if (isNestedLexicalScope)
+        symbolTable->markIsNestedLexicalScope();
+
     auto lookUpVarKind = [] (UniquedStringImpl*, const VariableEnvironmentEntry& entry) -> VarKind {
         return entry.isCaptured() ? VarKind::Scope : VarKind::Stack;
     };
@@ -3563,7 +3566,7 @@
         addResult.iterator->value.setIsCaptured();
     addResult.iterator->value.setIsConst(); // The function name scope name acts like a const variable.
     unsigned numVars = m_codeBlock->m_numVars;
-    pushLexicalScopeInternal(nameScopeEnvironment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
+    pushLexicalScopeInternal(nameScopeEnvironment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
     ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope.
     bool shouldTreatAsLexicalVariable = isStrictMode();
     Variable functionVar = variableForLocalEntry(property, m_symbolTableStack.last().m_symbolTable->get(property.impl()), m_symbolTableStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable);
@@ -3589,7 +3592,7 @@
 void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment)
 {
     RELEASE_ASSERT(environment.contains(property.impl()));
-    pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
+    pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
     Variable exceptionVar = variable(property);
     RELEASE_ASSERT(exceptionVar.isResolved());
     RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (194250 => 194251)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-12-18 01:09:13 UTC (rev 194251)
@@ -704,7 +704,7 @@
         enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
         enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
         enum class ScopeRegisterType { Var, Block };
-        void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
+        void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
         void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
         template<typename LookUpVarKindFunctor>
         bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
@@ -715,7 +715,7 @@
         void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
 
     public:
-        void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
+        void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, bool isNestedLexicalScope = false, RegisterID** constantSymbolTableResult = nullptr);
         void popLexicalScope(VariableEnvironmentNode*);
         void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
         int labelScopeDepth() const;

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -2049,7 +2049,7 @@
 {
     if (!m_statements)
         return;
-    generator.pushLexicalScope(this, true);
+    generator.pushLexicalScope(this, true, true);
     m_statements->emitBytecode(generator, dst);
     generator.popLexicalScope(this);
 }
@@ -2254,7 +2254,7 @@
     LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
 
     RegisterID* forLoopSymbolTable = nullptr;
-    generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+    generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
 
     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
 
@@ -2382,7 +2382,7 @@
     RefPtr<Label> end = generator.newLabel();
 
     RegisterID* forLoopSymbolTable = nullptr;
-    generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+    generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
 
     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
 
@@ -2532,7 +2532,7 @@
     }
 
     RegisterID* forLoopSymbolTable = nullptr;
-    generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+    generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
     auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
     {
@@ -2848,7 +2848,7 @@
 
     RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
 
-    generator.pushLexicalScope(this, false);
+    generator.pushLexicalScope(this, false, true);
     m_block->emitBytecodeForBlock(generator, r0.get(), dst);
     generator.popLexicalScope(this);
 
@@ -3181,7 +3181,7 @@
 RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (!m_name.isNull())
-        generator.pushLexicalScope(this, true);
+        generator.pushLexicalScope(this, true, true);
 
     RefPtr<RegisterID> superclass;
     if (m_classHeritage) {

Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -197,6 +197,11 @@
     return m_scope->isVarScope() || m_scope->isLexicalScope();
 }
 
+bool DebuggerScope::isNestedLexicalScope() const
+{
+    return m_scope->isNestedLexicalScope();
+}
+
 JSValue DebuggerScope::caughtValue(ExecState* exec) const
 {
     ASSERT(isCatchScope());

Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.h (194250 => 194251)


--- trunk/Source/_javascript_Core/debugger/DebuggerScope.h	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.h	2015-12-18 01:09:13 UTC (rev 194251)
@@ -91,6 +91,7 @@
     bool isGlobalScope() const;
     bool isClosureScope() const;
     bool isGlobalLexicalEnvironment() const;
+    bool isNestedLexicalScope() const;
 
     JSValue caughtValue(ExecState*) const;
 

Modified: trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js (194250 => 194251)


--- trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -1369,6 +1369,7 @@
     4: "catch", // CATCH_SCOPE
     5: "functionName", // FUNCTION_NAME_SCOPE
     6: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE
+    7: "nestedLexical", // NESTED_LEXICAL_SCOPE
 }
 
 InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)

Modified: trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -95,17 +95,9 @@
     DebuggerScope* scopeChain = impl().scopeChain();
     DebuggerScope::iterator end = scopeChain->end();
 
-    bool foundLocalScope = false;
     for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
         DebuggerScope* scope = iter.get();
 
-        if (!foundLocalScope && scope->isClosureScope()) {
-            // First closure scope is the local scope, each successive one is a true closure.
-            if (!index)
-                return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
-            foundLocalScope = true;
-        }
-
         if (!index) {
             if (scope->isCatchScope())
                 return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
@@ -113,6 +105,8 @@
                 return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE);
             if (scope->isWithScope())
                 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
+            if (scope->isNestedLexicalScope())
+                return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE);
             if (scope->isGlobalLexicalEnvironment())
                 return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE);
             if (scope->isGlobalScope()) {

Modified: trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h (194250 => 194251)


--- trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h	2015-12-18 01:09:13 UTC (rev 194251)
@@ -78,6 +78,7 @@
     static const unsigned short CATCH_SCOPE = 4;
     static const unsigned short FUNCTION_NAME_SCOPE = 5;
     static const unsigned short GLOBAL_LEXICAL_ENVIRONMENT_SCOPE = 6;
+    static const unsigned short NESTED_LEXICAL_SCOPE = 7;
 
 protected:
     void finishCreation(JSC::VM&);

Modified: trunk/Source/_javascript_Core/inspector/protocol/Debugger.json (194250 => 194251)


--- trunk/Source/_javascript_Core/inspector/protocol/Debugger.json	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/protocol/Debugger.json	2015-12-18 01:09:13 UTC (rev 194251)
@@ -81,7 +81,7 @@
             "id": "Scope",
             "type": "object",
             "properties": [
-                { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment"], "description": "Scope type." },
+                { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." },
                 { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }
             ],
             "description": "Scope description."

Modified: trunk/Source/_javascript_Core/runtime/JSScope.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/runtime/JSScope.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/JSScope.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -286,6 +286,13 @@
     return isScopeType<JSGlobalLexicalEnvironment, SymbolTable::ScopeType::GlobalLexicalScope>(this);
 }
 
+bool JSScope::isNestedLexicalScope()
+{
+    if (JSLexicalEnvironment* environment = jsDynamicCast<JSLexicalEnvironment*>(this))
+        return environment->symbolTable()->isNestedLexicalScope();
+    return false;
+}
+
 JSScope* JSScope::constantScopeForCodeBlock(ResolveType type, CodeBlock* codeBlock)
 {
     switch (type) {

Modified: trunk/Source/_javascript_Core/runtime/JSScope.h (194250 => 194251)


--- trunk/Source/_javascript_Core/runtime/JSScope.h	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/JSScope.h	2015-12-18 01:09:13 UTC (rev 194251)
@@ -62,6 +62,8 @@
     bool isCatchScope();
     bool isFunctionNameScopeObject();
 
+    bool isNestedLexicalScope();
+
     ScopeChainIterator begin();
     ScopeChainIterator end();
     JSScope* next();

Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.cpp (194250 => 194251)


--- trunk/Source/_javascript_Core/runtime/SymbolTable.cpp	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.cpp	2015-12-18 01:09:13 UTC (rev 194251)
@@ -84,6 +84,7 @@
 SymbolTable::SymbolTable(VM& vm)
     : JSCell(vm, vm.symbolTableStructure.get())
     , m_usesNonStrictEval(false)
+    , m_nestedLexicalScope(false)
     , m_scopeType(VarScope)
 {
 }
@@ -142,6 +143,7 @@
     SymbolTable* result = SymbolTable::create(vm);
     
     result->m_usesNonStrictEval = m_usesNonStrictEval;
+    result->m_nestedLexicalScope = m_nestedLexicalScope;
     result->m_scopeType = m_scopeType;
 
     for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {

Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.h (194250 => 194251)


--- trunk/Source/_javascript_Core/runtime/SymbolTable.h	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.h	2015-12-18 01:09:13 UTC (rev 194251)
@@ -646,9 +646,12 @@
     RefPtr<TypeSet> globalTypeSetForOffset(const ConcurrentJITLocker&, VarOffset, VM&);
     RefPtr<TypeSet> globalTypeSetForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM&);
 
-    bool usesNonStrictEval() { return m_usesNonStrictEval; }
+    bool usesNonStrictEval() const { return m_usesNonStrictEval; }
     void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
 
+    bool isNestedLexicalScope() const { return m_nestedLexicalScope; }
+    void markIsNestedLexicalScope() { ASSERT(scopeType() == LexicalScope); m_nestedLexicalScope = true; }
+
     enum ScopeType {
         VarScope,
         GlobalLexicalScope,
@@ -686,6 +689,7 @@
     std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
 
     bool m_usesNonStrictEval : 1;
+    bool m_nestedLexicalScope : 1; // Non-function LexicalScope.
     unsigned m_scopeType : 3; // ScopeType
     
     WriteBarrier<ScopedArgumentsTable> m_arguments;

Modified: trunk/Source/WebInspectorUI/ChangeLog (194250 => 194251)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,5 +1,24 @@
 2015-12-17  Joseph Pecoraro  <[email protected]>
 
+        Provide a way to distinguish a nested lexical block from a function's lexical block
+        https://bugs.webkit.org/show_bug.cgi?id=152361
+
+        Reviewed by Saam Barati.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
+        (WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection):
+        New "Block Variables" string.
+
+        * UserInterface/Models/ScopeChainNode.js:
+        New "Block" scope type, and update existing types.
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload):
+        Parse the protocol type to frontend types. Use the protocol generated enum.
+
+2015-12-17  Joseph Pecoraro  <[email protected]>
+
         Web Inspector: Improve names in Debugger Call Stack section when paused
         https://bugs.webkit.org/show_bug.cgi?id=152398
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (194250 => 194251)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -95,6 +95,7 @@
 localizedStrings["Background"] = "Background";
 localizedStrings["Basis"] = "Basis";
 localizedStrings["Begin Capturing"] = "Begin Capturing";
+localizedStrings["Block Variables"] = "Block Variables";
 localizedStrings["Blur"] = "Blur";
 localizedStrings["Border"] = "Border";
 localizedStrings["Bottom"] = "Bottom";

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (194250 => 194251)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -585,25 +585,28 @@
     {
         var type = null;
         switch (payload.type) {
-        case "local":
+        case DebuggerAgent.ScopeType.Local:
             type = WebInspector.ScopeChainNode.Type.Local;
             break;
-        case "global":
+        case DebuggerAgent.ScopeType.Global:
             type = WebInspector.ScopeChainNode.Type.Global;
             break;
-        case "with":
+        case DebuggerAgent.ScopeType.With:
             type = WebInspector.ScopeChainNode.Type.With;
             break;
-        case "closure":
+        case DebuggerAgent.ScopeType.Closure:
             type = WebInspector.ScopeChainNode.Type.Closure;
             break;
-        case "catch":
+        case DebuggerAgent.ScopeType.Catch:
             type = WebInspector.ScopeChainNode.Type.Catch;
             break;
-        case "functionName":
+        case DebuggerAgent.ScopeType.FunctionName:
             type = WebInspector.ScopeChainNode.Type.FunctionName;
             break;
-        case "globalLexicalEnvironment":
+        case DebuggerAgent.ScopeType.NestedLexical:
+            type = WebInspector.ScopeChainNode.Type.Block;
+            break;
+        case DebuggerAgent.ScopeType.GlobalLexicalEnvironment:
             type = WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment;
             break;
         default:

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js (194250 => 194251)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -55,9 +55,10 @@
 WebInspector.ScopeChainNode.Type = {
     Local: "scope-chain-type-local",
     Global: "scope-chain-type-global",
+    GlobalLexicalEnvironment: "scope-chain-type-global-lexical-environment",
     With: "scope-chain-type-with",
     Closure: "scope-chain-type-closure",
     Catch: "scope-chain-type-catch",
-    FunctionName: "scope-chain-type-functionName",
-    GlobalLexicalEnvironment: "scope-chain-type-globalLexicalEnvironment",
+    FunctionName: "scope-chain-type-function-name",
+    Block: "scope-chain-type-block",
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js (194250 => 194251)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js	2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js	2015-12-18 01:09:13 UTC (rev 194251)
@@ -184,6 +184,11 @@
                         extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: callFrame.thisObject});
                     break;
 
+                case WebInspector.ScopeChainNode.Type.Block:
+                    title = WebInspector.UIString("Block Variables");
+                    collapsedByDefault = false;
+                    break;
+
                 case WebInspector.ScopeChainNode.Type.Closure:
                     title = WebInspector.UIString("Closure Variables");
                     collapsedByDefault = false;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to