<!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>[202982] 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/202982">202982</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-07-08 09:27:35 -0700 (Fri, 08 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>TypedArrays need more isNeutered checks.
https://bugs.webkit.org/show_bug.cgi?id=159231

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

According to the ES6 spec if a user tries to get, set, or define a
property on a neutered TypedArray we should throw an
exception. Currently, if a user tries to get an out of bounds
access on a TypedArray we will always OSR.  This makes handling
the exception easy as all we need to do is make out of bounds gets
in PolymorphicAccess go to the slow path, which will then throw
the appropriate exception. For the case of set, we need ensure we
don't OSR on each out of bounds put since, for some confusing
reason, people do this.  Thus, for GetByVal in the DFG/FTL if the
user accesses out of bounds we then need to check if the view has
been neutered. If it is neutered then we will OSR.

Additionally, this patch adds a bunch of isNeutered checks to
various prototype functions for TypedArray, which are needed for
correctness.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
* dfg/DFGSpeculativeJIT.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
(JSC::FTL::DFG::LowerDFGToB3::speculateTypedArrayIsNotNeutered):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitIntTypedArrayPutByVal):
(JSC::JIT::emitFloatTypedArrayPutByVal):
* runtime/JSArrayBufferView.h:
* runtime/JSCJSValue.h:
(JSC::encodedJSUndefined):
(JSC::encodedJSValue):
* runtime/JSGenericTypedArrayView.h:
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::throwNeuteredTypedArrayTypeError):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnPropertySlot):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::put):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::defineOwnProperty):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::deleteProperty):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnPropertySlotByIndex):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::putByIndex):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::deletePropertyByIndex):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoFuncCopyWithin):
(JSC::genericTypedArrayViewProtoFuncFill):
(JSC::genericTypedArrayViewProtoFuncIndexOf):
(JSC::genericTypedArrayViewProtoFuncJoin):
(JSC::genericTypedArrayViewProtoFuncLastIndexOf):
(JSC::genericTypedArrayViewProtoFuncSlice):
(JSC::genericTypedArrayViewProtoFuncSubarray):
* tests/stress/fold-typed-array-properties.js:
* tests/stress/typedarray-access-monomorphic-neutered.js: Added.
(check):
(test):
(testFTL):
* tests/stress/typedarray-access-neutered.js: Added.
(check):
(test):
* tests/stress/typedarray-functions-with-neutered.js:
(defaultForArg):
(callWithArgs):
(checkArgumentsForType):
(checkArguments):
* tests/stress/typedarray-view-string-properties-neutered.js: Added.
(call):
(test):

LayoutTests:

Update tests that assert that we can access indexed properties on
a neutered TypedArray.

* fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js:
(assertViewClosed):
* js/dom/dfg-typed-array-neuter-expected.txt:
* js/dom/script-tests/dfg-typed-array-neuter.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcanvaswebglscripttestsarraybuffertransferofcontroljs">trunk/LayoutTests/fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js</a></li>
<li><a href="#trunkLayoutTestsjsdomdfgtypedarrayneuterexpectedtxt">trunk/LayoutTests/js/dom/dfg-typed-array-neuter-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsdomscripttestsdfgtypedarrayneuterjs">trunk/LayoutTests/js/dom/script-tests/dfg-typed-array-neuter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh">trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewPrototypeFunctionsh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressfoldtypedarraypropertiesjs">trunk/Source/JavaScriptCore/tests/stress/fold-typed-array-properties.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayfunctionswithneuteredjs">trunk/Source/JavaScriptCore/tests/stress/typedarray-functions-with-neutered.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayaccessmonomorphicneuteredjs">trunk/Source/JavaScriptCore/tests/stress/typedarray-access-monomorphic-neutered.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayaccessneuteredjs">trunk/Source/JavaScriptCore/tests/stress/typedarray-access-neutered.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayviewstringpropertiesneuteredjs">trunk/Source/JavaScriptCore/tests/stress/typedarray-view-string-properties-neutered.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/LayoutTests/ChangeLog        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-07-08  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        TypedArrays need more isNeutered checks.
+        https://bugs.webkit.org/show_bug.cgi?id=159231
+
+        Reviewed by Filip Pizlo.
+
+        Update tests that assert that we can access indexed properties on
+        a neutered TypedArray.
+
+        * fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js:
+        (assertViewClosed):
+        * js/dom/dfg-typed-array-neuter-expected.txt:
+        * js/dom/script-tests/dfg-typed-array-neuter.js:
+
</ins><span class="cx"> 2016-07-08  Frederic Wang  &lt;fwang@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use Fraction* parameters from the OpenType MATH table
</span></span></pre></div>
<a id="trunkLayoutTestsfastcanvaswebglscripttestsarraybuffertransferofcontroljs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/LayoutTests/fast/canvas/webgl/script-tests/arraybuffer-transfer-of-control.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -91,35 +91,36 @@
</span><span class="cx">             }
</span><span class="cx">             try {
</span><span class="cx">                 var v = view[0];
</span><del>-                if (v !== undefined) {
-                    testFailed(testName + &quot;: index get on a closed view did not return undefined.&quot;);
</del><ins>+                testFailed(testName + &quot;: index get on a closed view did not throw an exception&quot;);
+                return false;
+            } catch(xn) {
+                if (xn != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;) {
+                    testFailed(testName + &quot;: index get on a closed view threw the wrong exception: &quot; + xn);
</ins><span class="cx">                     return false;
</span><span class="cx">                 }
</span><del>-            } catch(xn) {
-                testFailed(testName + &quot;: index get on a closed view threw an exception: &quot; + xn);
-                return false;
</del><span class="cx">             }
</span><ins>+
</ins><span class="cx">             try {
</span><span class="cx">                 view[0] = 42;
</span><del>-                var v = view[0];
-                if (v !== undefined) {
-                    testFailed(testName + &quot;: index set then get on a closed view did not return undefined.&quot;);
</del><ins>+                testFailed(testName + &quot;: index set on a closed view did not throw an exception&quot;);
+                return false;
+            } catch(xn) {
+                if (xn != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;) {
+                    testFailed(testName + &quot;: index set then get on a closed view threw the wrong exception: &quot; + xn);
</ins><span class="cx">                     return false;
</span><span class="cx">                 }
</span><del>-            } catch(xn) {
-                testFailed(testName + &quot;: index set then get on a closed view threw an exception: &quot; + xn);
-                return false;
</del><span class="cx">             }
</span><ins>+
</ins><span class="cx">             try {
</span><del>-                view.get(0);
-                testFailed(testName + &quot;: get on a closed view succeeded&quot;);
-                return false;
-            } catch (xn) { }
-            try {
</del><span class="cx">                 view.set(0, 1);
</span><span class="cx">                 testFailed(testName + &quot;: set on a closed view succeeded&quot;);
</span><span class="cx">                 return false;
</span><del>-            } catch (xn) { }
</del><ins>+            } catch (xn) {
+                if (xn != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;) {
+                    testFailed(testName + &quot;: set on a closed view threw the wrong exception: &quot; + xn);
+                    return false;
+                }
+            }
</ins><span class="cx">         } else {
</span><span class="cx">             try {
</span><span class="cx">                 view.getInt8(0);
</span></span></pre></div>
<a id="trunkLayoutTestsjsdomdfgtypedarrayneuterexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/dom/dfg-typed-array-neuter-expected.txt (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/dom/dfg-typed-array-neuter-expected.txt        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/LayoutTests/js/dom/dfg-typed-array-neuter-expected.txt        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -8,9 +8,9 @@
</span><span class="cx"> PASS foo(array) is 100
</span><span class="cx"> PASS bar(array) is 42
</span><span class="cx"> PASS array.length is 0
</span><del>-PASS array[0] is void 0
</del><ins>+PASS array[0] threw exception TypeError: Underlying ArrayBuffer has been detached from the view.
</ins><span class="cx"> PASS foo(array) is 0
</span><del>-PASS bar(array) is void 0
</del><ins>+PASS bar(array) threw exception TypeError: Underlying ArrayBuffer has been detached from the view.
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsjsdomscripttestsdfgtypedarrayneuterjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/dom/script-tests/dfg-typed-array-neuter.js (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/dom/script-tests/dfg-typed-array-neuter.js        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/LayoutTests/js/dom/script-tests/dfg-typed-array-neuter.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> window.postMessage(array, &quot;*&quot;, [array.buffer]);
</span><span class="cx"> 
</span><span class="cx"> shouldBe(&quot;array.length&quot;, &quot;0&quot;);
</span><del>-shouldBe(&quot;array[0]&quot;, &quot;void 0&quot;);
</del><ins>+shouldThrow(&quot;array[0]&quot;);
</ins><span class="cx"> 
</span><span class="cx"> shouldBe(&quot;foo(array)&quot;, &quot;0&quot;);
</span><del>-shouldBe(&quot;bar(array)&quot;, &quot;void 0&quot;);
</del><ins>+shouldThrow(&quot;bar(array)&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -1,3 +1,76 @@
</span><ins>+2016-07-08  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        TypedArrays need more isNeutered checks.
+        https://bugs.webkit.org/show_bug.cgi?id=159231
+
+        Reviewed by Filip Pizlo.
+
+        According to the ES6 spec if a user tries to get, set, or define a
+        property on a neutered TypedArray we should throw an
+        exception. Currently, if a user tries to get an out of bounds
+        access on a TypedArray we will always OSR.  This makes handling
+        the exception easy as all we need to do is make out of bounds gets
+        in PolymorphicAccess go to the slow path, which will then throw
+        the appropriate exception. For the case of set, we need ensure we
+        don't OSR on each out of bounds put since, for some confusing
+        reason, people do this.  Thus, for GetByVal in the DFG/FTL if the
+        user accesses out of bounds we then need to check if the view has
+        been neutered. If it is neutered then we will OSR.
+
+        Additionally, this patch adds a bunch of isNeutered checks to
+        various prototype functions for TypedArray, which are needed for
+        correctness.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
+        * dfg/DFGSpeculativeJIT.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
+        (JSC::FTL::DFG::LowerDFGToB3::speculateTypedArrayIsNotNeutered):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitIntTypedArrayPutByVal):
+        (JSC::JIT::emitFloatTypedArrayPutByVal):
+        * runtime/JSArrayBufferView.h:
+        * runtime/JSCJSValue.h:
+        (JSC::encodedJSUndefined):
+        (JSC::encodedJSValue):
+        * runtime/JSGenericTypedArrayView.h:
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::throwNeuteredTypedArrayTypeError):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnPropertySlot):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::put):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::defineOwnProperty):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::deleteProperty):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnPropertySlotByIndex):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::putByIndex):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::deletePropertyByIndex):
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::genericTypedArrayViewProtoFuncCopyWithin):
+        (JSC::genericTypedArrayViewProtoFuncFill):
+        (JSC::genericTypedArrayViewProtoFuncIndexOf):
+        (JSC::genericTypedArrayViewProtoFuncJoin):
+        (JSC::genericTypedArrayViewProtoFuncLastIndexOf):
+        (JSC::genericTypedArrayViewProtoFuncSlice):
+        (JSC::genericTypedArrayViewProtoFuncSubarray):
+        * tests/stress/fold-typed-array-properties.js:
+        * tests/stress/typedarray-access-monomorphic-neutered.js: Added.
+        (check):
+        (test):
+        (testFTL):
+        * tests/stress/typedarray-access-neutered.js: Added.
+        (check):
+        (test):
+        * tests/stress/typedarray-functions-with-neutered.js:
+        (defaultForArg):
+        (callWithArgs):
+        (checkArgumentsForType):
+        (checkArguments):
+        * tests/stress/typedarray-view-string-properties-neutered.js: Added.
+        (call):
+        (test):
+
</ins><span class="cx"> 2016-07-08  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Generate WebCore builtin wrapper files
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -2613,6 +2613,31 @@
</span><span class="cx">     speculationCheck(OutOfBounds, JSValueRegs(), 0, jump);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds(Node* node, GPRReg base, JITCompiler::Jump outOfBounds)
+{
+    JITCompiler::Jump done;
+    if (outOfBounds.isSet()) {
+        done = m_jit.jump();
+        if (node-&gt;arrayMode().isInBounds())
+            speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
+        else {
+            outOfBounds.link(&amp;m_jit);
+
+            JITCompiler::Jump notWasteful = m_jit.branch32(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(base, JSArrayBufferView::offsetOfMode()),
+                TrustedImm32(WastefulTypedArray));
+
+            JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
+                MacroAssembler::Zero,
+                MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
+            speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
+            notWasteful.link(&amp;m_jit);
+        }
+    }
+    return done;
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isInt(type));
</span><span class="lines">@@ -2790,11 +2815,7 @@
</span><span class="cx">     ASSERT_UNUSED(valueGPR, valueGPR != property);
</span><span class="cx">     ASSERT(valueGPR != base);
</span><span class="cx">     ASSERT(valueGPR != storageReg);
</span><del>-    MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
-    if (node-&gt;arrayMode().isInBounds() &amp;&amp; outOfBounds.isSet()) {
-        speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
-        outOfBounds = MacroAssembler::Jump();
-    }
</del><ins>+    JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
</ins><span class="cx"> 
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 1:
</span><span class="lines">@@ -2809,8 +2830,10 @@
</span><span class="cx">     default:
</span><span class="cx">         CRASH();
</span><span class="cx">     }
</span><del>-    if (outOfBounds.isSet())
-        outOfBounds.link(&amp;m_jit);
</del><ins>+
+    JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
+    if (done.isSet())
+        done.link(&amp;m_jit);
</ins><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2865,10 +2888,6 @@
</span><span class="cx">     ASSERT_UNUSED(baseUse, node-&gt;arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(baseUse)));
</span><span class="cx">     
</span><span class="cx">     MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
</span><del>-    if (node-&gt;arrayMode().isInBounds() &amp;&amp; outOfBounds.isSet()) {
-        speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
-        outOfBounds = MacroAssembler::Jump();
-    }
</del><span class="cx">     
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 4: {
</span><span class="lines">@@ -2883,8 +2902,10 @@
</span><span class="cx">     default:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><del>-    if (outOfBounds.isSet())
-        outOfBounds.link(&amp;m_jit);
</del><ins>+
+    JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
+    if (done.isSet())
+        done.link(&amp;m_jit);
</ins><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -2521,6 +2521,7 @@
</span><span class="cx">     void compileConstantStoragePointer(Node*);
</span><span class="cx">     void compileGetIndexedPropertyStorage(Node*);
</span><span class="cx">     JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
</span><ins>+    JITCompiler::Jump jumpForTypedArrayIsNeuteredIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
</ins><span class="cx">     void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
</span><span class="cx">     void compileGetTypedArrayByteOffset(Node*);
</span><span class="cx">     void compileGetByValOnIntTypedArray(Node*, TypedArrayType);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -3317,20 +3317,25 @@
</span><span class="cx">                         DFG_CRASH(m_graph, m_node, &quot;Bad typed array type&quot;);
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><del>-                
</del><ins>+
</ins><span class="cx">                 if (m_node-&gt;arrayMode().isInBounds() || m_node-&gt;op() == PutByValAlias)
</span><span class="cx">                     m_out.store(valueToStore, pointer, storeType);
</span><span class="cx">                 else {
</span><span class="cx">                     LBasicBlock isInBounds = m_out.newBlock();
</span><ins>+                    LBasicBlock isOutOfBounds = m_out.newBlock();
</ins><span class="cx">                     LBasicBlock continuation = m_out.newBlock();
</span><span class="cx">                     
</span><span class="cx">                     m_out.branch(
</span><span class="cx">                         m_out.aboveOrEqual(index, lowInt32(child5)),
</span><del>-                        unsure(continuation), unsure(isInBounds));
</del><ins>+                        unsure(isOutOfBounds), unsure(isInBounds));
</ins><span class="cx">                     
</span><del>-                    LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
</del><ins>+                    LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds);
</ins><span class="cx">                     m_out.store(valueToStore, pointer, storeType);
</span><span class="cx">                     m_out.jump(continuation);
</span><ins>+
+                    m_out.appendTo(isOutOfBounds, continuation);
+                    speculateTypedArrayIsNotNeutered(base);
+                    m_out.jump(continuation);
</ins><span class="cx">                     
</span><span class="cx">                     m_out.appendTo(continuation, lastNext);
</span><span class="cx">                 }
</span><span class="lines">@@ -3337,7 +3342,7 @@
</span><span class="cx">                 
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-            
</del><ins>+
</ins><span class="cx">             DFG_CRASH(m_graph, m_node, &quot;Bad array type&quot;);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -10587,7 +10592,24 @@
</span><span class="cx">         LValue value = lowJSValue(edge, ManualOperandSpeculation);
</span><span class="cx">         typeCheck(jsValueValue(value), edge, SpecMisc, isNotMisc(value));
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void speculateTypedArrayIsNotNeutered(LValue base)
+    {
+        LBasicBlock isWasteful = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        LValue mode = m_out.load32(base, m_heaps.JSArrayBufferView_mode);
+        m_out.branch(m_out.equal(mode, m_out.constInt32(WastefulTypedArray)),
+            unsure(isWasteful), unsure(continuation));
+
+        LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation);
+        LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector);
+        speculate(Uncountable, jsValueValue(vector), m_node, m_out.notZero64(vector));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+    }
+
</ins><span class="cx">     bool masqueradesAsUndefinedWatchpointIsStillValid()
</span><span class="cx">     {
</span><span class="cx">         return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node-&gt;origin.semantic);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -1655,7 +1655,7 @@
</span><span class="cx">     badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
</span><span class="cx">     Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
</span><span class="cx">     emitArrayProfileOutOfBoundsSpecialCase(profile);
</span><del>-    Jump done = jump();
</del><ins>+    slowCases.append(jump());
</ins><span class="cx">     inBounds.link(this);
</span><span class="cx">     
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="lines">@@ -1697,8 +1697,6 @@
</span><span class="cx">         CRASH();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    done.link(this);
-    
</del><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1727,7 +1725,7 @@
</span><span class="cx">     badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
</span><span class="cx">     Jump inBounds = branch32(Below, property, Address(base, JSArrayBufferView::offsetOfLength()));
</span><span class="cx">     emitArrayProfileOutOfBoundsSpecialCase(profile);
</span><del>-    Jump done = jump();
</del><ins>+    slowCases.append(jump());
</ins><span class="cx">     inBounds.link(this);
</span><span class="cx">     
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="lines">@@ -1767,8 +1765,6 @@
</span><span class="cx">         CRASH();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    done.link(this);
-    
</del><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> // Typed array views have different modes depending on how big they are and
</span><span class="cx"> // whether the user has done anything that requires a separate backing
</span><span class="cx"> // buffer or the DOM-specified neutering capabilities.
</span><del>-enum TypedArrayMode {
</del><ins>+enum TypedArrayMode : uint32_t {
</ins><span class="cx">     // Small and fast typed array. B is unused, V points to a vector
</span><span class="cx">     // allocated in copied space, and M = FastTypedArray. V's liveness is
</span><span class="cx">     // determined entirely by the view's liveness.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -583,6 +583,16 @@
</span><span class="cx">     return JSValue(i);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE EncodedJSValue encodedJSUndefined()
+{
+    return JSValue::encode(jsUndefined());
+}
+
+ALWAYS_INLINE EncodedJSValue encodedJSValue()
+{
+    return JSValue::encode(JSValue());
+}
+
</ins><span class="cx"> inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
</span><span class="cx"> inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -269,10 +269,12 @@
</span><span class="cx">     ArrayBuffer* existingBuffer();
</span><span class="cx"> 
</span><span class="cx">     static const TypedArrayType TypedArrayStorageType = Adaptor::typeValue;
</span><del>-    
</del><ins>+
</ins><span class="cx"> protected:
</span><span class="cx">     friend struct TypedArrayClassInfos;
</span><span class="cx"> 
</span><ins>+    static EncodedJSValue throwNeuteredTypedArrayTypeError(ExecState*, EncodedJSValue, PropertyName);
+
</ins><span class="cx">     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&amp;);
</span><span class="cx">     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&amp;);
</span><span class="cx">     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -37,6 +37,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+static const char* typedArrayBufferHasBeenDetachedErrorMessage = &quot;Underlying ArrayBuffer has been detached from the view&quot;;
+
</ins><span class="cx"> template&lt;typename Adaptor&gt;
</span><span class="cx"> JSGenericTypedArrayView&lt;Adaptor&gt;::JSGenericTypedArrayView(
</span><span class="cx">     VM&amp; vm, ConstructionContext&amp; context)
</span><span class="lines">@@ -288,14 +290,28 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Adaptor&gt;
</span><ins>+EncodedJSValue JSGenericTypedArrayView&lt;Adaptor&gt;::throwNeuteredTypedArrayTypeError(ExecState* exec, EncodedJSValue object, PropertyName)
+{
+    ASSERT_UNUSED(object, jsCast&lt;JSGenericTypedArrayView*&gt;(JSValue::decode(object))-&gt;isNeutered());
+    return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+}
+
+template&lt;typename Adaptor&gt;
</ins><span class="cx"> bool JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnPropertySlot(
</span><span class="cx">     JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(object);
</span><span class="cx"> 
</span><del>-    Optional&lt;uint32_t&gt; index = parseIndex(propertyName);
-    if (index &amp;&amp; thisObject-&gt;canGetIndexQuickly(index.value())) {
-        slot.setValue(thisObject, DontDelete | ReadOnly, thisObject-&gt;getIndexQuickly(index.value()));
</del><ins>+    if (Optional&lt;uint32_t&gt; index = parseIndex(propertyName)) {
+        if (thisObject-&gt;isNeutered()) {
+            slot.setCustom(thisObject, None, throwNeuteredTypedArrayTypeError);
+            return true;
+        }
+
+        if (thisObject-&gt;canGetIndexQuickly(index.value()))
+            slot.setValue(thisObject, DontDelete | ReadOnly, thisObject-&gt;getIndexQuickly(index.value()));
+        else
+            slot.setValue(thisObject, DontDelete | ReadOnly, jsUndefined());
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -308,7 +324,10 @@
</span><span class="cx">     PutPropertySlot&amp; slot)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(cell);
</span><del>-    
</del><ins>+
+    if (thisObject-&gt;isNeutered())
+        return reject(exec, true, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     // https://tc39.github.io/ecma262/#sec-integer-indexed-exotic-objects-set-p-v-receiver
</span><span class="cx">     // Ignore the receiver even if the receiver is altered to non base value.
</span><span class="cx">     // 9.4.5.5-2-b-i Return ? IntegerIndexedElementSet(O, numericIndex, V).
</span><span class="lines">@@ -324,13 +343,21 @@
</span><span class="cx">     const PropertyDescriptor&amp; descriptor, bool shouldThrow)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(object);
</span><ins>+
+    if (parseIndex(propertyName)) {
+        if (descriptor.isAccessorDescriptor())
+            return reject(exec, shouldThrow, &quot;Attempting to store accessor indexed property on a typed array.&quot;);
+
+        if (descriptor.attributes() &amp; (DontEnum | DontDelete | ReadOnly))
+            return reject(exec, shouldThrow, &quot;Attempting to store non-enumerable, non-configurable or non-writable indexed property on a typed array.&quot;);
+
+        if (descriptor.value()) {
+            PutPropertySlot unused(JSValue(thisObject), shouldThrow);
+            return thisObject-&gt;put(thisObject, exec, propertyName, descriptor.value(), unused);
+        }
+        return true;
+    }
</ins><span class="cx">     
</span><del>-    // This is matching Firefox behavior. In particular, it rejects all attempts to
-    // defineOwnProperty for indexed properties on typed arrays, even if they're out
-    // of bounds.
-    if (parseIndex(propertyName))
-        return reject(exec, shouldThrow, &quot;Attempting to write to a read-only typed array property.&quot;);
-    
</del><span class="cx">     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -339,7 +366,10 @@
</span><span class="cx">     JSCell* cell, ExecState* exec, PropertyName propertyName)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(cell);
</span><del>-    
</del><ins>+
+    if (thisObject-&gt;isNeutered())
+        return reject(exec, true, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     if (parseIndex(propertyName))
</span><span class="cx">         return false;
</span><span class="cx">     
</span><span class="lines">@@ -351,7 +381,12 @@
</span><span class="cx">     JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot&amp; slot)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(object);
</span><del>-    
</del><ins>+
+    if (thisObject-&gt;isNeutered()) {
+        slot.setCustom(thisObject, None, throwNeuteredTypedArrayTypeError);
+        return true;
+    }
+
</ins><span class="cx">     if (propertyName &gt; MAX_ARRAY_INDEX) {
</span><span class="cx">         return thisObject-&gt;methodTable()-&gt;getOwnPropertySlot(
</span><span class="cx">             thisObject, exec, Identifier::from(exec, propertyName), slot);
</span><span class="lines">@@ -369,7 +404,10 @@
</span><span class="cx">     JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(cell);
</span><del>-    
</del><ins>+
+    if (thisObject-&gt;isNeutered())
+        return reject(exec, true, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     if (propertyName &gt; MAX_ARRAY_INDEX) {
</span><span class="cx">         PutPropertySlot slot(JSValue(thisObject), shouldThrow);
</span><span class="cx">         return thisObject-&gt;methodTable()-&gt;put(thisObject, exec, Identifier::from(exec, propertyName), value, slot);
</span><span class="lines">@@ -382,12 +420,7 @@
</span><span class="cx"> bool JSGenericTypedArrayView&lt;Adaptor&gt;::deletePropertyByIndex(
</span><span class="cx">     JSCell* cell, ExecState* exec, unsigned propertyName)
</span><span class="cx"> {
</span><del>-    if (propertyName &gt; MAX_ARRAY_INDEX) {
-        return cell-&gt;methodTable()-&gt;deleteProperty(
-            cell, exec, Identifier::from(exec, propertyName));
-    }
-    
-    return false;
</del><ins>+    return cell-&gt;methodTable()-&gt;deleteProperty(cell, exec, Identifier::from(exec, propertyName));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Adaptor&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewPrototypeFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -42,8 +42,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static const char* typedArrayBufferHasBeenDetachedErrorMessage = &quot;Underlying ArrayBuffer has been detached from the view&quot;;
-
</del><span class="cx"> // This implements 22.2.4.7 TypedArraySpeciesCreate
</span><span class="cx"> // Note, that this function throws.
</span><span class="cx"> template&lt;typename Functor&gt;
</span><span class="lines">@@ -140,21 +138,25 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncCopyWithin(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     // 22.2.3.5
</span><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">     ViewClass* thisObject = jsCast&lt;ViewClass*&gt;(exec-&gt;thisValue());
</span><span class="cx">     if (thisObject-&gt;isNeutered())
</span><span class="cx">         return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
</span><span class="cx"> 
</span><del>-    if (exec-&gt;argumentCount() &lt; 2)
-        return throwVMTypeError(exec, ASCIILiteral(&quot;Expected at least two arguments&quot;));
-
-    if (exec-&gt;hadException())
-        return JSValue::encode(jsUndefined());
-
</del><span class="cx">     long length = thisObject-&gt;length();
</span><span class="cx">     long to = argumentClampedIndexFromStartOrEnd(exec, 0, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx">     long from = argumentClampedIndexFromStartOrEnd(exec, 1, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx">     long final = argumentClampedIndexFromStartOrEnd(exec, 2, length, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     if (final &lt; from)
</span><span class="cx">         return JSValue::encode(exec-&gt;thisValue());
</span><span class="cx"> 
</span><span class="lines">@@ -170,6 +172,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncFill(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     // 22.2.3.8
</span><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">     ViewClass* thisObject = jsCast&lt;ViewClass*&gt;(exec-&gt;thisValue());
</span><span class="cx">     if (thisObject-&gt;isNeutered())
</span><span class="cx">         return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
</span><span class="lines">@@ -180,8 +183,15 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned length = thisObject-&gt;length();
</span><span class="cx">     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 1, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx">     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 2, length, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     if (end &lt; begin)
</span><span class="cx">         return JSValue::encode(exec-&gt;thisValue());
</span><span class="cx"> 
</span><span class="lines">@@ -195,6 +205,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncIndexOf(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     // 22.2.3.13
</span><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">     ViewClass* thisObject = jsCast&lt;ViewClass*&gt;(exec-&gt;thisValue());
</span><span class="cx">     if (thisObject-&gt;isNeutered())
</span><span class="cx">         return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
</span><span class="lines">@@ -206,7 +217,12 @@
</span><span class="cx"> 
</span><span class="cx">     JSValue valueToFind = exec-&gt;argument(0);
</span><span class="cx">     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     typename ViewClass::ElementType* array = thisObject-&gt;typedVector();
</span><span class="cx">     typename ViewClass::ElementType target = ViewClass::toAdaptorNativeFromValue(exec, valueToFind);
</span><span class="cx">     if (exec-&gt;hadException())
</span><span class="lines">@@ -252,6 +268,9 @@
</span><span class="cx">     JSString* separatorString = separatorValue.toString(exec);
</span><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return JSValue::encode(jsUndefined());
</span><ins>+
+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
</ins><span class="cx">     return joinWithSeparator(separatorString-&gt;view(exec).get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -283,6 +302,9 @@
</span><span class="cx">             index = static_cast&lt;unsigned&gt;(fromDouble);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     typename ViewClass::ElementType* array = thisObject-&gt;typedVector();
</span><span class="cx">     typename ViewClass::ElementType target = ViewClass::toAdaptorNativeFromValue(exec, valueToFind);
</span><span class="cx">     if (exec-&gt;hadException())
</span><span class="lines">@@ -363,6 +385,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncSlice(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     // 22.2.3.26
</span><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">     JSFunction* callee = jsCast&lt;JSFunction*&gt;(exec-&gt;callee());
</span><span class="cx"> 
</span><span class="cx">     ViewClass* thisObject = jsCast&lt;ViewClass*&gt;(exec-&gt;thisValue());
</span><span class="lines">@@ -372,8 +395,15 @@
</span><span class="cx">     unsigned thisLength = thisObject-&gt;length();
</span><span class="cx"> 
</span><span class="cx">     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx">     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     // Clamp end to begin.
</span><span class="cx">     end = std::max(begin, end);
</span><span class="cx"> 
</span><span class="lines">@@ -435,6 +465,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncSubarray(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     // 22.2.3.23
</span><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx">     JSFunction* callee = jsCast&lt;JSFunction*&gt;(exec-&gt;callee());
</span><span class="cx"> 
</span><span class="cx">     ViewClass* thisObject = jsCast&lt;ViewClass*&gt;(exec-&gt;thisValue());
</span><span class="lines">@@ -441,15 +472,19 @@
</span><span class="cx">     if (thisObject-&gt;isNeutered())
</span><span class="cx">         return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
</span><span class="cx"> 
</span><del>-    if (!exec-&gt;argumentCount())
-        return throwVMTypeError(exec, ASCIILiteral(&quot;Expected at least one argument&quot;));
-
</del><span class="cx">     // Get the length here; later assert that the length didn't change.
</span><span class="cx">     unsigned thisLength = thisObject-&gt;length();
</span><span class="cx"> 
</span><span class="cx">     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx">     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
</span><ins>+    if (vm.exception())
+        return encodedJSValue();
</ins><span class="cx"> 
</span><ins>+    if (thisObject-&gt;isNeutered())
+        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
+
</ins><span class="cx">     // Clamp end to begin.
</span><span class="cx">     end = std::max(begin, end);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfoldtypedarraypropertiesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/fold-typed-array-properties.js (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/fold-typed-array-properties.js        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/tests/stress/fold-typed-array-properties.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -33,10 +33,3 @@
</span><span class="cx"> 
</span><span class="cx"> if (!didThrow)
</span><span class="cx">     throw &quot;Should have thrown.&quot;;
</span><del>-
-if (a.length != 0)
-    throw &quot;Error: bad length (end): &quot; + a.length;
-if (a.byteOffset != 0)
-    throw &quot;Error: bad offset (end): &quot; + a.byteOffset;
-if (a.byteLength != 0)
-    throw &quot;Error: bad byte length (end): &quot; + a.byteLength;
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayaccessmonomorphicneuteredjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typedarray-access-monomorphic-neutered.js (0 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typedarray-access-monomorphic-neutered.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typedarray-access-monomorphic-neutered.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+typedArrays = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
+
+
+function check(array, thunk, count) {
+    let failed = true;
+    try {
+        thunk(array, count);
+    } catch(e) {
+        if (e != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;)
+            throw new Error([thunk, count, e]);
+        failed = false;
+    }
+    if (failed)
+        throw new Error([thunk, count]);
+}
+noInline(check);
+
+function test(thunk, array) {
+    let fn = Function(&quot;array&quot;, &quot;i&quot;, thunk);
+    noInline(fn);
+    for (let i = 0; i &lt; 10000; i++)
+        check(array, fn, i);
+}
+
+for (let constructor of typedArrays) {
+    let array = new constructor(10);
+    transferArrayBuffer(array.buffer);
+    test(&quot;array[0]&quot;, array);
+    test(&quot;delete array[0]&quot;, array);
+    test(&quot;Object.getOwnPropertyDescriptor(array, 0)&quot;, array);
+    test(&quot;Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true })&quot;, array);
+    test(&quot;array[0] = 1&quot;, array);
+    test(&quot;array[i] = 1&quot;, array);
+}
+
+function testFTL(thunk, array, failArray) {
+    let fn = Function(&quot;array&quot;, &quot;i&quot;, thunk);
+    noInline(fn);
+    for (let i = 0; i &lt; 10000; i++)
+        fn(array, i)
+    check(failArray, fn, 10000);
+}
+
+for (let constructor of typedArrays) {
+    let array = new constructor(10);
+    let failArray = new constructor(10);
+    transferArrayBuffer(failArray.buffer);
+    testFTL(&quot;array[0]&quot;, array, failArray);
+    testFTL(&quot;delete array[0]&quot;, array, failArray);
+    testFTL(&quot;Object.getOwnPropertyDescriptor(array, 0)&quot;, array, failArray);
+    testFTL(&quot;Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true })&quot;, array, failArray);
+    testFTL(&quot;array[0] = 1&quot;, array, failArray);
+    testFTL(&quot;array[i] = 1&quot;, array, failArray);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayaccessneuteredjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typedarray-access-neutered.js (0 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typedarray-access-neutered.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typedarray-access-neutered.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+typedArrays = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
+
+
+function check(thunk, count) {
+    let array = new constructor(10);
+    transferArrayBuffer(array.buffer);
+    let failed = true;
+    try {
+        thunk(array);
+    } catch(e) {
+        if (e != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;)
+            throw new Error([thunk, count, e]);
+        failed = false;
+    }
+    if (failed)
+        throw new Error([thunk, count]);
+}
+
+function test(thunk, count) {
+    for (constructor of typedArrays)
+        check(thunk, count);
+}
+
+for (let i = 0; i &lt; 10000; i++) {
+    test((array) =&gt; array[0], i);
+    test((array) =&gt; delete array[0], i);
+    test((array) =&gt; Object.getOwnPropertyDescriptor(array, 0), i);
+    test((array) =&gt; Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true }), i)
+    test((array) =&gt; array[0] = 1, i);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayfunctionswithneuteredjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/typedarray-functions-with-neutered.js (202981 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typedarray-functions-with-neutered.js        2016-07-08 15:52:57 UTC (rev 202981)
+++ trunk/Source/JavaScriptCore/tests/stress/typedarray-functions-with-neutered.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -73,3 +73,88 @@
</span><span class="cx"> for (var i = 0; i &lt; 1000; i++)
</span><span class="cx">     test();
</span><span class="cx"> 
</span><ins>+// Test that we handle neutering for any toInteger neutering the arraybuffer.
+prototypeFunctions = [
+    { func:proto.copyWithin, args:[&quot;prim&quot;, &quot;prim&quot;, &quot;prim&quot;] },
+    { func:proto.every, args:[&quot;func&quot;] },
+    { func:proto.fill, args:[&quot;ins&quot;, &quot;prim&quot;, &quot;prim&quot;] },
+    { func:proto.filter, args:[&quot;func&quot;] },
+    { func:proto.find, args:[&quot;func&quot;] },
+    { func:proto.findIndex, args:[&quot;func&quot;] },
+    { func:proto.forEach, args:[&quot;func&quot;] },
+    { func:proto.indexOf, args:[&quot;na&quot;, &quot;prim&quot;] },
+    { func:proto.join, args:[&quot;prim&quot;] },
+    { func:proto.lastIndexOf, args:[&quot;na&quot;, &quot;prim&quot;] },
+    { func:proto.map, args:[&quot;func&quot;] },
+    { func:proto.reduce, args:[&quot;func&quot;] },
+    { func:proto.reduceRight, args:[&quot;func&quot;] },
+    { func:proto.set, args:[&quot;array&quot;, &quot;prim&quot;] },
+    { func:proto.slice, args:[&quot;prim&quot;, &quot;prim&quot;] },
+    { func:proto.some, args:[&quot;func&quot;] },
+    { func:proto.sort, args:[&quot;func&quot;] },
+    { func:proto.subarray, args:[&quot;prim&quot;, &quot;prim&quot;] },
+];
+
+function defaultForArg(arg)
+{
+    if (arg === &quot;func&quot;)
+        return () =&gt; { return 1; }
+
+    return 1;
+}
+
+function callWithArgs(func, array, args) {
+    let failed = true;
+    try {
+        func.call(array, ...args);
+    } catch (e) {
+        if (e != &quot;TypeError: Underlying ArrayBuffer has been detached from the view&quot;)
+            throw new Error(e);
+        failed = false;
+    }
+    if (failed)
+        throw new Error([func, args]);
+}
+
+
+function checkArgumentsForType(func, args, constructor) {
+    let defaultArgs = args.map(defaultForArg);
+
+    for (let argNum = 0; argNum &lt; args.length; argNum++) {
+        let arg = args[argNum];
+        let callArgs = defaultArgs.slice();
+
+        if (arg === &quot;na&quot;)
+            continue;
+
+        let len = 10;
+        if (arg === &quot;func&quot;) {
+            let array = new constructor(len);
+            callArgs[argNum] = () =&gt; {
+                transferArrayBuffer(array.buffer);
+                return func === array.every ? 1 : 0;
+            };
+            callWithArgs(func, array, callArgs);
+        }
+
+        if (arg === &quot;prim&quot;) {
+            let array = new constructor(len)
+            callArgs[argNum] = { [Symbol.toPrimitive]() {
+                transferArrayBuffer(array.buffer);
+                return 1;
+            } };
+            callWithArgs(func, array, callArgs);
+        }
+    }
+}
+
+function checkArguments({func, args}) {
+    for (constructor of typedArrays)
+        checkArgumentsForType(func, args, constructor)
+}
+
+function test() {
+    prototypeFunctions.forEach(checkArguments);
+}
+
+test();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayviewstringpropertiesneuteredjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typedarray-view-string-properties-neutered.js (0 => 202982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typedarray-view-string-properties-neutered.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typedarray-view-string-properties-neutered.js        2016-07-08 16:27:35 UTC (rev 202982)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+typedArrays = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
+
+
+function call(thunk) {
+    thunk();
+}
+noInline(call);
+
+let name = [&quot;map&quot;, &quot;reduce&quot;];
+// First test with every access being neutered.
+function test(constructor) {
+    let array = new constructor(10);
+    transferArrayBuffer(array.buffer);
+    for (let i = 0; i &lt; 10000; i++) {
+        call(() =&gt; {
+            if (array.map !== constructor.prototype.map)
+                throw new Error();
+        });
+        call(() =&gt; {
+            if (array[name[i % 2]] !== constructor.prototype[name[i % 2]])
+                throw new Error();
+        });
+    }
+}
+
+for (constructor of typedArrays) {
+    test(constructor);
+}
+
+// Next test with neutered after tier up.
+function test(constructor) {
+    let array = new constructor(10);
+    let i = 0;
+    fnId = () =&gt;  {
+        if (array.map !== constructor.prototype.map)
+            throw new Error();
+    };
+    fnVal = () =&gt; {
+        if (array[name[i % 2]] !== constructor.prototype[name[i % 2]])
+            throw new Error();
+    };
+    for (; i &lt; 10000; i++) {
+        call(fnId);
+        call(fnVal);
+    }
+    transferArrayBuffer(array.buffer);
+    call(fnId);
+    call(fnVal);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>