<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[194251] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/194251">194251</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2015-12-17 17:09:13 -0800 (Thu, 17 Dec 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>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/JavaScriptCore:
* 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.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggerbreakpointscopeexpectedtxt">trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerScopecpp">trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerScopeh">trunk/Source/JavaScriptCore/debugger/DebuggerScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs">trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFrameh">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson">trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSScopecpp">trunk/Source/JavaScriptCore/runtime/JSScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSScopeh">trunk/Source/JavaScriptCore/runtime/JSScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSymbolTablecpp">trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSymbolTableh">trunk/Source/JavaScriptCore/runtime/SymbolTable.h</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsScopeChainNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScopeChainDetailsSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/inspector/model/resources/</li>
<li><a href="#trunkLayoutTestsinspectormodelresourcesallscopesjs">trunk/LayoutTests/inspector/model/resources/all-scopes.js</a></li>
<li><a href="#trunkLayoutTestsinspectormodelresourcesblockscopesjs">trunk/LayoutTests/inspector/model/resources/block-scopes.js</a></li>
<li><a href="#trunkLayoutTestsinspectormodelresourcesfunctionnamescopesjs">trunk/LayoutTests/inspector/model/resources/function-name-scopes.js</a></li>
<li><a href="#trunkLayoutTestsinspectormodelscopechainnodeexpectedtxt">trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectormodelscopechainnodehtml">trunk/LayoutTests/inspector/model/scope-chain-node.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/LayoutTests/ChangeLog        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2015-12-17 Joseph Pecoraro <pecoraro@apple.com>
+
+ 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.
+
</ins><span class="cx"> 2015-12-17 Keith Miller <keith_miller@apple.com>
</span><span class="cx">
</span><span class="cx"> [ES6] Add support for Symbol.hasInstance
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerbreakpointscopeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -3,12 +3,12 @@
</span><span class="cx">
</span><span class="cx"> Starting Test
</span><span class="cx"> Hit breakpoint at line: 4, column: 8
</span><del>-scope-chain-type-local properties:
</del><ins>+scope-chain-type-closure properties:
</ins><span class="cx"> resolve
</span><span class="cx"> reject
</span><span class="cx"> scope-chain-type-closure properties:
</span><span class="cx"> p
</span><del>-scope-chain-type-globalLexicalEnvironment properties:
</del><ins>+scope-chain-type-global-lexical-environment properties:
</ins><span class="cx"> lexicalVariable
</span><span class="cx"> scope-chain-type-global (properties not listed)
</span><span class="cx"> Tests done
</span></span></pre></div>
<a id="trunkLayoutTestsinspectormodelresourcesallscopesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/resources/all-scopes.js (0 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+// 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();
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectormodelresourcesblockscopesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/resources/block-scopes.js (0 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,147 @@
</span><ins>+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
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectormodelresourcesfunctionnamescopesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/resources/function-name-scopes.js (0 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+function testFunctionNameScope1() {
+ (function functionName() {
+ debugger;
+ })();
+}
+
+function testFunctionNameScope2() {
+ (class MyClass {
+ static staticMethod() {
+ debugger;
+ }
+ }).staticMethod();
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectormodelscopechainnodeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt (0 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,136 @@
</span><ins>+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.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectormodelscopechainnodehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/scope-chain-node.html (0 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,160 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="resources/all-scopes.js"></script>
+<script src="resources/function-name-scopes.js"></script>
+<script src="resources/block-scopes.js"></script>
+<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>
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -1,5 +1,57 @@
</span><span class="cx"> 2015-12-17 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><ins>+ 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 <pecoraro@apple.com>
+
</ins><span class="cx"> Unreviewed EFL Build Fix after r194247.
</span><span class="cx">
</span><span class="cx"> * interpreter/CallFrame.cpp:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -809,7 +809,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // This implements step 25 of section 9.2.12.
</span><del>- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</del><ins>+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</ins><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> temp = newTemporary();
</span><span class="cx"> for (unsigned i = 0; i < parameters.size(); i++) {
</span><span class="lines">@@ -927,7 +927,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> size_t size = m_symbolTableStack.size();
</span><del>- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</del><ins>+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</ins><span class="cx">
</span><span class="cx"> ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1);
</span><span class="cx">
</span><span class="lines">@@ -1797,13 +1797,13 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
</del><ins>+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult)
</ins><span class="cx"> {
</span><span class="cx"> VariableEnvironment& environment = node->lexicalVariables();
</span><del>- pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</del><ins>+ pushLexicalScopeInternal(environment, canOptimizeTDZChecks, isNestedLexicalScope, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks,
</del><ins>+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, bool isNestedLexicalScope,
</ins><span class="cx"> RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
</span><span class="cx"> {
</span><span class="cx"> if (!environment.size())
</span><span class="lines">@@ -1825,6 +1825,9 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (isNestedLexicalScope)
+ symbolTable->markIsNestedLexicalScope();
+
</ins><span class="cx"> auto lookUpVarKind = [] (UniquedStringImpl*, const VariableEnvironmentEntry& entry) -> VarKind {
</span><span class="cx"> return entry.isCaptured() ? VarKind::Scope : VarKind::Stack;
</span><span class="cx"> };
</span><span class="lines">@@ -3563,7 +3566,7 @@
</span><span class="cx"> addResult.iterator->value.setIsCaptured();
</span><span class="cx"> addResult.iterator->value.setIsConst(); // The function name scope name acts like a const variable.
</span><span class="cx"> unsigned numVars = m_codeBlock->m_numVars;
</span><del>- pushLexicalScopeInternal(nameScopeEnvironment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
</del><ins>+ pushLexicalScopeInternal(nameScopeEnvironment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
</ins><span class="cx"> ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope.
</span><span class="cx"> bool shouldTreatAsLexicalVariable = isStrictMode();
</span><span class="cx"> Variable functionVar = variableForLocalEntry(property, m_symbolTableStack.last().m_symbolTable->get(property.impl()), m_symbolTableStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable);
</span><span class="lines">@@ -3589,7 +3592,7 @@
</span><span class="cx"> void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment)
</span><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT(environment.contains(property.impl()));
</span><del>- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
</del><ins>+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
</ins><span class="cx"> Variable exceptionVar = variable(property);
</span><span class="cx"> RELEASE_ASSERT(exceptionVar.isResolved());
</span><span class="cx"> RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -704,7 +704,7 @@
</span><span class="cx"> enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
</span><span class="cx"> enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
</span><span class="cx"> enum class ScopeRegisterType { Var, Block };
</span><del>- void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
</del><ins>+ void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
</ins><span class="cx"> void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
</span><span class="cx"> template<typename LookUpVarKindFunctor>
</span><span class="cx"> bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
</span><span class="lines">@@ -715,7 +715,7 @@
</span><span class="cx"> void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
</span><span class="cx">
</span><span class="cx"> public:
</span><del>- void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
</del><ins>+ void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, bool isNestedLexicalScope = false, RegisterID** constantSymbolTableResult = nullptr);
</ins><span class="cx"> void popLexicalScope(VariableEnvironmentNode*);
</span><span class="cx"> void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
</span><span class="cx"> int labelScopeDepth() const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -2049,7 +2049,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (!m_statements)
</span><span class="cx"> return;
</span><del>- generator.pushLexicalScope(this, true);
</del><ins>+ generator.pushLexicalScope(this, true, true);
</ins><span class="cx"> m_statements->emitBytecode(generator, dst);
</span><span class="cx"> generator.popLexicalScope(this);
</span><span class="cx"> }
</span><span class="lines">@@ -2254,7 +2254,7 @@
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx">
</span><span class="cx"> RegisterID* forLoopSymbolTable = nullptr;
</span><del>- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
</del><ins>+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
</ins><span class="cx">
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2382,7 +2382,7 @@
</span><span class="cx"> RefPtr<Label> end = generator.newLabel();
</span><span class="cx">
</span><span class="cx"> RegisterID* forLoopSymbolTable = nullptr;
</span><del>- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
</del><ins>+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
</ins><span class="cx">
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2532,7 +2532,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* forLoopSymbolTable = nullptr;
</span><del>- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
</del><ins>+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
</ins><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx"> auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
</span><span class="cx"> {
</span><span class="lines">@@ -2848,7 +2848,7 @@
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
</span><span class="cx">
</span><del>- generator.pushLexicalScope(this, false);
</del><ins>+ generator.pushLexicalScope(this, false, true);
</ins><span class="cx"> m_block->emitBytecodeForBlock(generator, r0.get(), dst);
</span><span class="cx"> generator.popLexicalScope(this);
</span><span class="cx">
</span><span class="lines">@@ -3181,7 +3181,7 @@
</span><span class="cx"> RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx"> if (!m_name.isNull())
</span><del>- generator.pushLexicalScope(this, true);
</del><ins>+ generator.pushLexicalScope(this, true, true);
</ins><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> superclass;
</span><span class="cx"> if (m_classHeritage) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -197,6 +197,11 @@
</span><span class="cx"> return m_scope->isVarScope() || m_scope->isLexicalScope();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool DebuggerScope::isNestedLexicalScope() const
+{
+ return m_scope->isNestedLexicalScope();
+}
+
</ins><span class="cx"> JSValue DebuggerScope::caughtValue(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx"> ASSERT(isCatchScope());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerScope.h (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx"> bool isGlobalScope() const;
</span><span class="cx"> bool isClosureScope() const;
</span><span class="cx"> bool isGlobalLexicalEnvironment() const;
</span><ins>+ bool isNestedLexicalScope() const;
</ins><span class="cx">
</span><span class="cx"> JSValue caughtValue(ExecState*) const;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -1369,6 +1369,7 @@
</span><span class="cx"> 4: "catch", // CATCH_SCOPE
</span><span class="cx"> 5: "functionName", // FUNCTION_NAME_SCOPE
</span><span class="cx"> 6: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE
</span><ins>+ 7: "nestedLexical", // NESTED_LEXICAL_SCOPE
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -95,17 +95,9 @@
</span><span class="cx"> DebuggerScope* scopeChain = impl().scopeChain();
</span><span class="cx"> DebuggerScope::iterator end = scopeChain->end();
</span><span class="cx">
</span><del>- bool foundLocalScope = false;
</del><span class="cx"> for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
</span><span class="cx"> DebuggerScope* scope = iter.get();
</span><span class="cx">
</span><del>- 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;
- }
-
</del><span class="cx"> if (!index) {
</span><span class="cx"> if (scope->isCatchScope())
</span><span class="cx"> return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
</span><span class="lines">@@ -113,6 +105,8 @@
</span><span class="cx"> return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE);
</span><span class="cx"> if (scope->isWithScope())
</span><span class="cx"> return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
</span><ins>+ if (scope->isNestedLexicalScope())
+ return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE);
</ins><span class="cx"> if (scope->isGlobalLexicalEnvironment())
</span><span class="cx"> return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE);
</span><span class="cx"> if (scope->isGlobalScope()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -78,6 +78,7 @@
</span><span class="cx"> static const unsigned short CATCH_SCOPE = 4;
</span><span class="cx"> static const unsigned short FUNCTION_NAME_SCOPE = 5;
</span><span class="cx"> static const unsigned short GLOBAL_LEXICAL_ENVIRONMENT_SCOPE = 6;
</span><ins>+ static const unsigned short NESTED_LEXICAL_SCOPE = 7;
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> void finishCreation(JSC::VM&);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx"> "id": "Scope",
</span><span class="cx"> "type": "object",
</span><span class="cx"> "properties": [
</span><del>- { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment"], "description": "Scope type." },
</del><ins>+ { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." },
</ins><span class="cx"> { "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." }
</span><span class="cx"> ],
</span><span class="cx"> "description": "Scope description."
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -286,6 +286,13 @@
</span><span class="cx"> return isScopeType<JSGlobalLexicalEnvironment, SymbolTable::ScopeType::GlobalLexicalScope>(this);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool JSScope::isNestedLexicalScope()
+{
+ if (JSLexicalEnvironment* environment = jsDynamicCast<JSLexicalEnvironment*>(this))
+ return environment->symbolTable()->isNestedLexicalScope();
+ return false;
+}
+
</ins><span class="cx"> JSScope* JSScope::constantScopeForCodeBlock(ResolveType type, CodeBlock* codeBlock)
</span><span class="cx"> {
</span><span class="cx"> switch (type) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.h (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.h        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.h        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -62,6 +62,8 @@
</span><span class="cx"> bool isCatchScope();
</span><span class="cx"> bool isFunctionNameScopeObject();
</span><span class="cx">
</span><ins>+ bool isNestedLexicalScope();
+
</ins><span class="cx"> ScopeChainIterator begin();
</span><span class="cx"> ScopeChainIterator end();
</span><span class="cx"> JSScope* next();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -84,6 +84,7 @@
</span><span class="cx"> SymbolTable::SymbolTable(VM& vm)
</span><span class="cx"> : JSCell(vm, vm.symbolTableStructure.get())
</span><span class="cx"> , m_usesNonStrictEval(false)
</span><ins>+ , m_nestedLexicalScope(false)
</ins><span class="cx"> , m_scopeType(VarScope)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -142,6 +143,7 @@
</span><span class="cx"> SymbolTable* result = SymbolTable::create(vm);
</span><span class="cx">
</span><span class="cx"> result->m_usesNonStrictEval = m_usesNonStrictEval;
</span><ins>+ result->m_nestedLexicalScope = m_nestedLexicalScope;
</ins><span class="cx"> result->m_scopeType = m_scopeType;
</span><span class="cx">
</span><span class="cx"> for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SymbolTable.h (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2015-12-18 01:09:13 UTC (rev 194251)
</span><span class="lines">@@ -646,9 +646,12 @@
</span><span class="cx"> RefPtr<TypeSet> globalTypeSetForOffset(const ConcurrentJITLocker&, VarOffset, VM&);
</span><span class="cx"> RefPtr<TypeSet> globalTypeSetForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM&);
</span><span class="cx">
</span><del>- bool usesNonStrictEval() { return m_usesNonStrictEval; }
</del><ins>+ bool usesNonStrictEval() const { return m_usesNonStrictEval; }
</ins><span class="cx"> void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
</span><span class="cx">
</span><ins>+ bool isNestedLexicalScope() const { return m_nestedLexicalScope; }
+ void markIsNestedLexicalScope() { ASSERT(scopeType() == LexicalScope); m_nestedLexicalScope = true; }
+
</ins><span class="cx"> enum ScopeType {
</span><span class="cx"> VarScope,
</span><span class="cx"> GlobalLexicalScope,
</span><span class="lines">@@ -686,6 +689,7 @@
</span><span class="cx"> std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
</span><span class="cx">
</span><span class="cx"> bool m_usesNonStrictEval : 1;
</span><ins>+ bool m_nestedLexicalScope : 1; // Non-function LexicalScope.
</ins><span class="cx"> unsigned m_scopeType : 3; // ScopeType
</span><span class="cx">
</span><span class="cx"> WriteBarrier<ScopedArgumentsTable> m_arguments;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,24 @@
</span><span class="cx"> 2015-12-17 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><ins>+ 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 <pecoraro@apple.com>
+
</ins><span class="cx"> Web Inspector: Improve names in Debugger Call Stack section when paused
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=152398
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -95,6 +95,7 @@
</span><span class="cx"> localizedStrings["Background"] = "Background";
</span><span class="cx"> localizedStrings["Basis"] = "Basis";
</span><span class="cx"> localizedStrings["Begin Capturing"] = "Begin Capturing";
</span><ins>+localizedStrings["Block Variables"] = "Block Variables";
</ins><span class="cx"> localizedStrings["Blur"] = "Blur";
</span><span class="cx"> localizedStrings["Border"] = "Border";
</span><span class="cx"> localizedStrings["Bottom"] = "Bottom";
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -585,25 +585,28 @@
</span><span class="cx"> {
</span><span class="cx"> var type = null;
</span><span class="cx"> switch (payload.type) {
</span><del>- case "local":
</del><ins>+ case DebuggerAgent.ScopeType.Local:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.Local;
</span><span class="cx"> break;
</span><del>- case "global":
</del><ins>+ case DebuggerAgent.ScopeType.Global:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.Global;
</span><span class="cx"> break;
</span><del>- case "with":
</del><ins>+ case DebuggerAgent.ScopeType.With:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.With;
</span><span class="cx"> break;
</span><del>- case "closure":
</del><ins>+ case DebuggerAgent.ScopeType.Closure:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.Closure;
</span><span class="cx"> break;
</span><del>- case "catch":
</del><ins>+ case DebuggerAgent.ScopeType.Catch:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.Catch;
</span><span class="cx"> break;
</span><del>- case "functionName":
</del><ins>+ case DebuggerAgent.ScopeType.FunctionName:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.FunctionName;
</span><span class="cx"> break;
</span><del>- case "globalLexicalEnvironment":
</del><ins>+ case DebuggerAgent.ScopeType.NestedLexical:
+ type = WebInspector.ScopeChainNode.Type.Block;
+ break;
+ case DebuggerAgent.ScopeType.GlobalLexicalEnvironment:
</ins><span class="cx"> type = WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment;
</span><span class="cx"> break;
</span><span class="cx"> default:
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsScopeChainNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -55,9 +55,10 @@
</span><span class="cx"> WebInspector.ScopeChainNode.Type = {
</span><span class="cx"> Local: "scope-chain-type-local",
</span><span class="cx"> Global: "scope-chain-type-global",
</span><ins>+ GlobalLexicalEnvironment: "scope-chain-type-global-lexical-environment",
</ins><span class="cx"> With: "scope-chain-type-with",
</span><span class="cx"> Closure: "scope-chain-type-closure",
</span><span class="cx"> Catch: "scope-chain-type-catch",
</span><del>- FunctionName: "scope-chain-type-functionName",
- GlobalLexicalEnvironment: "scope-chain-type-globalLexicalEnvironment",
</del><ins>+ FunctionName: "scope-chain-type-function-name",
+ Block: "scope-chain-type-block",
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScopeChainDetailsSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js (194250 => 194251)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -184,6 +184,11 @@
</span><span class="cx"> extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: callFrame.thisObject});
</span><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case WebInspector.ScopeChainNode.Type.Block:
+ title = WebInspector.UIString("Block Variables");
+ collapsedByDefault = false;
+ break;
+
</ins><span class="cx"> case WebInspector.ScopeChainNode.Type.Closure:
</span><span class="cx"> title = WebInspector.UIString("Closure Variables");
</span><span class="cx"> collapsedByDefault = false;
</span></span></pre>
</div>
</div>
</body>
</html>