<!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>[173100] trunk/Source</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/173100">173100</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2014-08-28 17:48:59 -0700 (Thu, 28 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>DebuggerCallFrame::scope() should return a DebuggerScope.
&lt;https://webkit.org/b/134420&gt;

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Rolling back in <a href="http://trac.webkit.org/projects/webkit/changeset/170680">r170680</a> with the fix for &lt;https://webkit.org/b/135656&gt;.

Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
peers) which the WebInspector will use to introspect CallFrame variables.
Instead, we should be returning a DebuggerScope as an abstraction layer that
provides the introspection functionality that the WebInspector needs.  This
is the first step towards not forcing every frame to have a JSActivation
object just because the debugger is enabled.

1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
   instead of the VM.  This allows JSObject::globalObject() to be able to
   return the global object for the DebuggerScope.

2. On the DebuggerScope's life-cycle management:

   The DebuggerCallFrame is designed to be &quot;valid&quot; only during a debugging session
   (while the debugger is broken) through the use of a DebuggerCallFrameScope in
   Debugger::pauseIfNeeded().  Once the debugger resumes from the break, the
   DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
   We can't guarantee (from this code alone) that the Inspector code isn't still
   holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
   the frame will be invalidated, and any attempt to query it will return null values.
   This is pre-existing behavior.

   Now, we're adding the DebuggerScope into the picture.  While a single debugger
   pause session is in progress, the Inspector may request the scope from the
   DebuggerCallFrame.  While the DebuggerCallFrame is still valid, we want
   DebuggerCallFrame::scope() to always return the same DebuggerScope object.
   This is why we hold on to the DebuggerScope with a strong ref.

   If we use a weak ref instead, the following cooky behavior can manifest:
   1. The Inspector calls Debugger::scope() to get the top scope.
   2. The Inspector iterates down the scope chain and is now only holding a
      reference to a parent scope.  It is no longer referencing the top scope.
   3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
      gets cleared.
   4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
      a different DebuggerScope instance.
   5. The Inspector iterates down the scope chain but never sees the parent scope
      instance that retained a ref to in step 2 above.  This is because when iterating
      this new DebuggerScope instance (which has no knowledge of the previous parent
      DebuggerScope instance), a new DebuggerScope instance will get created for the
      same parent scope. 

   Since the DebuggerScope is a JSObject, its liveness is determined by its reachability.
   However, its &quot;validity&quot; is determined by the life-cycle of its owner DebuggerCallFrame.
   When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
   instantiated) will also get invalidated.  This is why we need the
   DebuggerScope::invalidateChain() method.  The Inspector should not be using the
   DebuggerScope instance after its owner DebuggerCallFrame is invalidated.  If it does,
   those methods will do nothing or returned a failed status.

Fix for &lt;https://webkit.org/b/135656&gt;:
3. DebuggerScope::getOwnPropertySlot() and DebuggerScope::put() need to set
   m_thisValue in the returned slot to the wrapped scope object.  Previously,
   it was pointing to the DebuggerScope though the rest of the fields in the
   returned slot will be set to data pertaining the wrapped scope object.

4. DebuggerScope::getOwnPropertySlot() will invoke getPropertySlot() on its
   wrapped scope.  This is because JSObject::getPropertySlot() cannot be
   overridden, and when called on a DebuggerScope, will not know to look in
   the ptototype chain of the DebuggerScope's wrapped scope.  Hence, we'll
   treat all properties in the wrapped scope as own properties in the
   DebuggerScope.  This is fine because the WebInspector does not presently
   care about where in the prototype chain the scope property comes from.

   Note that the DebuggerScope and the JSActivation objects that it wraps do
   not have prototypes.  They are always jsNull().  This works perfectly with
   the above change to use getPropertySlot() instead of getOwnPropertySlot().
   To make this an explicit invariant, I also changed DebuggerScope::createStructure()
   and JSActivation::createStructure() to not take a prototype argument, and
   to always use jsNull() for their prototype value.

* debugger/Debugger.h:
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::scope):
(JSC::DebuggerCallFrame::evaluate):
(JSC::DebuggerCallFrame::invalidate):
* debugger/DebuggerCallFrame.h:
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::DebuggerScope):
(JSC::DebuggerScope::finishCreation):
(JSC::DebuggerScope::visitChildren):
(JSC::DebuggerScope::className):
(JSC::DebuggerScope::getOwnPropertySlot):
(JSC::DebuggerScope::put):
(JSC::DebuggerScope::deleteProperty):
(JSC::DebuggerScope::getOwnPropertyNames):
(JSC::DebuggerScope::defineOwnProperty):
(JSC::DebuggerScope::next):
(JSC::DebuggerScope::invalidateChain):
(JSC::DebuggerScope::isWithScope):
(JSC::DebuggerScope::isGlobalScope):
(JSC::DebuggerScope::isFunctionOrEvalScope):
* debugger/DebuggerScope.h:
(JSC::DebuggerScope::create):
(JSC::DebuggerScope::createStructure):
(JSC::DebuggerScope::iterator::iterator):
(JSC::DebuggerScope::iterator::get):
(JSC::DebuggerScope::iterator::operator++):
(JSC::DebuggerScope::iterator::operator==):
(JSC::DebuggerScope::iterator::operator!=):
(JSC::DebuggerScope::isValid):
(JSC::DebuggerScope::jsScope):
(JSC::DebuggerScope::begin):
(JSC::DebuggerScope::end):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::scopeType):
(Inspector::JSJavaScriptCallFrame::scopeChain):
* inspector/JavaScriptCallFrame.h:
(Inspector::JavaScriptCallFrame::scopeChain):
* inspector/ScriptDebugServer.cpp:
* runtime/JSActivation.h:
(JSC::JSActivation::createStructure):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::debuggerScopeStructure):
* runtime/JSObject.cpp:
* runtime/JSObject.h:
(JSC::JSObject::isWithScope):
* runtime/JSScope.h:
* runtime/PropertySlot.h:
(JSC::PropertySlot::setThisValue):
* runtime/PutPropertySlot.h:
(JSC::PutPropertySlot::setThisValue):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WebCore:

No new tests.

Rolling back in <a href="http://trac.webkit.org/projects/webkit/changeset/170680">r170680</a> with the fix for &lt;https://webkit.org/b/135656&gt;.

* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::attachDebugger):
- We should acquire the JSLock before modifying a JS global object.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerh">trunk/Source/JavaScriptCore/debugger/Debugger.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerCallFramecpp">trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerCallFrameh">trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h</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="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJavaScriptCallFrameh">trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorScriptDebugServercpp">trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSActivationh">trunk/Source/JavaScriptCore/runtime/JSActivation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjecth">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectcpp">trunk/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSScopeh">trunk/Source/JavaScriptCore/runtime/JSScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimePropertySloth">trunk/Source/JavaScriptCore/runtime/PropertySlot.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimePutPropertySloth">trunk/Source/JavaScriptCore/runtime/PutPropertySlot.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsScriptControllercpp">trunk/Source/WebCore/bindings/js/ScriptController.cpp</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#trunkSourceWebCore">trunk/Source/WebCore/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -1,3 +1,141 @@
</span><ins>+2014-08-28  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        DebuggerCallFrame::scope() should return a DebuggerScope.
+        &lt;https://webkit.org/b/134420&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        Rolling back in r170680 with the fix for &lt;https://webkit.org/b/135656&gt;.
+
+        Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
+        peers) which the WebInspector will use to introspect CallFrame variables.
+        Instead, we should be returning a DebuggerScope as an abstraction layer that
+        provides the introspection functionality that the WebInspector needs.  This
+        is the first step towards not forcing every frame to have a JSActivation
+        object just because the debugger is enabled.
+
+        1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
+           instead of the VM.  This allows JSObject::globalObject() to be able to
+           return the global object for the DebuggerScope.
+
+        2. On the DebuggerScope's life-cycle management:
+
+           The DebuggerCallFrame is designed to be &quot;valid&quot; only during a debugging session
+           (while the debugger is broken) through the use of a DebuggerCallFrameScope in
+           Debugger::pauseIfNeeded().  Once the debugger resumes from the break, the
+           DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
+           We can't guarantee (from this code alone) that the Inspector code isn't still
+           holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
+           the frame will be invalidated, and any attempt to query it will return null values.
+           This is pre-existing behavior.
+
+           Now, we're adding the DebuggerScope into the picture.  While a single debugger
+           pause session is in progress, the Inspector may request the scope from the
+           DebuggerCallFrame.  While the DebuggerCallFrame is still valid, we want
+           DebuggerCallFrame::scope() to always return the same DebuggerScope object.
+           This is why we hold on to the DebuggerScope with a strong ref.
+
+           If we use a weak ref instead, the following cooky behavior can manifest:
+           1. The Inspector calls Debugger::scope() to get the top scope.
+           2. The Inspector iterates down the scope chain and is now only holding a
+              reference to a parent scope.  It is no longer referencing the top scope.
+           3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
+              gets cleared.
+           4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
+              a different DebuggerScope instance.
+           5. The Inspector iterates down the scope chain but never sees the parent scope
+              instance that retained a ref to in step 2 above.  This is because when iterating
+              this new DebuggerScope instance (which has no knowledge of the previous parent
+              DebuggerScope instance), a new DebuggerScope instance will get created for the
+              same parent scope. 
+
+           Since the DebuggerScope is a JSObject, its liveness is determined by its reachability.
+           However, its &quot;validity&quot; is determined by the life-cycle of its owner DebuggerCallFrame.
+           When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
+           instantiated) will also get invalidated.  This is why we need the
+           DebuggerScope::invalidateChain() method.  The Inspector should not be using the
+           DebuggerScope instance after its owner DebuggerCallFrame is invalidated.  If it does,
+           those methods will do nothing or returned a failed status.
+
+        Fix for &lt;https://webkit.org/b/135656&gt;:
+        3. DebuggerScope::getOwnPropertySlot() and DebuggerScope::put() need to set
+           m_thisValue in the returned slot to the wrapped scope object.  Previously,
+           it was pointing to the DebuggerScope though the rest of the fields in the
+           returned slot will be set to data pertaining the wrapped scope object.
+
+        4. DebuggerScope::getOwnPropertySlot() will invoke getPropertySlot() on its
+           wrapped scope.  This is because JSObject::getPropertySlot() cannot be
+           overridden, and when called on a DebuggerScope, will not know to look in
+           the ptototype chain of the DebuggerScope's wrapped scope.  Hence, we'll
+           treat all properties in the wrapped scope as own properties in the
+           DebuggerScope.  This is fine because the WebInspector does not presently
+           care about where in the prototype chain the scope property comes from.
+
+           Note that the DebuggerScope and the JSActivation objects that it wraps do
+           not have prototypes.  They are always jsNull().  This works perfectly with
+           the above change to use getPropertySlot() instead of getOwnPropertySlot().
+           To make this an explicit invariant, I also changed DebuggerScope::createStructure()
+           and JSActivation::createStructure() to not take a prototype argument, and
+           to always use jsNull() for their prototype value.
+
+        * debugger/Debugger.h:
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::scope):
+        (JSC::DebuggerCallFrame::evaluate):
+        (JSC::DebuggerCallFrame::invalidate):
+        * debugger/DebuggerCallFrame.h:
+        * debugger/DebuggerScope.cpp:
+        (JSC::DebuggerScope::DebuggerScope):
+        (JSC::DebuggerScope::finishCreation):
+        (JSC::DebuggerScope::visitChildren):
+        (JSC::DebuggerScope::className):
+        (JSC::DebuggerScope::getOwnPropertySlot):
+        (JSC::DebuggerScope::put):
+        (JSC::DebuggerScope::deleteProperty):
+        (JSC::DebuggerScope::getOwnPropertyNames):
+        (JSC::DebuggerScope::defineOwnProperty):
+        (JSC::DebuggerScope::next):
+        (JSC::DebuggerScope::invalidateChain):
+        (JSC::DebuggerScope::isWithScope):
+        (JSC::DebuggerScope::isGlobalScope):
+        (JSC::DebuggerScope::isFunctionOrEvalScope):
+        * debugger/DebuggerScope.h:
+        (JSC::DebuggerScope::create):
+        (JSC::DebuggerScope::createStructure):
+        (JSC::DebuggerScope::iterator::iterator):
+        (JSC::DebuggerScope::iterator::get):
+        (JSC::DebuggerScope::iterator::operator++):
+        (JSC::DebuggerScope::iterator::operator==):
+        (JSC::DebuggerScope::iterator::operator!=):
+        (JSC::DebuggerScope::isValid):
+        (JSC::DebuggerScope::jsScope):
+        (JSC::DebuggerScope::begin):
+        (JSC::DebuggerScope::end):
+        * inspector/JSJavaScriptCallFrame.cpp:
+        (Inspector::JSJavaScriptCallFrame::scopeType):
+        (Inspector::JSJavaScriptCallFrame::scopeChain):
+        * inspector/JavaScriptCallFrame.h:
+        (Inspector::JavaScriptCallFrame::scopeChain):
+        * inspector/ScriptDebugServer.cpp:
+        * runtime/JSActivation.h:
+        (JSC::JSActivation::createStructure):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::reset):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::debuggerScopeStructure):
+        * runtime/JSObject.cpp:
+        * runtime/JSObject.h:
+        (JSC::JSObject::isWithScope):
+        * runtime/JSScope.h:
+        * runtime/PropertySlot.h:
+        (JSC::PropertySlot::setThisValue):
+        * runtime/PutPropertySlot.h:
+        (JSC::PutPropertySlot::setThisValue):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
</ins><span class="cx"> 2014-08-28  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use JSString::toIdentifier() in more places.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class CodeBlock;
</ins><span class="cx"> class ExecState;
</span><span class="cx"> class JSGlobalObject;
</span><span class="cx"> class SourceProvider;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -30,12 +30,14 @@
</span><span class="cx"> #include &quot;DebuggerCallFrame.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><span class="cx"> #include &quot;StackVisitor.h&quot;
</span><ins>+#include &quot;StrongInlines.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -132,20 +134,25 @@
</span><span class="cx">     return getCalculatedDisplayName(m_callFrame, function);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSScope* DebuggerCallFrame::scope() const
</del><ins>+DebuggerScope* DebuggerCallFrame::scope()
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><del>-    CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
-    if (codeBlock &amp;&amp; codeBlock-&gt;needsActivation() &amp;&amp; !m_callFrame-&gt;hasActivation()) {
-        JSActivation* activation = JSActivation::create(*codeBlock-&gt;vm(), m_callFrame, codeBlock);
-        m_callFrame-&gt;setActivation(activation);
-        m_callFrame-&gt;setScope(activation);
</del><ins>+    if (!m_scope) {
+        VM&amp; vm = m_callFrame-&gt;vm();
+        CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
+        if (codeBlock &amp;&amp; codeBlock-&gt;needsActivation() &amp;&amp; !m_callFrame-&gt;hasActivation()) {
+            ASSERT(!m_callFrame-&gt;scope()-&gt;isWithScope());
+            JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock);
+            m_callFrame-&gt;setActivation(activation);
+            m_callFrame-&gt;setScope(activation);
+        }
+
+        m_scope.set(vm, DebuggerScope::create(vm, m_callFrame-&gt;scope()));
</ins><span class="cx">     }
</span><del>-
-    return m_callFrame-&gt;scope();
</del><ins>+    return m_scope.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DebuggerCallFrame::Type DebuggerCallFrame::type() const
</span><span class="lines">@@ -188,7 +195,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSValue thisValue = thisValueForCallFrame(callFrame);
</span><del>-    JSValue result = vm.interpreter-&gt;execute(eval, callFrame, thisValue, scope());
</del><ins>+    JSValue result = vm.interpreter-&gt;execute(eval, callFrame, thisValue, scope()-&gt;jsScope());
</ins><span class="cx">     if (vm.exception()) {
</span><span class="cx">         exception = vm.exception();
</span><span class="cx">         vm.clearException();
</span><span class="lines">@@ -200,6 +207,10 @@
</span><span class="cx"> void DebuggerCallFrame::invalidate()
</span><span class="cx"> {
</span><span class="cx">     m_callFrame = nullptr;
</span><ins>+    if (m_scope) {
+        m_scope-&gt;invalidateChain();
+        m_scope.clear();
+    }
</ins><span class="cx">     RefPtr&lt;DebuggerCallFrame&gt; frame = m_caller.release();
</span><span class="cx">     while (frame) {
</span><span class="cx">         frame-&gt;m_callFrame = nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -29,14 +29,18 @@
</span><span class="cx"> #ifndef DebuggerCallFrame_h
</span><span class="cx"> #define DebuggerCallFrame_h
</span><span class="cx"> 
</span><del>-#include &quot;CallFrame.h&quot;
</del><span class="cx"> #include &quot;DebuggerPrimitives.h&quot;
</span><ins>+#include &quot;Strong.h&quot;
</ins><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/text/TextPosition.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class DebuggerScope;
+class ExecState;
+typedef ExecState CallFrame;
+
</ins><span class="cx"> class DebuggerCallFrame : public RefCounted&lt;DebuggerCallFrame&gt; {
</span><span class="cx"> public:
</span><span class="cx">     enum Type { ProgramType, FunctionType };
</span><span class="lines">@@ -58,7 +62,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE const TextPosition&amp; position() const { return m_position; }
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const;
</span><del>-    JS_EXPORT_PRIVATE JSScope* scope() const;
</del><ins>+    JS_EXPORT_PRIVATE DebuggerScope* scope();
</ins><span class="cx">     JS_EXPORT_PRIVATE String functionName() const;
</span><span class="cx">     JS_EXPORT_PRIVATE Type type() const;
</span><span class="cx">     JS_EXPORT_PRIVATE JSValue thisValue() const;
</span><span class="lines">@@ -78,6 +82,9 @@
</span><span class="cx">     CallFrame* m_callFrame;
</span><span class="cx">     RefPtr&lt;DebuggerCallFrame&gt; m_caller;
</span><span class="cx">     TextPosition m_position;
</span><ins>+    // The DebuggerCallFrameScope is responsible for calling invalidate() which,
+    // in turn, will clear this strong ref.
+    Strong&lt;DebuggerScope&gt; m_scope;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;JSWithScope.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -35,17 +36,16 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo DebuggerScope::s_info = { &quot;DebuggerScope&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) };
</span><span class="cx"> 
</span><del>-DebuggerScope::DebuggerScope(VM&amp; vm)
-    : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
</del><ins>+DebuggerScope::DebuggerScope(VM&amp; vm, JSScope* scope)
+    : JSNonFinalObject(vm, scope-&gt;globalObject()-&gt;debuggerScopeStructure())
</ins><span class="cx"> {
</span><ins>+    ASSERT(scope);
+    m_scope.set(vm, this, scope);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DebuggerScope::finishCreation(VM&amp; vm, JSObject* activation)
</del><ins>+void DebuggerScope::finishCreation(VM&amp; vm)
</ins><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><del>-    ASSERT(activation);
-    ASSERT(activation-&gt;isActivationObject());
-    m_activation.set(vm, this, jsCast&lt;JSActivation*&gt;(activation));
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -53,43 +53,120 @@
</span><span class="cx">     DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(cell);
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx">     JSObject::visitChildren(thisObject, visitor);
</span><del>-    visitor.append(&amp;thisObject-&gt;m_activation);
</del><ins>+    visitor.append(&amp;thisObject-&gt;m_scope);
+    visitor.append(&amp;thisObject-&gt;m_next);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String DebuggerScope::className(const JSObject* object)
</span><span class="cx"> {
</span><del>-    const DebuggerScope* thisObject = jsCast&lt;const DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;className(thisObject-&gt;m_activation.get());
</del><ins>+    const DebuggerScope* scope = jsCast&lt;const DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return String();
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;className(thisObject);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;getOwnPropertySlot(thisObject-&gt;m_activation.get(), exec, propertyName, slot);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    slot.setThisValue(JSValue(thisObject));
+
+    // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype
+    // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden
+    // to behave differently for the DebuggerScope.
+    //
+    // Instead, we'll treat all properties in the wrapped scope and its prototype chain as
+    // the own properties of the DebuggerScope. This is fine because the WebInspector
+    // does not presently need to distinguish between what's owned at each level in the
+    // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here
+    // instead of getOwnPropertySlot().
+    return thisObject-&gt;getPropertySlot(exec, propertyName, slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&amp; slot)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(cell);
-    thisObject-&gt;m_activation-&gt;methodTable()-&gt;put(thisObject-&gt;m_activation.get(), exec, propertyName, value, slot);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(cell);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    slot.setThisValue(JSValue(thisObject));
+    thisObject-&gt;methodTable()-&gt;put(thisObject, exec, propertyName, value, slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(cell);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;deleteProperty(thisObject-&gt;m_activation.get(), exec, propertyName);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(cell);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;deleteProperty(thisObject, exec, propertyName);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    thisObject-&gt;m_activation-&gt;methodTable()-&gt;getPropertyNames(thisObject-&gt;m_activation.get(), exec, propertyNames, mode);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    thisObject-&gt;methodTable()-&gt;getPropertyNames(thisObject, exec, propertyNames, mode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor&amp; descriptor, bool shouldThrow)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;defineOwnProperty(thisObject-&gt;m_activation.get(), exec, propertyName, descriptor, shouldThrow);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+DebuggerScope* DebuggerScope::next()
+{
+    ASSERT(isValid());
+    if (!m_next &amp;&amp; m_scope-&gt;next()) {
+        VM&amp; vm = *m_scope-&gt;vm();
+        DebuggerScope* nextScope = create(vm, m_scope-&gt;next());
+        m_next.set(vm, this, nextScope);
+    }
+    return m_next.get();
+}
+
+void DebuggerScope::invalidateChain()
+{
+    DebuggerScope* scope = this;
+    while (scope) {
+        ASSERT(scope-&gt;isValid());
+        DebuggerScope* nextScope = scope-&gt;m_next.get();
+        scope-&gt;m_next.clear();
+        scope-&gt;m_scope.clear();
+        scope = nextScope;
+    }
+}
+
+bool DebuggerScope::isWithScope() const
+{
+    return m_scope-&gt;isWithScope();
+}
+
+bool DebuggerScope::isGlobalScope() const
+{
+    return m_scope-&gt;isGlobalObject();
+}
+
+bool DebuggerScope::isFunctionOrEvalScope() const
+{
+    // In the current debugger implementation, every function or eval will create an
+    // activation object. Hence, an activation object implies a function or eval scope.
+    return m_scope-&gt;isActivationObject();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerScope.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -30,15 +30,18 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class DebuggerCallFrame;
+class JSScope;
+
</ins><span class="cx"> class DebuggerScope : public JSNonFinalObject {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSNonFinalObject Base;
</span><span class="cx"> 
</span><del>-    static DebuggerScope* create(VM&amp; vm, JSObject* object)
</del><ins>+    static DebuggerScope* create(VM&amp; vm, JSScope* scope)
</ins><span class="cx">     {
</span><del>-        DebuggerScope* activation = new (NotNull, allocateCell&lt;DebuggerScope&gt;(vm.heap)) DebuggerScope(vm);
-        activation-&gt;finishCreation(vm, object);
-        return activation;
</del><ins>+        DebuggerScope* debuggerScope = new (NotNull, allocateCell&lt;DebuggerScope&gt;(vm.heap)) DebuggerScope(vm, scope);
+        debuggerScope-&gt;finishCreation(vm);
+        return debuggerScope;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="lines">@@ -51,21 +54,64 @@
</span><span class="cx"> 
</span><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="cx"> 
</span><del>-    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype) 
</del><ins>+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject) 
</ins><span class="cx">     {
</span><del>-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 
</del><ins>+        return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info()); 
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-protected:
-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
</del><ins>+    class iterator {
+    public:
+        iterator(DebuggerScope* node)
+            : m_node(node)
+        {
+        }
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void finishCreation(VM&amp;, JSObject* activation);
</del><ins>+        DebuggerScope* get() { return m_node; }
+        iterator&amp; operator++() { m_node = m_node-&gt;next(); return *this; }
+        // postfix ++ intentionally omitted
</ins><span class="cx"> 
</span><ins>+        bool operator==(const iterator&amp; other) const { return m_node == other.m_node; }
+        bool operator!=(const iterator&amp; other) const { return m_node != other.m_node; }
+
+    private:
+        DebuggerScope* m_node;
+    };
+
+    iterator begin();
+    iterator end();
+    DebuggerScope* next();
+
+    void invalidateChain();
+    bool isValid() const { return !!m_scope; }
+
+    bool isWithScope() const;
+    bool isGlobalScope() const;
+    bool isFunctionOrEvalScope() const;
+
</ins><span class="cx"> private:
</span><del>-    JS_EXPORT_PRIVATE DebuggerScope(VM&amp;);
-    WriteBarrier&lt;JSActivation&gt; m_activation;
</del><ins>+    JS_EXPORT_PRIVATE DebuggerScope(VM&amp;, JSScope*);
+    JS_EXPORT_PRIVATE void finishCreation(VM&amp;);
+
+    JSScope* jsScope() const { return m_scope.get(); }
+
+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+
+    WriteBarrier&lt;JSScope&gt; m_scope;
+    WriteBarrier&lt;DebuggerScope&gt; m_next;
+
+    friend class DebuggerCallFrame;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline DebuggerScope::iterator DebuggerScope::begin()
+{
+    return iterator(this); 
+}
+
+inline DebuggerScope::iterator DebuggerScope::end()
+{ 
+    return iterator(0); 
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // DebuggerScope_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INSPECTOR)
</span><span class="cx"> 
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Error.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSCellInlines.h&quot;
</span><span class="lines">@@ -95,29 +96,30 @@
</span><span class="cx">         return jsUndefined();
</span><span class="cx">     int index = exec-&gt;argument(0).asInt32();
</span><span class="cx"> 
</span><del>-    JSScope* scopeChain = impl().scopeChain();
-    ScopeChainIterator end = scopeChain-&gt;end();
</del><ins>+    DebuggerScope* scopeChain = impl().scopeChain();
+    DebuggerScope::iterator end = scopeChain-&gt;end();
</ins><span class="cx"> 
</span><del>-    // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
</del><ins>+    bool foundLocalScope = false;
+    for (DebuggerScope::iterator iter = scopeChain-&gt;begin(); iter != end; ++iter) {
+        DebuggerScope* scope = iter.get();
</ins><span class="cx"> 
</span><del>-    bool foundLocalScope = false;
-    for (ScopeChainIterator iter = scopeChain-&gt;begin(); iter != end; ++iter) {
-        JSObject* scope = iter.get();
-        if (scope-&gt;isActivationObject()) {
-            if (!foundLocalScope) {
-                // First activation object is local scope, each successive activation object is closure.
-                if (!index)
-                    return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
-                foundLocalScope = true;
-            } else if (!index)
-                return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
</del><ins>+        if (!foundLocalScope &amp;&amp; scope-&gt;isFunctionOrEvalScope()) {
+            // First function scope is the local scope, each successive one is a closure.
+            if (!index)
+                return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
+            foundLocalScope = true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!index) {
</span><del>-            // Last in the chain is global scope.
-            if (++iter == end)
</del><ins>+            if (scope-&gt;isWithScope())
+                return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
+            if (scope-&gt;isGlobalScope()) {
+                ASSERT(++iter == end);
</ins><span class="cx">                 return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
</span><del>-            return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
</del><ins>+            }
+            // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
+            ASSERT(scope-&gt;isFunctionOrEvalScope());
+            return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         --index;
</span><span class="lines">@@ -157,9 +159,9 @@
</span><span class="cx">     if (!impl().scopeChain())
</span><span class="cx">         return jsNull();
</span><span class="cx"> 
</span><del>-    JSScope* scopeChain = impl().scopeChain();
-    ScopeChainIterator iter = scopeChain-&gt;begin();
-    ScopeChainIterator end = scopeChain-&gt;end();
</del><ins>+    DebuggerScope* scopeChain = impl().scopeChain();
+    DebuggerScope::iterator iter = scopeChain-&gt;begin();
+    DebuggerScope::iterator end = scopeChain-&gt;end();
</ins><span class="cx"> 
</span><span class="cx">     // We must always have something in the scope chain.
</span><span class="cx">     ASSERT(iter != end);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> 
</span><span class="cx">     String functionName() const { return m_debuggerCallFrame-&gt;functionName(); }
</span><span class="cx">     JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame-&gt;type(); }
</span><del>-    JSC::JSScope* scopeChain() const { return m_debuggerCallFrame-&gt;scope(); }
</del><ins>+    JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame-&gt;scope(); }
</ins><span class="cx">     JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame-&gt;vmEntryGlobalObject(); }
</span><span class="cx"> 
</span><span class="cx">     JSC::JSValue thisValue() const { return m_debuggerCallFrame-&gt;thisValue(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorScriptDebugServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #if ENABLE(INSPECTOR)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DebuggerCallFrame.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;JSJavaScriptCallFrame.h&quot;
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="cx"> #include &quot;JavaScriptCallFrame.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSActivationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSActivation.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSActivation.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSActivation.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx">         
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><del>-    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), info()); }
</del><ins>+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject) { return Structure::create(vm, globalObject, jsNull(), TypeInfo(ActivationObjectType, StructureFlags), info()); }
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrierBase&lt;Unknown&gt;&amp; registerAt(int) const;
</span><span class="cx">     bool isValidIndex(int) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;DateConstructor.h&quot;
</span><span class="cx"> #include &quot;DatePrototype.h&quot;
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Error.h&quot;
</span><span class="cx"> #include &quot;ErrorConstructor.h&quot;
</span><span class="cx"> #include &quot;ErrorPrototype.h&quot;
</span><span class="lines">@@ -318,8 +319,9 @@
</span><span class="cx">     m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get()));
</span><span class="cx"> 
</span><span class="cx">     m_nameScopeStructure.set(vm, this, JSNameScope::createStructure(vm, this, jsNull()));
</span><del>-    m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull()));
</del><ins>+    m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this));
</ins><span class="cx">     m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
</span><ins>+    m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this));
</ins><span class="cx">     m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
</span><span class="cx"> 
</span><span class="cx">     m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
</span><span class="lines">@@ -662,6 +664,7 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_promisePrototype);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    visitor.append(&amp;thisObject-&gt;m_debuggerScopeStructure);
</ins><span class="cx">     visitor.append(&amp;thisObject-&gt;m_withScopeStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_strictEvalActivationStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_activationStructure);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -186,6 +186,7 @@
</span><span class="cx">     WriteBarrier&lt;JSPromisePrototype&gt; m_promisePrototype;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    WriteBarrier&lt;Structure&gt; m_debuggerScopeStructure;
</ins><span class="cx">     WriteBarrier&lt;Structure&gt; m_withScopeStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_strictEvalActivationStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_activationStructure;
</span><span class="lines">@@ -391,6 +392,7 @@
</span><span class="cx">     JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); }
</ins><span class="cx">     Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
</span><span class="cx">     Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
</span><span class="cx">     Structure* activationStructure() const { return m_activationStructure.get(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -2782,5 +2782,4 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -594,6 +594,7 @@
</span><span class="cx">     bool isNameScopeObject() const;
</span><span class="cx">     bool isActivationObject() const;
</span><span class="cx">     bool isErrorInstance() const;
</span><ins>+    bool isWithScope() const;
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void seal(VM&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE void freeze(VM&amp;);
</span><span class="lines">@@ -1150,6 +1151,11 @@
</span><span class="cx">     return type() == ErrorInstanceType;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool JSObject::isWithScope() const
+{
+    return type() == WithScopeType;
+}
+
</ins><span class="cx"> inline void JSObject::setStructureAndButterfly(VM&amp; vm, Structure* structure, Butterfly* butterfly)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(structure);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSScope.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSScope.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/JSScope.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx">     static size_t offsetOfNext();
</span><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
</del><ins>+    static JSObject* objectAtScope(JSScope*);
</ins><span class="cx"> 
</span><span class="cx">     static JSValue resolve(ExecState*, JSScope*, const Identifier&amp;);
</span><span class="cx">     static ResolveOp abstractResolve(ExecState*, bool hasTopActivation, JSScope*, const Identifier&amp;, GetOrPut, ResolveType);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimePropertySloth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/PropertySlot.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/PropertySlot.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/PropertySlot.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -204,6 +204,11 @@
</span><span class="cx">         m_offset = offset;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void setThisValue(JSValue thisValue)
+    {
+        m_thisValue = thisValue;
+    }
+
</ins><span class="cx">     void setUndefined()
</span><span class="cx">     {
</span><span class="cx">         m_data.value = JSValue::encode(jsUndefined());
</span><span class="lines">@@ -235,7 +240,7 @@
</span><span class="cx"> 
</span><span class="cx">     PropertyType m_propertyType;
</span><span class="cx">     PropertyOffset m_offset;
</span><del>-    const JSValue m_thisValue;
</del><ins>+    JSValue m_thisValue;
</ins><span class="cx">     JSObject* m_slotBase;
</span><span class="cx">     WatchpointSet* m_watchpointSet;
</span><span class="cx">     CacheabilityType m_cacheability;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimePutPropertySloth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/PutPropertySlot.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/PutPropertySlot.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/PutPropertySlot.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -80,6 +80,11 @@
</span><span class="cx">             m_offset = offset;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        void setThisValue(JSValue thisValue)
+        {
+            m_thisValue = thisValue;
+        }
+
</ins><span class="cx">         PutValueFunc customSetter() const { return m_putFunction; }
</span><span class="cx"> 
</span><span class="cx">         Context context() const { return static_cast&lt;Context&gt;(m_context); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -40,7 +40,6 @@
</span><span class="cx"> #include &quot;CustomGetterSetter.h&quot;
</span><span class="cx"> #include &quot;DFGLongLivedState.h&quot;
</span><span class="cx"> #include &quot;DFGWorklist.h&quot;
</span><del>-#include &quot;DebuggerScope.h&quot;
</del><span class="cx"> #include &quot;ErrorInstance.h&quot;
</span><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;FunctionConstructor.h&quot;
</span><span class="lines">@@ -209,7 +208,6 @@
</span><span class="cx">     propertyNames = new CommonIdentifiers(this);
</span><span class="cx">     structureStructure.set(*this, Structure::createStructure(*this));
</span><span class="cx">     structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
</span><del>-    debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull()));
</del><span class="cx">     terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
</span><span class="cx">     stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
</span><span class="cx">     notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -246,7 +246,6 @@
</span><span class="cx"> 
</span><span class="cx">         Strong&lt;Structure&gt; structureStructure;
</span><span class="cx">         Strong&lt;Structure&gt; structureRareDataStructure;
</span><del>-        Strong&lt;Structure&gt; debuggerScopeStructure;
</del><span class="cx">         Strong&lt;Structure&gt; terminatedExecutionErrorStructure;
</span><span class="cx">         Strong&lt;Structure&gt; stringStructure;
</span><span class="cx">         Strong&lt;Structure&gt; notAnObjectStructure;
</span></span></pre></div>
<a id="trunkSourceWebCore"></a>
<div class="propset"><h4>Property changes: trunk/Source/WebCore</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4>Modified: svn:mergeinfo</h4></div>
<span class="cx">   + /branches/ftlopt/Source/WebCore:170680
</span><span class="cx">/trunk/WebCore:53455
</span><a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/WebCore/ChangeLog        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2014-08-28  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        DebuggerCallFrame::scope() should return a DebuggerScope.
+        &lt;https://webkit.org/b/134420&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests.
+
+        Rolling back in r170680 with the fix for &lt;https://webkit.org/b/135656&gt;.
+
+        * bindings/js/ScriptController.cpp:
+        (WebCore::ScriptController::attachDebugger):
+        - We should acquire the JSLock before modifying a JS global object.
+
</ins><span class="cx"> 2014-08-28  Enrica Casucci  &lt;enrica@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Can't hit tab key more than 3 times continuously.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsScriptControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/ScriptController.cpp (173099 => 173100)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/ScriptController.cpp        2014-08-29 00:35:00 UTC (rev 173099)
+++ trunk/Source/WebCore/bindings/js/ScriptController.cpp        2014-08-29 00:48:59 UTC (rev 173100)
</span><span class="lines">@@ -307,6 +307,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     JSDOMWindow* globalObject = shell-&gt;window();
</span><ins>+    JSLockHolder lock(globalObject-&gt;vm());
</ins><span class="cx">     if (debugger)
</span><span class="cx">         debugger-&gt;attach(globalObject);
</span><span class="cx">     else if (JSC::Debugger* currentDebugger = globalObject-&gt;debugger())
</span></span></pre>
</div>
</div>

</body>
</html>