<!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>[202710] trunk/Source/JavaScriptCore</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/202710">202710</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-06-30 15:06:44 -0700 (Thu, 30 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>get_by_id_with_this does not trigger a to_this in caller.
https://bugs.webkit.org/show_bug.cgi?id=159226

Reviewed by Keith Miller.

This is a bug if the caller is in sloppy mode and the callee is in strict
mode. This can't happen with ES6 classes because they're all in strict mode,
but it can happen with method syntax on an object literal. The caller must
to_this on |this| when it knows that it performs super property accesses.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* tests/stress/super-property-access-object-literal-to-this-2.js: Added.
(assert):
(test):
(let.o1.get foo):
(let.o2.a):
(let.o2.aa):
* tests/stress/super-property-access-object-literal-to-this.js: Added.
(assert):
(test):
(let.o1.get foo):
(let.o2.a):
(let.o2.aa):
(let.o2.b):
(let.o2.bb):
* tests/stress/super-property-access-to-this.js: Added.
(assert):
(test):
(Base.prototype.get foo):
(Base):
(Child.prototype.a):
(Child.prototype.b):
(Child):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresssuperpropertyaccessobjectliteraltothis2js">trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this-2.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssuperpropertyaccessobjectliteraltothisjs">trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssuperpropertyaccesstothisjs">trunk/Source/JavaScriptCore/tests/stress/super-property-access-to-this.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202709 => 202710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-30 21:50:40 UTC (rev 202709)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-30 22:06:44 UTC (rev 202710)
</span><span class="lines">@@ -1,5 +1,42 @@
</span><span class="cx"> 2016-06-30  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        get_by_id_with_this does not trigger a to_this in caller.
+        https://bugs.webkit.org/show_bug.cgi?id=159226
+
+        Reviewed by Keith Miller.
+
+        This is a bug if the caller is in sloppy mode and the callee is in strict
+        mode. This can't happen with ES6 classes because they're all in strict mode,
+        but it can happen with method syntax on an object literal. The caller must
+        to_this on |this| when it knows that it performs super property accesses.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * tests/stress/super-property-access-object-literal-to-this-2.js: Added.
+        (assert):
+        (test):
+        (let.o1.get foo):
+        (let.o2.a):
+        (let.o2.aa):
+        * tests/stress/super-property-access-object-literal-to-this.js: Added.
+        (assert):
+        (test):
+        (let.o1.get foo):
+        (let.o2.a):
+        (let.o2.aa):
+        (let.o2.b):
+        (let.o2.bb):
+        * tests/stress/super-property-access-to-this.js: Added.
+        (assert):
+        (test):
+        (Base.prototype.get foo):
+        (Base):
+        (Child.prototype.a):
+        (Child.prototype.b):
+        (Child):
+
+2016-06-30  Saam Barati  &lt;sbarati@apple.com&gt;
+
</ins><span class="cx">         We need to to_this when an inner arrow function uses 'this'
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=159290
</span><span class="cx">         &lt;rdar://problem/27058322&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (202709 => 202710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-06-30 21:50:40 UTC (rev 202709)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-06-30 22:06:44 UTC (rev 202710)
</span><span class="lines">@@ -549,14 +549,34 @@
</span><span class="cx">                     emitMoveEmptyValue(&amp;m_thisRegister);
</span><span class="cx">                 else
</span><span class="cx">                     emitCreateThis(&amp;m_thisRegister);
</span><del>-            } else if (constructorKind() != ConstructorKind::None) {
</del><ins>+            } else if (constructorKind() != ConstructorKind::None)
</ins><span class="cx">                 emitThrowTypeError(&quot;Cannot call a class constructor&quot;);
</span><del>-            } else if (functionNode-&gt;usesThis() || codeBlock-&gt;usesEval() || isThisUsedInInnerArrowFunction()) {
-                m_codeBlock-&gt;addPropertyAccessInstruction(instructions().size());
-                emitOpcode(op_to_this);
-                instructions().append(kill(&amp;m_thisRegister));
-                instructions().append(0);
-                instructions().append(0);
</del><ins>+            else {
+                bool shouldEmitToThis = false;
+                if (functionNode-&gt;usesThis() || codeBlock-&gt;usesEval() || m_scopeNode-&gt;doAnyInnerArrowFunctionsUseThis() || m_scopeNode-&gt;doAnyInnerArrowFunctionsUseEval())
+                    shouldEmitToThis = true;
+                else if ((functionNode-&gt;usesSuperProperty() || m_scopeNode-&gt;doAnyInnerArrowFunctionsUseSuperProperty()) &amp;&amp; !codeBlock-&gt;isStrictMode()) {
+                    // We must emit to_this when we're not in strict mode because we
+                    // will convert |this| to an object, and that object may be passed
+                    // to a strict function as |this|. This is observable because that
+                    // strict function's to_this will just return the object.
+                    //
+                    // We don't need to emit this for strict-mode code because
+                    // strict-mode code may call another strict function, which will
+                    // to_this if it directly uses this; this is OK, because we defer
+                    // to_this until |this| is used directly. Strict-mode code might
+                    // also call a sloppy mode function, and that will to_this, which
+                    // will defer the conversion, again, until necessary.
+                    shouldEmitToThis = true;
+                }
+
+                if (shouldEmitToThis) {
+                    m_codeBlock-&gt;addPropertyAccessInstruction(instructions().size());
+                    emitOpcode(op_to_this);
+                    instructions().append(kill(&amp;m_thisRegister));
+                    instructions().append(0);
+                    instructions().append(0);
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssuperpropertyaccessobjectliteraltothis2js"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this-2.js (0 => 202710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this-2.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this-2.js        2016-06-30 22:06:44 UTC (rev 202710)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+
+function test(f, n = 1000) {
+    for (let i = 0; i &lt; n; ++i)
+        f();
+}
+
+let o1 = {
+    get foo() {
+        return this;
+    }
+};
+
+let o2 = {
+    __proto__: o1,
+    a() {
+        &quot;use strict&quot;;
+        return super.foo;
+    },
+
+    aa() {
+        &quot;use strict&quot;;
+        let arr = () =&gt; super.foo;
+        return arr();
+    }
+};
+
+var A = o2.a;
+var AA = o2.aa;
+
+let globalObj = this;
+
+AA();
+
+test(function() {
+    let num = o2.a.call(25);
+    assert(typeof num === &quot;object&quot;);
+    assert(num instanceof Number);
+
+    let str = o2.a.call(&quot;foo bar&quot;);
+    assert(typeof str === &quot;object&quot;);
+    assert(str instanceof String);
+    assert(str == &quot;foo bar&quot;);
+
+    let o = {};
+    assert(o2.a.call(o) === o);
+
+    assert(A() === globalObj);
+    assert(AA() === globalObj);
+
+    assert(o2.a.call(undefined) === globalObj);
+    assert(o2.a.call(null) === globalObj);
+    assert(o2.aa.call(undefined) === globalObj);
+    assert(o2.aa.call(null) === globalObj);
+});
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssuperpropertyaccessobjectliteraltothisjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this.js (0 => 202710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/super-property-access-object-literal-to-this.js        2016-06-30 22:06:44 UTC (rev 202710)
</span><span class="lines">@@ -0,0 +1,108 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+
+function test(f, n = 1000) {
+    for (let i = 0; i &lt; n; ++i)
+        f();
+}
+
+let o1 = {
+    get foo() {
+        &quot;use strict&quot;;
+        return this;
+    }
+};
+
+let o2 = {
+    __proto__: o1,
+    a() {
+        return super.foo;
+    },
+
+    aa() {
+        let arr = () =&gt; super.foo;
+        return arr();
+    },
+
+    b() {
+        &quot;use strict&quot;;
+        return super.foo;
+    },
+
+    bb() {
+        &quot;use strict&quot;;
+        let arr = () =&gt; super.foo;
+        return arr();
+    }
+};
+
+var A = o2.a;
+var AA = o2.aa;
+var B = o2.b;
+var BB = o2.b;
+
+let globalObj = this;
+
+test(function() {
+    let num = o2.a.call(25);
+    assert(typeof num === &quot;object&quot;);
+    assert(num instanceof Number);
+
+    let str = o2.a.call(&quot;foo bar&quot;);
+    assert(typeof str === &quot;object&quot;);
+    assert(str instanceof String);
+    assert(str == &quot;foo bar&quot;);
+
+    let o = {};
+    assert(o2.a.call(o) === o);
+
+    assert(A() === globalObj);
+});
+
+test(function() {
+    let num = o2.aa.call(25);
+    assert(typeof num === &quot;object&quot;);
+    assert(num instanceof Number);
+
+    let str = o2.aa.call(&quot;foo bar&quot;);
+    assert(typeof str === &quot;object&quot;);
+    assert(str instanceof String);
+    assert(str == &quot;foo bar&quot;);
+
+    let o = {};
+    assert(o2.aa.call(o) === o);
+
+    assert(AA() === globalObj);
+});
+
+test(function() {
+    let num = o2.b.call(25);
+    assert(typeof num === &quot;number&quot;);
+    assert(num === 25);
+
+    let str = o2.b.call(&quot;foo bar&quot;);
+    assert(typeof str === &quot;string&quot;);
+    assert(str === &quot;foo bar&quot;);
+
+    let o = {};
+    assert(o2.b.call(o) === o);
+
+    assert(B() === undefined);
+});
+
+test(function() {
+    let num = o2.bb.call(25);
+    assert(typeof num === &quot;number&quot;);
+    assert(num === 25);
+
+    let str = o2.bb.call(&quot;foo bar&quot;);
+    assert(typeof str === &quot;string&quot;);
+    assert(str === &quot;foo bar&quot;);
+
+    let o = {};
+    assert(o2.bb.call(o) === o);
+
+    assert(BB() === undefined);
+});
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssuperpropertyaccesstothisjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/super-property-access-to-this.js (0 => 202710)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/super-property-access-to-this.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/super-property-access-to-this.js        2016-06-30 22:06:44 UTC (rev 202710)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+&quot;use strict&quot;;
+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+
+function test(f, n = 1000) {
+    for (let i = 0; i &lt; n; ++i)
+        f();
+}
+
+class Base {
+    get foo() { return this; }
+}
+
+class Child extends Base {
+    a() {
+        return super.foo;
+    }
+
+    b() {
+        let arr = () =&gt; super.foo;
+        return arr();
+    }
+};
+
+let A = Child.prototype.a;
+var AA = Child.prototype.a;
+this.AAA = Child.prototype.a;
+
+let globalObj = this;
+
+test(function() {
+    assert(Child.prototype.a.call(&quot;xyz&quot;) === &quot;xyz&quot;);
+    let obj = {};
+    assert(Child.prototype.a.call(obj) === obj);
+    assert(Child.prototype.a.call(25) === 25);
+    assert(Child.prototype.a.call(globalObj) === globalObj);
+
+    assert(Child.prototype.b.call(&quot;xyz&quot;) === &quot;xyz&quot;);
+    assert(Child.prototype.b.call(obj) === obj);
+    assert(Child.prototype.b.call(25) === 25);
+    assert(Child.prototype.b.call(globalObj) === globalObj);
+
+    assert(A() === undefined);
+    assert(AA() === undefined);
+    assert(AAA() === undefined);
+});
</ins></span></pre>
</div>
</div>

</body>
</html>