<!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>[202659] 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/202659">202659</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2016-06-29 16:59:35 -0700 (Wed, 29 Jun 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Wrong function name next to scope
https://bugs.webkit.org/show_bug.cgi?id=158210
<rdar://problem/26543093>
Reviewed by Brian Burg.
Source/JavaScriptCore:
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
Add DebuggerLocation. A helper for describing a unique location.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::setConstantRegisters):
When compiled with debug info, add a SymbolTable rare data pointer
back to the CodeBlock. This will be used later to get JSScope debug
info if Web Inspector pauses.
* runtime/SymbolTable.h:
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::cloneScopePart):
(JSC::SymbolTable::prepareForTypeProfiling):
(JSC::SymbolTable::uniqueIDForVariable):
(JSC::SymbolTable::uniqueIDForOffset):
(JSC::SymbolTable::globalTypeSetForOffset):
(JSC::SymbolTable::globalTypeSetForVariable):
Rename rareData and include a CodeBlock pointer.
(JSC::SymbolTable::rareDataCodeBlock):
(JSC::SymbolTable::setRareDataCodeBlock):
Setter and getter for the rare data. It should only be set once.
(JSC::SymbolTable::visitChildren):
Visit the rare data code block if we have one.
* debugger/DebuggerLocation.cpp: Added.
(JSC::DebuggerLocation::DebuggerLocation):
* debugger/DebuggerLocation.h: Added.
(JSC::DebuggerLocation::DebuggerLocation):
Construction from a ScriptExecutable.
* runtime/JSScope.cpp:
(JSC::JSScope::symbolTable):
* runtime/JSScope.h:
* debugger/DebuggerScope.h:
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::name):
(JSC::DebuggerScope::location):
Name and location for a scope. This uses:
JSScope -> SymbolTable -> CodeBlock -> Executable
* inspector/protocol/Debugger.json:
* inspector/InjectedScriptSource.js:
(InjectedScript.CallFrameProxy.prototype._wrapScopeChain):
(InjectedScript.CallFrameProxy._createScopeJson):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::valueForScopeType):
(Inspector::valueForScopeLocation):
(Inspector::JSJavaScriptCallFrame::scopeDescriptions):
(Inspector::JSJavaScriptCallFrame::scopeType): Deleted.
* inspector/JSJavaScriptCallFrame.h:
* inspector/JSJavaScriptCallFramePrototype.cpp:
(Inspector::JSJavaScriptCallFramePrototype::finishCreation):
(Inspector::jsJavaScriptCallFramePrototypeFunctionScopeDescriptions):
(Inspector::jsJavaScriptCallFramePrototypeFunctionScopeType): Deleted.
Simplify this code to build the objects we will send across the protocol
to descript a Scope.
Source/WebInspectorUI:
* UserInterface/Controllers/DebuggerManager.js:
(WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload):
Include new payload data in the construction call.
All the new data is optional, so we gracefully handle
legacy backends.
* UserInterface/Models/ScopeChainNode.js:
(WebInspector.ScopeChainNode):
(WebInspector.ScopeChainNode.prototype.get type):
(WebInspector.ScopeChainNode.prototype.get objects):
(WebInspector.ScopeChainNode.prototype.get name):
(WebInspector.ScopeChainNode.prototype.get location):
(WebInspector.ScopeChainNode.prototype.get hash):
Hash is a rough (name:sourceId:line:column) string for quick comparisons.
(WebInspector.ScopeChainNode.prototype.makeLocalScope):
Make this an action you take on a scope, to avoid having to
do it at construction time, or making it a generic setting.
* UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
(WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection):
This was wrong before. Move the work to CallFrame
and change it to be correct.
* UserInterface/CallFrame.js:
(WebInspector.CallFrame.prototype.mergedScopeChain):
This transforms the scope chain for a call frame from:
scope1 scope2 scope3 scope4 scope5 scope6 scope7
foo foo foo bar bar - -
Block Closure Closure Closure Closure GLE GBL
To:
scope1 scope2&3 scope4&5 scope6 scope7
foo foo* bar* - -
Block Local Closure GLE GBL
Doing a few things:
- Merge the first two Closure scopes sharing a location.
These are the "var" and "let" Closure scopes in a function,
and it is better to present these together in the UI.
- Mark the first Closure scope within a function (*). When
this is displayed in the UI, we can provide the name of
the function: "Closure Scope (name)", and we even have
location information that we can use to display a goto
arrow if needed.
- Make the first Closure scope the Local scope if it
matches the Call Frame's function name. This lets us
display the section as "Local Variables".
LayoutTests:
* inspector/debugger/paused-scopes-expected.txt: Added.
* inspector/debugger/paused-scopes.html: Added.
* inspector/debugger/resources/paused-scopes.js: Added.
Test dumps the call frames and scope chains for each call frame
when pausing at different locations in a program. Outputting
the hashes we can see even identically named functions have
different hashes because their location is different.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.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="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramePrototypecpp">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp</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="#trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsCallFramejs">trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.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><a href="#trunkLayoutTestsinspectordebuggerpausedscopesexpectedtxt">trunk/LayoutTests/inspector/debugger/paused-scopes-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggerpausedscopeshtml">trunk/LayoutTests/inspector/debugger/paused-scopes.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggerresourcespausedscopesjs">trunk/LayoutTests/inspector/debugger/resources/paused-scopes.js</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerLocationcpp">trunk/Source/JavaScriptCore/debugger/DebuggerLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerLocationh">trunk/Source/JavaScriptCore/debugger/DebuggerLocation.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/LayoutTests/ChangeLog        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-06-29 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Wrong function name next to scope
+ https://bugs.webkit.org/show_bug.cgi?id=158210
+ <rdar://problem/26543093>
+
+ Reviewed by Brian Burg.
+
+ * inspector/debugger/paused-scopes-expected.txt: Added.
+ * inspector/debugger/paused-scopes.html: Added.
+ * inspector/debugger/resources/paused-scopes.js: Added.
+ Test dumps the call frames and scope chains for each call frame
+ when pausing at different locations in a program. Outputting
+ the hashes we can see even identically named functions have
+ different hashes because their location is different.
+
</ins><span class="cx"> 2016-06-29 Ryan Haddad <ryanhaddad@apple.com>
</span><span class="cx">
</span><span class="cx"> Marking perf/rel-list-remove.html as flaky on ios-simulator
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerpausedscopesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/paused-scopes-expected.txt (0 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/paused-scopes-expected.txt         (rev 0)
+++ trunk/LayoutTests/inspector/debugger/paused-scopes-expected.txt        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -0,0 +1,205 @@
</span><ins>+Check scope chains for different call frames at different pauses.
+
+
+== Running test suite: PausedCallFrameScope
+-- Running test case: TriggerFirstPause
+CALLFRAME: firstPause
+
+---- Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Block) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:21:29)
+ - barVarVariable1
+ SCOPE: Name (firstPause) - Type (FunctionName) - Hash (firstPause:<sourceID>:21:29)
+ - firstPause
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Block) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Local) - Hash (firstPause:<sourceID>:21:29)
+ - barVarVariable1
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (FunctionName) - Hash (firstPause:<sourceID>:21:29)
+ - firstPause
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+CALLFRAME: firstPause
+
+---- Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Local) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+CALLFRAME: entry
+
+---- Scope Chain ----
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (entry) - Type (Local) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+
+-- Running test case: TriggerSecondPause
+CALLFRAME: secondPause
+
+---- Scope Chain ----
+ SCOPE: Name (secondPause) - Type (Block) - Hash (secondPause:<sourceID>:6:21)
+ - blockLexicalVariable
+ SCOPE: Name (secondPause) - Type (Closure) - Hash (secondPause:<sourceID>:6:21)
+ - shoeLexicalVariable1
+ SCOPE: Name (secondPause) - Type (Closure) - Hash (secondPause:<sourceID>:6:21)
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (secondPause) - Type (Block) - Hash (secondPause:<sourceID>:6:21)
+ - blockLexicalVariable
+ SCOPE: Name (secondPause) - Type (Local) - Hash (secondPause:<sourceID>:6:21)
+ - shoeLexicalVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+CALLFRAME: firstPause
+
+---- Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Block) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:21:29)
+ - barVarVariable1
+ SCOPE: Name (firstPause) - Type (FunctionName) - Hash (firstPause:<sourceID>:21:29)
+ - firstPause
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Block) - Hash (firstPause:<sourceID>:21:29)
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (Local) - Hash (firstPause:<sourceID>:21:29)
+ - barVarVariable1
+ - barLexicalVariable2
+ SCOPE: Name (firstPause) - Type (FunctionName) - Hash (firstPause:<sourceID>:21:29)
+ - firstPause
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+CALLFRAME: firstPause
+
+---- Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (firstPause) - Type (Closure) - Hash (firstPause:<sourceID>:19:24)
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (firstPause) - Type (Local) - Hash (firstPause:<sourceID>:19:24)
+ - fakeFirstPauseLexicalVariable
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+CALLFRAME: entry
+
+---- Scope Chain ----
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - fooLexicalVariable2
+ SCOPE: Name (entry) - Type (Closure) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+---- Merged Scope Chain ----
+ SCOPE: Name (entry) - Type (Local) - Hash (entry:<sourceID>:14:15)
+ - firstPause
+ - fooVarVariable1
+ - fooLexicalVariable2
+ SCOPE: Name () - Type (GlobalLexicalEnvironment) - Hash ()
+ - globalLet2
+ SCOPE: Name () - Type (Global) - Hash ()
+
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerpausedscopeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/paused-scopes.html (0 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/paused-scopes.html         (rev 0)
+++ trunk/LayoutTests/inspector/debugger/paused-scopes.html        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -0,0 +1,118 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="resources/paused-scopes.js"></script>
+<script>
+
+function test()
+{
+ function scopeTypeName(type) {
+ switch (type) {
+ case WebInspector.ScopeChainNode.Type.Local: return "Local";
+ case WebInspector.ScopeChainNode.Type.Global: return "Global";
+ case WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment: return "GlobalLexicalEnvironment";
+ case WebInspector.ScopeChainNode.Type.With: return "With";
+ case WebInspector.ScopeChainNode.Type.Closure: return "Closure";
+ case WebInspector.ScopeChainNode.Type.Catch: return "Catch";
+ case WebInspector.ScopeChainNode.Type.FunctionName: return "FunctionName";
+ case WebInspector.ScopeChainNode.Type.Block: return "Block";
+ default: return "Unknown!";
+ };
+ }
+
+ function sanitizeHash(hash) {
+ return hash.replace(/:(.*?):/, ":<sourceID>:");
+ }
+
+ function collectScopeChainProperties(scopeChain) {
+ let scopeChainData = [];
+
+ let promises = [];
+ for (let scope of scopeChain) {
+ let data = {scope, properties: []};
+ scopeChainData.push(data);
+ if (scope.type === WebInspector.ScopeChainNode.Type.Global)
+ continue;
+
+ for (let scopeObject of scope.objects) {
+ promises.push(new Promise((resolve, reject) => {
+ scopeObject.getAllPropertyDescriptors((propertyDescriptors) => {
+ data.properties = data.properties.concat(propertyDescriptors);
+ resolve();
+ });
+ }));
+ }
+ }
+
+ return Promise.all(promises)
+ .then(() => scopeChainData);
+ }
+
+ function dumpScopeChainData(scopeChainData) {
+ for (let {scope, properties} of scopeChainData) {
+ InspectorTest.log(` SCOPE: Name (${scope.name}) - Type (${scopeTypeName(scope.type)}) - Hash (${sanitizeHash(scope.hash)})`);
+ for (let propertyDescriptor of properties)
+ InspectorTest.log(` - ${propertyDescriptor.name}`);
+ }
+ }
+
+ function dumpCallFrame(callFrame) {
+ return Promise.all([
+ collectScopeChainProperties(callFrame.scopeChain),
+ collectScopeChainProperties(callFrame.mergedScopeChain()),
+ ]).then((results) => {
+ let [scopeChainData, mergedScopeChainData] = results;
+ InspectorTest.log(`CALLFRAME: ${callFrame.functionName}`);
+ InspectorTest.log("\n---- Scope Chain ----");
+ dumpScopeChainData(scopeChainData);
+ InspectorTest.log("\n---- Merged Scope Chain ----");
+ dumpScopeChainData(mergedScopeChainData);
+ InspectorTest.log("");
+ });
+ }
+
+ function dumpCallFrames() {
+ let callFrames = WebInspector.debuggerManager.callFrames;
+ let chain = Promise.resolve();
+ for (let callFrame of callFrames)
+ chain = chain.then(() => dumpCallFrame(callFrame));
+ return chain;
+ }
+
+
+ let suite = InspectorTest.createAsyncSuite("PausedCallFrameScope");
+
+ suite.addTestCase({
+ name: "TriggerFirstPause",
+ description: "Verify CallFrames and Scopes with the first pause.",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("setTimeout(entry)");
+ WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+ dumpCallFrames().then(resolve, reject);
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "TriggerSecondPause",
+ description: "Verify CallFrames and Scopes with the first pause.",
+ test: (resolve, reject) => {
+ WebInspector.debuggerManager.resume();
+ WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+ dumpCallFrames().then(() => {
+ WebInspector.debuggerManager.resume();
+ resolve();
+ }, reject);
+ });
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Check scope chains for different call frames at different pauses.</p>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerresourcespausedscopesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/resources/paused-scopes.js (0 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/resources/paused-scopes.js         (rev 0)
+++ trunk/LayoutTests/inspector/debugger/resources/paused-scopes.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+"use strict";
+
+var globalVar1; // Global (globalVar1)
+let globalLet2; // GlobalLexicalEnvironment (globalLet2)
+
+function secondPause() { // Global (secondPause)
+ let shoeLexicalVariable1 = document; // ClosureScope (shoeLexicalVariable1)
+ if (true) {
+ let blockLexicalVariable = "block"; // NestedBlockScope (blockLexicalVariable)
+ debugger;
+ }
+}
+
+function entry() { // Global (entry)
+ var fooVarVariable1; // foo ClosureScope (fooVarVariable1)
+ let fooLexicalVariable2; // foo ClosureScope (fooLexicalVariable2)
+ firstPause();
+
+ function firstPause() { // foo ClosureScope (firstPause)
+ let fakeFirstPauseLexicalVariable; // firstPause ClosureScope (fakeFirstPauseLexicalVariable)
+ (function firstPause() {
+ var barVarVariable1 = window.navigator; // firstPause ClosureScope (barVarVariable1)
+ let barLexicalVariable2 = window.navigator; // firstPause ClosureScope (barLexicalVariable2)
+ if (true) {
+ let barLexicalVariable2 = window.navigator; // NestedBlockScope (barLexicalVariable2)
+ debugger;
+ secondPause();
+ }
+ })();
+ }
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -239,6 +239,7 @@
</span><span class="cx">
</span><span class="cx"> debugger/Debugger.cpp
</span><span class="cx"> debugger/DebuggerCallFrame.cpp
</span><ins>+ debugger/DebuggerLocation.cpp
</ins><span class="cx"> debugger/DebuggerScope.cpp
</span><span class="cx">
</span><span class="cx"> dfg/DFGAbstractHeap.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -1,3 +1,71 @@
</span><ins>+2016-06-29 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Wrong function name next to scope
+ https://bugs.webkit.org/show_bug.cgi?id=158210
+ <rdar://problem/26543093>
+
+ Reviewed by Brian Burg.
+
+ * CMakeLists.txt:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ Add DebuggerLocation. A helper for describing a unique location.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::setConstantRegisters):
+ When compiled with debug info, add a SymbolTable rare data pointer
+ back to the CodeBlock. This will be used later to get JSScope debug
+ info if Web Inspector pauses.
+
+ * runtime/SymbolTable.h:
+ * runtime/SymbolTable.cpp:
+ (JSC::SymbolTable::cloneScopePart):
+ (JSC::SymbolTable::prepareForTypeProfiling):
+ (JSC::SymbolTable::uniqueIDForVariable):
+ (JSC::SymbolTable::uniqueIDForOffset):
+ (JSC::SymbolTable::globalTypeSetForOffset):
+ (JSC::SymbolTable::globalTypeSetForVariable):
+ Rename rareData and include a CodeBlock pointer.
+
+ (JSC::SymbolTable::rareDataCodeBlock):
+ (JSC::SymbolTable::setRareDataCodeBlock):
+ Setter and getter for the rare data. It should only be set once.
+
+ (JSC::SymbolTable::visitChildren):
+ Visit the rare data code block if we have one.
+
+ * debugger/DebuggerLocation.cpp: Added.
+ (JSC::DebuggerLocation::DebuggerLocation):
+ * debugger/DebuggerLocation.h: Added.
+ (JSC::DebuggerLocation::DebuggerLocation):
+ Construction from a ScriptExecutable.
+
+ * runtime/JSScope.cpp:
+ (JSC::JSScope::symbolTable):
+ * runtime/JSScope.h:
+ * debugger/DebuggerScope.h:
+ * debugger/DebuggerScope.cpp:
+ (JSC::DebuggerScope::name):
+ (JSC::DebuggerScope::location):
+ Name and location for a scope. This uses:
+ JSScope -> SymbolTable -> CodeBlock -> Executable
+
+ * inspector/protocol/Debugger.json:
+ * inspector/InjectedScriptSource.js:
+ (InjectedScript.CallFrameProxy.prototype._wrapScopeChain):
+ (InjectedScript.CallFrameProxy._createScopeJson):
+ * inspector/JSJavaScriptCallFrame.cpp:
+ (Inspector::valueForScopeType):
+ (Inspector::valueForScopeLocation):
+ (Inspector::JSJavaScriptCallFrame::scopeDescriptions):
+ (Inspector::JSJavaScriptCallFrame::scopeType): Deleted.
+ * inspector/JSJavaScriptCallFrame.h:
+ * inspector/JSJavaScriptCallFramePrototype.cpp:
+ (Inspector::JSJavaScriptCallFramePrototype::finishCreation):
+ (Inspector::jsJavaScriptCallFramePrototypeFunctionScopeDescriptions):
+ (Inspector::jsJavaScriptCallFramePrototypeFunctionScopeType): Deleted.
+ Simplify this code to build the objects we will send across the protocol
+ to descript a Scope.
+
</ins><span class="cx"> 2016-06-29 Saam barati <sbarati@apple.com>
</span><span class="cx">
</span><span class="cx"> We don't emit TDZ checks for call_eval
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -1645,6 +1645,8 @@
</span><span class="cx">                 A5EF9B171A1D440300702E90 /* generate_cpp_frontend_dispatcher_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D41A05C76F005CAB76 /* generate_cpp_frontend_dispatcher_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 A5EF9B181A1D440600702E90 /* generate_cpp_protocol_types_header.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D51A05C76F005CAB76 /* generate_cpp_protocol_types_header.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 A5EF9B191A1D440700702E90 /* generate_cpp_protocol_types_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D61A05C76F005CAB76 /* generate_cpp_protocol_types_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                A5FC84B21D1DDAD6006B5C46 /* DebuggerLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */; };
+                A5FC84B31D1DDAD9006B5C46 /* DebuggerLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */; };
</ins><span class="cx">                 A5FD0067189AFE9C00633231 /* ScriptArguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FD0065189AFE9C00633231 /* ScriptArguments.cpp */; };
</span><span class="cx">                 A5FD0068189AFE9C00633231 /* ScriptArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = A5FD0066189AFE9C00633231 /* ScriptArguments.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 A5FD006D189B00AA00633231 /* ScriptCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FD0069189B00A900633231 /* ScriptCallFrame.cpp */; };
</span><span class="lines">@@ -3865,6 +3867,8 @@
</span><span class="cx">                 A5EA70F619F6DE5A0098F5EC /* generate_objc_internal_header.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = generate_objc_internal_header.py; sourceTree = "<group>"; };
</span><span class="cx">                 A5EA70F819F6DE5A0098F5EC /* objc_generator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = objc_generator.py; sourceTree = "<group>"; };
</span><span class="cx">                 A5EA710D19F6DF810098F5EC /* InspectorAlternateBackendDispatchers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorAlternateBackendDispatchers.h; sourceTree = "<group>"; };
</span><ins>+                A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerLocation.cpp; sourceTree = "<group>"; };
+                A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerLocation.h; sourceTree = "<group>"; };
</ins><span class="cx">                 A5FD0065189AFE9C00633231 /* ScriptArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptArguments.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 A5FD0066189AFE9C00633231 /* ScriptArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptArguments.h; sourceTree = "<group>"; };
</span><span class="cx">                 A5FD0069189B00A900633231 /* ScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptCallFrame.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -5342,6 +5346,8 @@
</span><span class="cx">                                 149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */,
</span><span class="cx">                                 1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */,
</span><span class="cx">                                 6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */,
</span><ins>+                                A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */,
+                                A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */,
</ins><span class="cx">                                 FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */,
</span><span class="cx">                                 0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */,
</span><span class="cx">                                 0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */,
</span><span class="lines">@@ -7691,6 +7697,7 @@
</span><span class="cx">                                 996B731C1BDA08DD00331B84 /* JSDataViewPrototype.lut.h in Headers */,
</span><span class="cx">                                 978801411471AD920041B016 /* JSDateMath.h in Headers */,
</span><span class="cx">                                 C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */,
</span><ins>+                                A5FC84B21D1DDAD6006B5C46 /* DebuggerLocation.h in Headers */,
</ins><span class="cx">                                 FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */,
</span><span class="cx">                                 FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */,
</span><span class="cx">                                 BC18C42D0E16F5CD00B34460 /* JSEnvironmentRecord.h in Headers */,
</span><span class="lines">@@ -8770,6 +8777,7 @@
</span><span class="cx">                                 A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
</span><span class="cx">                                 52B717B51A0597E1007AF4F3 /* ControlFlowProfiler.cpp in Sources */,
</span><span class="cx">                                 0FBADF541BD1F4B800E073C1 /* CopiedBlock.cpp in Sources */,
</span><ins>+                                A5FC84B31D1DDAD9006B5C46 /* DebuggerLocation.cpp in Sources */,
</ins><span class="cx">                                 C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
</span><span class="cx">                                 0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */,
</span><span class="cx">                                 C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -2477,7 +2477,12 @@
</span><span class="cx"> ConcurrentJITLocker locker(symbolTable->m_lock);
</span><span class="cx"> symbolTable->prepareForTypeProfiling(locker);
</span><span class="cx"> }
</span><del>- constant = symbolTable->cloneScopePart(*m_vm);
</del><ins>+
+ SymbolTable* clone = symbolTable->cloneScopePart(*m_vm);
+ if (wasCompiledWithDebuggingOpcodes())
+ clone->setRareDataCodeBlock(this);
+
+ constant = clone;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerLocationcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/debugger/DebuggerLocation.cpp (0 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerLocation.cpp         (rev 0)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerLocation.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DebuggerLocation.h"
+
+#include "Executable.h"
+
+namespace JSC {
+
+DebuggerLocation::DebuggerLocation(ScriptExecutable* executable)
+{
+ if (executable->isHostFunction())
+ return;
+
+ sourceID = executable->sourceID();
+ line = executable->firstLine();
+ column = executable->startColumn();
+ url = executable->sourceURL();
+ if (url.isEmpty())
+ url = executable->source().provider()->sourceURL();
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerLocationh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/debugger/DebuggerLocation.h (0 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerLocation.h         (rev 0)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerLocation.h        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "DebuggerPrimitives.h"
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class ScriptExecutable;
+
+struct DebuggerLocation {
+
+ DebuggerLocation() { }
+ DebuggerLocation(const String& url, intptr_t sourceID, unsigned line, unsigned column)
+ : url(url)
+ , sourceID(sourceID)
+ , line(line)
+ , column(column)
+ { }
+
+ DebuggerLocation(ScriptExecutable*);
+
+ String url;
+ intptr_t sourceID { noSourceID };
+ unsigned line { 0 };
+ unsigned column { 0 };
+};
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -210,6 +210,33 @@
</span><span class="cx"> return m_scope->isNestedLexicalScope();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+String DebuggerScope::name() const
+{
+ SymbolTable* symbolTable = m_scope->symbolTable();
+ if (!symbolTable)
+ return String();
+
+ CodeBlock* codeBlock = symbolTable->rareDataCodeBlock();
+ if (!codeBlock)
+ return String();
+
+ return String::fromUTF8(codeBlock->inferredName());
+}
+
+DebuggerLocation DebuggerScope::location() const
+{
+ SymbolTable* symbolTable = m_scope->symbolTable();
+ if (!symbolTable)
+ return DebuggerLocation();
+
+ CodeBlock* codeBlock = symbolTable->rareDataCodeBlock();
+ if (!codeBlock)
+ return DebuggerLocation();
+
+ ScriptExecutable* executable = codeBlock->ownerScriptExecutable();
+ return DebuggerLocation(executable);
+}
+
</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 (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef DebuggerScope_h
</span><span class="cx"> #define DebuggerScope_h
</span><span class="cx">
</span><ins>+#include "DebuggerLocation.h"
</ins><span class="cx"> #include "JSObject.h"
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -88,6 +89,9 @@
</span><span class="cx"> bool isGlobalLexicalEnvironment() const;
</span><span class="cx"> bool isNestedLexicalScope() const;
</span><span class="cx">
</span><ins>+ String name() const;
+ DebuggerLocation location() const;
+
</ins><span class="cx"> JSValue caughtValue(ExecState*) const;
</span><span class="cx">
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -1306,9 +1306,11 @@
</span><span class="cx"> _wrapScopeChain: function(callFrame)
</span><span class="cx"> {
</span><span class="cx"> var scopeChain = callFrame.scopeChain;
</span><ins>+ var scopeDescriptions = callFrame.scopeDescriptions();
+
</ins><span class="cx"> var scopeChainProxy = [];
</span><span class="cx"> for (var i = 0; i < scopeChain.length; i++)
</span><del>- scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(callFrame.scopeType(i), scopeChain[i], "backtrace");
</del><ins>+ scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(scopeChain[i], scopeDescriptions[i], "backtrace");
</ins><span class="cx"> return scopeChainProxy;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1321,14 +1323,21 @@
</span><span class="cx"> 4: "functionName", // FUNCTION_NAME_SCOPE
</span><span class="cx"> 5: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE
</span><span class="cx"> 6: "nestedLexical", // NESTED_LEXICAL_SCOPE
</span><del>-}
</del><ins>+};
</ins><span class="cx">
</span><del>-InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)
</del><ins>+InjectedScript.CallFrameProxy._createScopeJson = function(object, {name, type, location}, groupId)
</ins><span class="cx"> {
</span><del>- return {
- object: injectedScript._wrapObject(scopeObject, groupId),
- type: InjectedScript.CallFrameProxy._scopeTypeNames[scopeTypeCode]
</del><ins>+ var scope = {
+ object: injectedScript._wrapObject(object, groupId),
+ type: InjectedScript.CallFrameProxy._scopeTypeNames[type],
</ins><span class="cx"> };
</span><ins>+
+ if (name)
+ scope.name = name;
+ if (location)
+ scope.location = location;
+
+ return scope;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -28,9 +28,11 @@
</span><span class="cx">
</span><span class="cx"> #include "DebuggerScope.h"
</span><span class="cx"> #include "Error.h"
</span><ins>+#include "IdentifierInlines.h"
</ins><span class="cx"> #include "JSCJSValue.h"
</span><span class="cx"> #include "JSCellInlines.h"
</span><span class="cx"> #include "JSJavaScriptCallFramePrototype.h"
</span><ins>+#include "ObjectConstructor.h"
</ins><span class="cx"> #include "StructureInlines.h"
</span><span class="cx">
</span><span class="cx"> using namespace JSC;
</span><span class="lines">@@ -92,45 +94,58 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec)
</del><ins>+static JSValue valueForScopeType(DebuggerScope* scope)
</ins><span class="cx"> {
</span><del>- if (!impl().scopeChain())
- return jsUndefined();
</del><ins>+ if (scope->isCatchScope())
+ return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
+ if (scope->isFunctionNameScope())
+ 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())
+ return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
</ins><span class="cx">
</span><del>- if (!exec->argument(0).isInt32())
</del><ins>+ ASSERT(scope->isClosureScope());
+ return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
+}
+
+static JSValue valueForScopeLocation(ExecState* exec, const DebuggerLocation& location)
+{
+ if (location.sourceID == noSourceID)
+ return jsNull();
+
+ // Debugger.Location protocol object.
+ JSObject* result = constructEmptyObject(exec);
+ result->putDirect(exec->vm(), Identifier::fromString(exec, "scriptId"), jsString(exec, String::number(location.sourceID)));
+ result->putDirect(exec->vm(), Identifier::fromString(exec, "lineNumber"), jsNumber(location.line));
+ result->putDirect(exec->vm(), Identifier::fromString(exec, "columnNumber"), jsNumber(location.column));
+ return result;
+}
+
+JSValue JSJavaScriptCallFrame::scopeDescriptions(ExecState* exec)
+{
+ DebuggerScope* scopeChain = impl().scopeChain();
+ if (!scopeChain)
</ins><span class="cx"> return jsUndefined();
</span><del>- int index = exec->argument(0).asInt32();
</del><span class="cx">
</span><del>- DebuggerScope* scopeChain = impl().scopeChain();
</del><ins>+ int index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr);
+
</ins><span class="cx"> DebuggerScope::iterator end = scopeChain->end();
</span><del>-
</del><span class="cx"> for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
</span><span class="cx"> DebuggerScope* scope = iter.get();
</span><del>-
- if (!index) {
- if (scope->isCatchScope())
- return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
- if (scope->isFunctionNameScope())
- 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()) {
- ASSERT(++iter == end);
- return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
- }
- ASSERT(scope->isClosureScope());
- return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
- }
-
- --index;
</del><ins>+ JSObject* description = constructEmptyObject(exec);
+ description->putDirect(exec->vm(), Identifier::fromString(exec, "type"), valueForScopeType(scope));
+ description->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, scope->name()));
+ description->putDirect(exec->vm(), Identifier::fromString(exec, "location"), valueForScopeLocation(exec, scope->location()));
+ array->putDirectIndex(exec, index++, description);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- ASSERT_NOT_REACHED();
- return jsUndefined();
</del><ins>+ return array;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSValue JSJavaScriptCallFrame::caller(ExecState* exec) const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">
</span><span class="cx"> // Functions.
</span><span class="cx"> JSC::JSValue evaluateWithScopeExtension(JSC::ExecState*);
</span><del>- JSC::JSValue scopeType(JSC::ExecState*);
</del><ins>+ JSC::JSValue scopeDescriptions(JSC::ExecState*);
</ins><span class="cx">
</span><span class="cx"> // Attributes.
</span><span class="cx"> JSC::JSValue caller(JSC::ExecState*) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramePrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx">
</span><span class="cx"> // Functions.
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension(ExecState*);
</span><del>-static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeType(ExecState*);
</del><ins>+static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState*);
</ins><span class="cx">
</span><span class="cx"> // Attributes.
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeCaller(ExecState*);
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx"> vm.prototypeMap.addPrototype(this);
</span><span class="cx">
</span><span class="cx"> JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension, DontEnum, 1);
</span><del>- JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeType", jsJavaScriptCallFramePrototypeFunctionScopeType, DontEnum, 1);
</del><ins>+ JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeDescriptions", jsJavaScriptCallFramePrototypeFunctionScopeDescriptions, DontEnum, 0);
</ins><span class="cx">
</span><span class="cx"> JSC_NATIVE_GETTER("caller", jsJavaScriptCallFrameAttributeCaller, DontEnum | Accessor);
</span><span class="cx"> JSC_NATIVE_GETTER("sourceID", jsJavaScriptCallFrameAttributeSourceID, DontEnum | Accessor);
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx"> return JSValue::encode(castedThis->evaluateWithScopeExtension(exec));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeType(ExecState* exec)
</del><ins>+EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState* exec)
</ins><span class="cx"> {
</span><span class="cx"> JSValue thisValue = exec->thisValue();
</span><span class="cx"> JSJavaScriptCallFrame* castedThis = jsDynamicCast<JSJavaScriptCallFrame*>(thisValue);
</span><span class="lines">@@ -91,7 +91,7 @@
</span><span class="cx"> if (!castedThis)
</span><span class="cx"> return throwVMTypeError(exec);
</span><span class="cx">
</span><del>- return JSValue::encode(castedThis->scopeType(exec));
</del><ins>+ return JSValue::encode(castedThis->scopeDescriptions(exec));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeCaller(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -81,8 +81,10 @@
</span><span class="cx"> "id": "Scope",
</span><span class="cx"> "type": "object",
</span><span class="cx"> "properties": [
</span><ins>+ { "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." },
</ins><span class="cx"> { "name": "type", "type": "string", "enum": ["global", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." },
</span><del>- { "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." }
</del><ins>+ { "name": "name", "type": "string", "optional": true, "description": "Name associated with the scope." },
+ { "name": "location", "$ref": "Location", "optional": true, "description": "Location if available of the scope definition." }
</ins><span class="cx"> ],
</span><span class="cx"> "description": "Scope description."
</span><span class="cx"> },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -340,4 +340,12 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+SymbolTable* JSScope::symbolTable()
+{
+ if (JSSymbolTableObject* symbolTableObject = jsDynamicCast<JSSymbolTableObject*>(this))
+ return symbolTableObject->symbolTable();
+
+ return nullptr;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.h (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.h        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.h        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -32,8 +32,9 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><span class="cx"> class ScopeChainIterator;
</span><ins>+class SymbolTable;
+class VariableEnvironment;
</ins><span class="cx"> class WatchpointSet;
</span><del>-class VariableEnvironment;
</del><span class="cx">
</span><span class="cx"> class JSScope : public JSNonFinalObject {
</span><span class="cx"> public:
</span><span class="lines">@@ -71,6 +72,8 @@
</span><span class="cx"> VM* vm();
</span><span class="cx"> JSObject* globalThis();
</span><span class="cx">
</span><ins>+ SymbolTable* symbolTable();
+
</ins><span class="cx"> protected:
</span><span class="cx"> JSScope(VM&, Structure*, JSScope* next);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -104,6 +104,9 @@
</span><span class="cx"> visitor.append(&thisSymbolTable->m_arguments);
</span><span class="cx"> visitor.append(&thisSymbolTable->m_singletonScope);
</span><span class="cx">
</span><ins>+ if (thisSymbolTable->m_rareData)
+ visitor.append(&thisSymbolTable->m_rareData->m_codeBlock);
+
</ins><span class="cx"> // Save some memory. This is O(n) to rebuild and we do so on the fly.
</span><span class="cx"> ConcurrentJITLocker locker(thisSymbolTable->m_lock);
</span><span class="cx"> thisSymbolTable->m_localToEntry = nullptr;
</span><span class="lines">@@ -159,28 +162,28 @@
</span><span class="cx"> if (ScopedArgumentsTable* arguments = this->arguments())
</span><span class="cx"> result->m_arguments.set(vm, result, arguments);
</span><span class="cx">
</span><del>- if (m_typeProfilingRareData) {
- result->m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>();
</del><ins>+ if (m_rareData) {
+ result->m_rareData = std::make_unique<SymbolTableRareData>();
</ins><span class="cx">
</span><span class="cx"> {
</span><del>- auto iter = m_typeProfilingRareData->m_uniqueIDMap.begin();
- auto end = m_typeProfilingRareData->m_uniqueIDMap.end();
</del><ins>+ auto iter = m_rareData->m_uniqueIDMap.begin();
+ auto end = m_rareData->m_uniqueIDMap.end();
</ins><span class="cx"> for (; iter != end; ++iter)
</span><del>- result->m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, iter->value);
</del><ins>+ result->m_rareData->m_uniqueIDMap.set(iter->key, iter->value);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> {
</span><del>- auto iter = m_typeProfilingRareData->m_offsetToVariableMap.begin();
- auto end = m_typeProfilingRareData->m_offsetToVariableMap.end();
</del><ins>+ auto iter = m_rareData->m_offsetToVariableMap.begin();
+ auto end = m_rareData->m_offsetToVariableMap.end();
</ins><span class="cx"> for (; iter != end; ++iter)
</span><del>- result->m_typeProfilingRareData->m_offsetToVariableMap.set(iter->key, iter->value);
</del><ins>+ result->m_rareData->m_offsetToVariableMap.set(iter->key, iter->value);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> {
</span><del>- auto iter = m_typeProfilingRareData->m_uniqueTypeSetMap.begin();
- auto end = m_typeProfilingRareData->m_uniqueTypeSetMap.end();
</del><ins>+ auto iter = m_rareData->m_uniqueTypeSetMap.begin();
+ auto end = m_rareData->m_uniqueTypeSetMap.end();
</ins><span class="cx"> for (; iter != end; ++iter)
</span><del>- result->m_typeProfilingRareData->m_uniqueTypeSetMap.set(iter->key, iter->value);
</del><ins>+ result->m_rareData->m_uniqueTypeSetMap.set(iter->key, iter->value);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -189,23 +192,40 @@
</span><span class="cx">
</span><span class="cx"> void SymbolTable::prepareForTypeProfiling(const ConcurrentJITLocker&)
</span><span class="cx"> {
</span><del>- if (m_typeProfilingRareData)
</del><ins>+ if (m_rareData)
</ins><span class="cx"> return;
</span><span class="cx">
</span><del>- m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>();
</del><ins>+ m_rareData = std::make_unique<SymbolTableRareData>();
</ins><span class="cx">
</span><span class="cx"> for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
</span><del>- m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration);
- m_typeProfilingRareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key);
</del><ins>+ m_rareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration);
+ m_rareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+CodeBlock* SymbolTable::rareDataCodeBlock()
+{
+ if (!m_rareData)
+ return nullptr;
+
+ return m_rareData->m_codeBlock.get();
+}
+
+void SymbolTable::setRareDataCodeBlock(CodeBlock* codeBlock)
+{
+ if (!m_rareData)
+ m_rareData = std::make_unique<SymbolTableRareData>();
+
+ ASSERT(!m_rareData->m_codeBlock);
+ m_rareData->m_codeBlock.set(*codeBlock->vm(), this, codeBlock);
+}
+
</ins><span class="cx"> GlobalVariableID SymbolTable::uniqueIDForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM& vm)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_typeProfilingRareData);
</del><ins>+ RELEASE_ASSERT(m_rareData);
</ins><span class="cx">
</span><del>- auto iter = m_typeProfilingRareData->m_uniqueIDMap.find(key);
- auto end = m_typeProfilingRareData->m_uniqueIDMap.end();
</del><ins>+ auto iter = m_rareData->m_uniqueIDMap.find(key);
+ auto end = m_rareData->m_uniqueIDMap.end();
</ins><span class="cx"> if (iter == end)
</span><span class="cx"> return TypeProfilerNoGlobalIDExists;
</span><span class="cx">
</span><span class="lines">@@ -212,8 +232,8 @@
</span><span class="cx"> GlobalVariableID id = iter->value;
</span><span class="cx"> if (id == TypeProfilerNeedsUniqueIDGeneration) {
</span><span class="cx"> id = vm.typeProfiler()->getNextUniqueVariableID();
</span><del>- m_typeProfilingRareData->m_uniqueIDMap.set(key, id);
- m_typeProfilingRareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID.
</del><ins>+ m_rareData->m_uniqueIDMap.set(key, id);
+ m_rareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID.
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return id;
</span><span class="lines">@@ -221,10 +241,10 @@
</span><span class="cx">
</span><span class="cx"> GlobalVariableID SymbolTable::uniqueIDForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_typeProfilingRareData);
</del><ins>+ RELEASE_ASSERT(m_rareData);
</ins><span class="cx">
</span><del>- auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset);
- auto end = m_typeProfilingRareData->m_offsetToVariableMap.end();
</del><ins>+ auto iter = m_rareData->m_offsetToVariableMap.find(offset);
+ auto end = m_rareData->m_offsetToVariableMap.end();
</ins><span class="cx"> if (iter == end)
</span><span class="cx"> return TypeProfilerNoGlobalIDExists;
</span><span class="cx">
</span><span class="lines">@@ -233,12 +253,12 @@
</span><span class="cx">
</span><span class="cx"> RefPtr<TypeSet> SymbolTable::globalTypeSetForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_typeProfilingRareData);
</del><ins>+ RELEASE_ASSERT(m_rareData);
</ins><span class="cx">
</span><span class="cx"> uniqueIDForOffset(locker, offset, vm); // Lazily create the TypeSet if necessary.
</span><span class="cx">
</span><del>- auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset);
- auto end = m_typeProfilingRareData->m_offsetToVariableMap.end();
</del><ins>+ auto iter = m_rareData->m_offsetToVariableMap.find(offset);
+ auto end = m_rareData->m_offsetToVariableMap.end();
</ins><span class="cx"> if (iter == end)
</span><span class="cx"> return nullptr;
</span><span class="cx">
</span><span class="lines">@@ -247,12 +267,12 @@
</span><span class="cx">
</span><span class="cx"> RefPtr<TypeSet> SymbolTable::globalTypeSetForVariable(const ConcurrentJITLocker& locker, UniquedStringImpl* key, VM& vm)
</span><span class="cx"> {
</span><del>- RELEASE_ASSERT(m_typeProfilingRareData);
</del><ins>+ RELEASE_ASSERT(m_rareData);
</ins><span class="cx">
</span><span class="cx"> uniqueIDForVariable(locker, key, vm); // Lazily create the TypeSet if necessary.
</span><span class="cx">
</span><del>- auto iter = m_typeProfilingRareData->m_uniqueTypeSetMap.find(key);
- auto end = m_typeProfilingRareData->m_uniqueTypeSetMap.end();
</del><ins>+ auto iter = m_rareData->m_uniqueTypeSetMap.find(key);
+ auto end = m_rareData->m_uniqueTypeSetMap.end();
</ins><span class="cx"> if (iter == end)
</span><span class="cx"> return nullptr;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SymbolTable.h (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/JavaScriptCore/runtime/SymbolTable.h        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -679,6 +679,9 @@
</span><span class="cx"> SymbolTable* cloneScopePart(VM&);
</span><span class="cx">
</span><span class="cx"> void prepareForTypeProfiling(const ConcurrentJITLocker&);
</span><ins>+
+ CodeBlock* rareDataCodeBlock();
+ void setRareDataCodeBlock(CodeBlock*);
</ins><span class="cx">
</span><span class="cx"> InferredValue* singletonScope() { return m_singletonScope.get(); }
</span><span class="cx">
</span><span class="lines">@@ -695,12 +698,13 @@
</span><span class="cx"> Map m_map;
</span><span class="cx"> ScopeOffset m_maxScopeOffset;
</span><span class="cx">
</span><del>- struct TypeProfilingRareData {
</del><ins>+ struct SymbolTableRareData {
</ins><span class="cx"> UniqueIDMap m_uniqueIDMap;
</span><span class="cx"> OffsetToVariableMap m_offsetToVariableMap;
</span><span class="cx"> UniqueTypeSetMap m_uniqueTypeSetMap;
</span><ins>+ WriteBarrier<CodeBlock> m_codeBlock;
</ins><span class="cx"> };
</span><del>- std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
</del><ins>+ std::unique_ptr<SymbolTableRareData> m_rareData;
</ins><span class="cx">
</span><span class="cx"> bool m_usesNonStrictEval : 1;
</span><span class="cx"> bool m_nestedLexicalScope : 1; // Non-function LexicalScope.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -1,3 +1,65 @@
</span><ins>+2016-06-29 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Wrong function name next to scope
+ https://bugs.webkit.org/show_bug.cgi?id=158210
+ <rdar://problem/26543093>
+
+ Reviewed by Brian Burg.
+
+ * UserInterface/Controllers/DebuggerManager.js:
+ (WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload):
+ Include new payload data in the construction call.
+ All the new data is optional, so we gracefully handle
+ legacy backends.
+
+ * UserInterface/Models/ScopeChainNode.js:
+ (WebInspector.ScopeChainNode):
+ (WebInspector.ScopeChainNode.prototype.get type):
+ (WebInspector.ScopeChainNode.prototype.get objects):
+ (WebInspector.ScopeChainNode.prototype.get name):
+ (WebInspector.ScopeChainNode.prototype.get location):
+ (WebInspector.ScopeChainNode.prototype.get hash):
+ Hash is a rough (name:sourceId:line:column) string for quick comparisons.
+
+ (WebInspector.ScopeChainNode.prototype.makeLocalScope):
+ Make this an action you take on a scope, to avoid having to
+ do it at construction time, or making it a generic setting.
+
+ * UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
+ (WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection):
+ This was wrong before. Move the work to CallFrame
+ and change it to be correct.
+
+ * UserInterface/CallFrame.js:
+ (WebInspector.CallFrame.prototype.mergedScopeChain):
+
+ This transforms the scope chain for a call frame from:
+
+ scope1 scope2 scope3 scope4 scope5 scope6 scope7
+ foo foo foo bar bar - -
+ Block Closure Closure Closure Closure GLE GBL
+
+ To:
+ scope1 scope2&3 scope4&5 scope6 scope7
+ foo foo* bar* - -
+ Block Local Closure GLE GBL
+
+ Doing a few things:
+
+ - Merge the first two Closure scopes sharing a location.
+ These are the "var" and "let" Closure scopes in a function,
+ and it is better to present these together in the UI.
+
+ - Mark the first Closure scope within a function (*). When
+ this is displayed in the UI, we can provide the name of
+ the function: "Closure Scope (name)", and we even have
+ location information that we can use to display a goto
+ arrow if needed.
+
+ - Make the first Closure scope the Local scope if it
+ matches the Call Frame's function name. This lets us
+ display the section as "Local Variables".
+
</ins><span class="cx"> 2016-06-29 Brian Burg <bburg@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: Uncaught Exception page never shows if exception is thrown while processing a protocol event
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -662,7 +662,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> var object = WebInspector.RemoteObject.fromPayload(payload.object);
</span><del>- return new WebInspector.ScopeChainNode(type, [object]);
</del><ins>+ return new WebInspector.ScopeChainNode(type, [object], payload.name, payload.location);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> _pauseReasonFromPayload(payload)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsCallFramejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -45,46 +45,15 @@
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="cx">
</span><del>- get id()
- {
- return this._id;
- }
</del><ins>+ get id() { return this._id; }
+ get sourceCodeLocation() { return this._sourceCodeLocation; }
+ get functionName() { return this._functionName; }
+ get nativeCode() { return this._nativeCode; }
+ get programCode() { return this._programCode; }
+ get thisObject() { return this._thisObject; }
+ get scopeChain() { return this._scopeChain; }
+ get isTailDeleted() { return this._isTailDeleted; }
</ins><span class="cx">
</span><del>- get sourceCodeLocation()
- {
- return this._sourceCodeLocation;
- }
-
- get functionName()
- {
- return this._functionName;
- }
-
- get nativeCode()
- {
- return this._nativeCode;
- }
-
- get programCode()
- {
- return this._programCode;
- }
-
- get thisObject()
- {
- return this._thisObject;
- }
-
- get scopeChain()
- {
- return this._scopeChain;
- }
-
- get isTailDeleted()
- {
- return this._isTailDeleted;
- }
-
</del><span class="cx"> saveIdentityToCookie()
</span><span class="cx"> {
</span><span class="cx"> // Do nothing. The call frame is torn down when the inspector closes, and
</span><span class="lines">@@ -112,6 +81,99 @@
</span><span class="cx"> this._scopeChain[i].objects[0].deprecatedGetAllProperties(propertiesCollected);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ mergedScopeChain()
+ {
+ let mergedScopes = [];
+
+ // Scopes list goes from top/local (1) to bottom/global (5)
+ // [scope1, scope2, scope3, scope4, scope5]
+ let scopes = this._scopeChain.slice();
+
+ // Merge similiar scopes. Some function call frames may have multiple
+ // top level closure scopes (one for `var`s one for `let`s) that can be
+ // combined to a single scope of variables. Go in reverse order so we
+ // merge the first two closure scopes with the same name. Also mark
+ // the first time we see a new name, so we know the base for the name.
+ // [scope1&2, scope3, scope4, scope5]
+ // foo bar GLE global
+ let lastMarkedHash = null;
+ function markAsBaseIfNeeded(scope) {
+ if (!scope.hash)
+ return false;
+ if (scope.type !== WebInspector.ScopeChainNode.Type.Closure)
+ return false;
+ if (scope.hash === lastMarkedHash)
+ return false;
+ lastMarkedHash = scope.hash;
+ scope.__baseClosureScope = true;
+ return true;
+ }
+
+ function shouldMergeClosureScopes(youngScope, oldScope, lastMerge) {
+ if (!youngScope || !oldScope)
+ return false;
+
+ // Don't merge unknown locations.
+ if (!youngScope.hash || !oldScope.hash)
+ return false;
+
+ // Only merge closure scopes.
+ if (youngScope.type !== WebInspector.ScopeChainNode.Type.Closure)
+ return false;
+ if (oldScope.type !== WebInspector.ScopeChainNode.Type.Closure)
+ return false;
+
+ // Don't merge if they are not the same.
+ if (youngScope.hash !== oldScope.hash)
+ return false;
+
+ // Don't merge if there was already a merge.
+ if (lastMerge && youngScope.hash === lastMerge.hash)
+ return false;
+
+ return true;
+ }
+
+ let lastScope = null;
+ let lastMerge = null;
+ for (let i = scopes.length - 1; i >= 0; --i) {
+ let scope = scopes[i];
+ markAsBaseIfNeeded(scope);
+ if (shouldMergeClosureScopes(scope, lastScope, lastMerge)) {
+ console.assert(lastScope.__baseClosureScope);
+ let type = WebInspector.ScopeChainNode.Type.Closure;
+ let objects = lastScope.objects.concat(scope.objects);
+ let merged = new WebInspector.ScopeChainNode(type, objects, scope.name, scope.location);
+ merged.__baseClosureScope = true;
+ console.assert(objects.length === 2);
+
+ mergedScopes.pop(); // Remove the last.
+ mergedScopes.push(merged); // Add the merged scope.
+
+ lastMerge = merged;
+ lastScope = null;
+ } else {
+ mergedScopes.push(scope);
+
+ lastMerge = null;
+ lastScope = scope;
+ }
+ }
+
+ mergedScopes = mergedScopes.reverse();
+
+ // Mark the first Closure as Local if the name matches this call frame.
+ for (let scope of mergedScopes) {
+ if (scope.type === WebInspector.ScopeChainNode.Type.Closure) {
+ if (scope.name === this._functionName)
+ scope.convertToLocalScope();
+ break;
+ }
+ }
+
+ return mergedScopes;
+ }
+
</ins><span class="cx"> // Static
</span><span class="cx">
</span><span class="cx"> static functionNameFromPayload(payload)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsScopeChainNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx">
</span><span class="cx"> WebInspector.ScopeChainNode = class ScopeChainNode extends WebInspector.Object
</span><span class="cx"> {
</span><del>- constructor(type, objects)
</del><ins>+ constructor(type, objects, name, location)
</ins><span class="cx"> {
</span><span class="cx"> super();
</span><span class="cx">
</span><span class="lines">@@ -37,18 +37,31 @@
</span><span class="cx">
</span><span class="cx"> this._type = type || null;
</span><span class="cx"> this._objects = objects || [];
</span><ins>+ this._name = name || "";
+ this._location = location || null;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="cx">
</span><del>- get type()
</del><ins>+ get type() { return this._type; }
+ get objects() { return this._objects; }
+ get name() { return this._name; }
+ get location() { return this._location; }
+
+ get hash()
</ins><span class="cx"> {
</span><del>- return this._type;
</del><ins>+ if (this._hash)
+ return this._hash;
+
+ this._hash = this._name;
+ if (this._location)
+ this._hash += `:${this._location.scriptId}:${this._location.lineNumber}:${this._location.columnNumber}`;
+ return this._hash;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- get objects()
</del><ins>+ convertToLocalScope()
</ins><span class="cx"> {
</span><del>- return this._objects;
</del><ins>+ this._type = WebInspector.ScopeChainNode.Type.Local;
</ins><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScopeChainDetailsSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js (202658 => 202659)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js        2016-06-29 23:28:16 UTC (rev 202658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js        2016-06-29 23:59:35 UTC (rev 202659)
</span><span class="lines">@@ -164,159 +164,92 @@
</span><span class="cx"> for (let type in WebInspector.ScopeChainNode.Type)
</span><span class="cx"> sectionCountByType.set(WebInspector.ScopeChainNode.Type[type], 0);
</span><span class="cx">
</span><del>- // Scopes list goes from top/local (1) to bottom/global (5)
- // Call frames list goes from top/local (1) to bottom/global (2)
- // [scope1, scope2, scope3, scope4, scope5]
- // [CallFrame1, CallFrame2]
- let scopeChain = callFrame.scopeChain;
- let callFrames = WebInspector.debuggerManager.callFrames;
</del><ins>+ let scopeChain = callFrame.mergedScopeChain();
+ for (let scope of scopeChain) {
+ let title = null;
+ let extraPropertyDescriptor = null;
+ let collapsedByDefault = false;
</ins><span class="cx">
</span><del>- // Group scopes with the call frame containing them.
- // Creating a map that looks like:
- // CallFrame2 => [scope5, scope4]
- // CallFrame1 => [scope3, scope2, scope1]
- let reversedScopeChain = scopeChain.slice().reverse();
- let callFrameScopes = new Map;
- let lastLength = 0;
- for (let i = callFrames.length - 1; i >= 0; --i) {
- let nextCallFrame = callFrames[i];
- console.assert(nextCallFrame.scopeChain.length > lastLength);
- callFrameScopes.set(nextCallFrame, reversedScopeChain.slice(lastLength, nextCallFrame.scopeChain.length));
- lastLength = nextCallFrame.scopeChain.length;
- if (nextCallFrame === callFrame) {
- console.assert(lastLength === scopeChain.length);
</del><ins>+ let count = sectionCountByType.get(scope.type);
+ sectionCountByType.set(scope.type, ++count);
+
+ switch (scope.type) {
+ case WebInspector.ScopeChainNode.Type.Local:
+ foundLocalScope = true;
+ collapsedByDefault = false;
+ title = WebInspector.UIString("Local Variables");
+ if (callFrame.thisObject)
+ extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: callFrame.thisObject});
</ins><span class="cx"> break;
</span><del>- }
- }
</del><span class="cx">
</span><del>- // Now that we have this map we can merge some of the scopes within an individual
- // call frame. In particular, function call frames may have multiple top level
- // closure scopes (one for `var`s one for `let`s) that can be combined to a
- // single scope of variables.
- // This modifies the Map, resulting in:
- // CallFrame2 => [scope4, scope5]
- // CallFrame1 => [scope1, scope2&3]
- for (let [currentCallFrame, scopes] of callFrameScopes) {
- let firstClosureScope = null;
- for (let scope of scopes) {
- // Reached a non-closure scope. Bail.
- let isClosureScope = scope.type === WebInspector.ScopeChainNode.Type.Closure;
- if (!isClosureScope && firstClosureScope)
- break;
</del><ins>+ case WebInspector.ScopeChainNode.Type.Closure:
+ if (scope.__baseClosureScope && scope.name)
+ title = WebInspector.UIString("Closure Variables (%s)").format(scope.name);
+ else
+ title = WebInspector.UIString("Closure Variables");
+ collapsedByDefault = false;
+ break;
</ins><span class="cx">
</span><del>- // Found first closure scope. Mark it so we can provide the function name later in the UI.
- if (isClosureScope && !firstClosureScope) {
- firstClosureScope = scope;
- firstClosureScope[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] = true;
- continue;
- }
</del><ins>+ case WebInspector.ScopeChainNode.Type.Block:
+ title = WebInspector.UIString("Block Variables");
+ collapsedByDefault = false;
+ break;
</ins><span class="cx">
</span><del>- // Found 2 sequential top level closure scopes. Merge and mark it so we can provide the function name later in the UI.
- if (isClosureScope && firstClosureScope) {
- let type = currentCallFrame === callFrame ? WebInspector.ScopeChainNode.Type.Local : WebInspector.ScopeChainNode.Type.Closure;
- let objects = firstClosureScope.objects.concat(scope.objects);
- let merged = new WebInspector.ScopeChainNode(type, objects);
- merged[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] = true;
- console.assert(objects.length === 2);
</del><ins>+ case WebInspector.ScopeChainNode.Type.Catch:
+ title = WebInspector.UIString("Catch Variables");
+ collapsedByDefault = false;
+ break;
</ins><span class="cx">
</span><del>- let index = scopes.indexOf(firstClosureScope);
- scopes.splice(index, 1); // Remove one of them.
- scopes[index] = merged; // Replace the remaining with the merged.
- break;
- }
- }
- scopes.reverse();
- }
</del><ins>+ case WebInspector.ScopeChainNode.Type.FunctionName:
+ title = WebInspector.UIString("Function Name Variable");
+ collapsedByDefault = true;
+ break;
</ins><span class="cx">
</span><del>- // Now we can walk the list of call frames and their scopes.
- // We walk in top -> down order:
- // CallFrame1 => [scope1, scope2&3]
- // CallFrame2 => [scope5, scope4]
- for (let [call, scopes] of [...callFrameScopes.entries()].reverse()) {
- for (let scope of scopes) {
- let title = null;
- let extraPropertyDescriptor = null;
- let collapsedByDefault = false;
</del><ins>+ case WebInspector.ScopeChainNode.Type.With:
+ title = WebInspector.UIString("With Object Properties");
+ collapsedByDefault = foundLocalScope;
+ break;
</ins><span class="cx">
</span><del>- let count = sectionCountByType.get(scope.type);
- sectionCountByType.set(scope.type, ++count);
</del><ins>+ case WebInspector.ScopeChainNode.Type.Global:
+ title = WebInspector.UIString("Global Variables");
+ collapsedByDefault = true;
+ break;
</ins><span class="cx">
</span><del>- switch (scope.type) {
- case WebInspector.ScopeChainNode.Type.Local:
- foundLocalScope = true;
- collapsedByDefault = false;
- title = WebInspector.UIString("Local Variables");
- if (call.thisObject)
- extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: call.thisObject});
- break;
</del><ins>+ case WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment:
+ title = WebInspector.UIString("Global Lexical Environment");
+ collapsedByDefault = true;
+ break;
+ }
</ins><span class="cx">
</span><del>- case WebInspector.ScopeChainNode.Type.Closure:
- if (scope[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] && call.functionName)
- title = WebInspector.UIString("Closure Variables (%s)").format(call.functionName);
- else
- title = WebInspector.UIString("Closure Variables");
- collapsedByDefault = false;
- break;
</del><ins>+ let detailsSectionIdentifier = scope.type + "-" + sectionCountByType.get(scope.type);
</ins><span class="cx">
</span><del>- case WebInspector.ScopeChainNode.Type.Block:
- title = WebInspector.UIString("Block Variables");
- collapsedByDefault = false;
- break;
</del><ins>+ // FIXME: This just puts two ObjectTreeViews next to each other, but that means
+ // that properties are not nicely sorted between the two separate lists.
</ins><span class="cx">
</span><del>- case WebInspector.ScopeChainNode.Type.Catch:
- title = WebInspector.UIString("Catch Variables");
- collapsedByDefault = false;
- break;
</del><ins>+ let rows = [];
+ for (let object of scope.objects) {
+ let scopePropertyPath = WebInspector.PropertyPath.emptyPropertyPathForScope(object);
+ let objectTree = new WebInspector.ObjectTreeView(object, WebInspector.ObjectTreeView.Mode.Properties, scopePropertyPath);
</ins><span class="cx">
</span><del>- case WebInspector.ScopeChainNode.Type.FunctionName:
- title = WebInspector.UIString("Function Name Variable");
- collapsedByDefault = true;
- break;
</del><ins>+ objectTree.showOnlyProperties();
</ins><span class="cx">
</span><del>- case WebInspector.ScopeChainNode.Type.With:
- title = WebInspector.UIString("With Object Properties");
- collapsedByDefault = foundLocalScope;
- break;
-
- case WebInspector.ScopeChainNode.Type.Global:
- title = WebInspector.UIString("Global Variables");
- collapsedByDefault = true;
- break;
-
- case WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment:
- title = WebInspector.UIString("Global Lexical Environment");
- collapsedByDefault = true;
- break;
</del><ins>+ if (extraPropertyDescriptor) {
+ objectTree.appendExtraPropertyDescriptor(extraPropertyDescriptor);
+ extraPropertyDescriptor = null;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- let detailsSectionIdentifier = scope.type + "-" + sectionCountByType.get(scope.type);
</del><ins>+ let treeOutline = objectTree.treeOutline;
+ treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementAdded, this._treeElementAdded.bind(this, detailsSectionIdentifier), this);
+ treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange.bind(this, detailsSectionIdentifier), this);
</ins><span class="cx">
</span><del>- // FIXME: This just puts two ObjectTreeViews next to eachother, but that means
- // that properties are not nicely sorted between the two separate lists.
</del><ins>+ // FIXME: <https://webkit.org/b/140567> Web Inspector: Do not request Scope Chain lists if section is collapsed (mainly Global Variables)
+ // This autoexpands the ObjectTreeView and fetches all properties. Should wait to see if we are collapsed or not.
+ rows.push(new WebInspector.DetailsSectionPropertiesRow(objectTree));
+ }
</ins><span class="cx">
</span><del>- let rows = [];
- for (let object of scope.objects) {
- let scopePropertyPath = WebInspector.PropertyPath.emptyPropertyPathForScope(object);
- let objectTree = new WebInspector.ObjectTreeView(object, WebInspector.ObjectTreeView.Mode.Properties, scopePropertyPath);
-
- objectTree.showOnlyProperties();
-
- if (extraPropertyDescriptor) {
- objectTree.appendExtraPropertyDescriptor(extraPropertyDescriptor);
- extraPropertyDescriptor = null;
- }
-
- let treeOutline = objectTree.treeOutline;
- treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementAdded, this._treeElementAdded.bind(this, detailsSectionIdentifier), this);
- treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange.bind(this, detailsSectionIdentifier), this);
-
- rows.push(new WebInspector.DetailsSectionPropertiesRow(objectTree));
- }
-
- let detailsSection = new WebInspector.DetailsSection(detailsSectionIdentifier, title, null, null, collapsedByDefault);
- detailsSection.groups[0].rows = rows;
- detailsSections.push(detailsSection);
- }
</del><ins>+ let detailsSection = new WebInspector.DetailsSection(detailsSectionIdentifier, title, null, null, collapsedByDefault);
+ detailsSection.groups[0].rows = rows;
+ detailsSections.push(detailsSection);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return Promise.resolve(detailsSections);
</span><span class="lines">@@ -545,4 +478,3 @@
</span><span class="cx">
</span><span class="cx"> WebInspector.ScopeChainDetailsSidebarPanel._autoExpandProperties = new Set;
</span><span class="cx"> WebInspector.ScopeChainDetailsSidebarPanel.WatchExpressionsObjectGroupName = "watch-expressions";
</span><del>-WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol = Symbol("scope-chain-call-frame-base-closure-scope");
</del></span></pre>
</div>
</div>
</body>
</html>