<!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>[191190] 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/191190">191190</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2015-10-16 11:37:14 -0700 (Fri, 16 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix some issues with TypedArrays
https://bugs.webkit.org/show_bug.cgi?id=150216

Reviewed by Michael Saboff.

This fixes a couple of issues:
1) The DFG had a separate case for creating new typedarrays in the dfg when the first argument is an object.
   Since the code for creating a Typedarray in the dfg is almost the same as the code in Baseline/LLInt
   the two cases have been merged.
2) If the length property on an object was unset then the construction could crash.
3) The TypedArray.prototype.set function and the TypedArray constructor should not call [[Get]] for the
   length of the source object when the source object is a TypedArray.
4) The conditions that were used to decide if the iterator could be skipped were incorrect.
   Instead of checking for have a bad time we should have checked the Indexing type did not allow for
   indexed accessors.

* dfg/DFGOperations.cpp:
(JSC::DFG::newTypedArrayWithOneArgument): Deleted.
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayViewFromIterator):
(JSC::constructGenericTypedArrayViewWithFirstArgument):
(JSC::constructGenericTypedArrayView):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoFuncSet):
* tests/stress/typedarray-construct-iterator.js: Added.
(iterator.return.next):
(iterator):
(body):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewConstructorInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewPrototypeFunctionsh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayconstructiteratorjs">trunk/Source/JavaScriptCore/tests/stress/typedarray-construct-iterator.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (191189 => 191190)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-16 18:30:23 UTC (rev 191189)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-16 18:37:14 UTC (rev 191190)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2015-10-16  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Fix some issues with TypedArrays
+        https://bugs.webkit.org/show_bug.cgi?id=150216
+
+        Reviewed by Michael Saboff.
+
+        This fixes a couple of issues:
+        1) The DFG had a separate case for creating new typedarrays in the dfg when the first argument is an object.
+           Since the code for creating a Typedarray in the dfg is almost the same as the code in Baseline/LLInt
+           the two cases have been merged.
+        2) If the length property on an object was unset then the construction could crash.
+        3) The TypedArray.prototype.set function and the TypedArray constructor should not call [[Get]] for the
+           length of the source object when the source object is a TypedArray.
+        4) The conditions that were used to decide if the iterator could be skipped were incorrect.
+           Instead of checking for have a bad time we should have checked the Indexing type did not allow for
+           indexed accessors.
+
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::newTypedArrayWithOneArgument): Deleted.
+        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
+        (JSC::constructGenericTypedArrayViewFromIterator):
+        (JSC::constructGenericTypedArrayViewWithFirstArgument):
+        (JSC::constructGenericTypedArrayView):
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::genericTypedArrayViewProtoFuncSet):
+        * tests/stress/typedarray-construct-iterator.js: Added.
+        (iterator.return.next):
+        (iterator):
+        (body):
+
</ins><span class="cx"> 2015-10-15  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r190289): Repro crash clicking back button on netflix.com
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (191189 => 191190)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-10-16 18:30:23 UTC (rev 191189)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-10-16 18:37:14 UTC (rev 191190)
</span><span class="lines">@@ -142,64 +142,6 @@
</span><span class="cx">     return bitwise_cast&lt;char*&gt;(ViewClass::create(exec, structure, size));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename ViewClass&gt;
-char* newTypedArrayWithOneArgument(
-    ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
-{
-    VM&amp; vm = exec-&gt;vm();
-    NativeCallFrameTracer tracer(&amp;vm, exec);
-    
-    JSValue value = JSValue::decode(encodedValue);
-    
-    if (JSArrayBuffer* jsBuffer = jsDynamicCast&lt;JSArrayBuffer*&gt;(value)) {
-        RefPtr&lt;ArrayBuffer&gt; buffer = jsBuffer-&gt;impl();
-        
-        if (buffer-&gt;byteLength() % ViewClass::elementSize) {
-            vm.throwException(exec, createRangeError(exec, ASCIILiteral(&quot;ArrayBuffer length minus the byteOffset is not a multiple of the element size&quot;)));
-            return 0;
-        }
-        return bitwise_cast&lt;char*&gt;(
-            ViewClass::create(
-                exec, structure, buffer, 0, buffer-&gt;byteLength() / ViewClass::elementSize));
-    }
-    
-    if (JSObject* object = jsDynamicCast&lt;JSObject*&gt;(value)) {
-        unsigned length = object-&gt;get(exec, vm.propertyNames-&gt;length).toUInt32(exec);
-        if (exec-&gt;hadException())
-            return 0;
-        
-        ViewClass* result = ViewClass::createUninitialized(exec, structure, length);
-        if (!result)
-            return 0;
-        
-        if (!result-&gt;set(exec, object, 0, length))
-            return 0;
-        
-        return bitwise_cast&lt;char*&gt;(result);
-    }
-    
-    int length;
-    if (value.isInt32())
-        length = value.asInt32();
-    else if (!value.isNumber()) {
-        vm.throwException(exec, createTypeError(exec, ASCIILiteral(&quot;Invalid array length argument&quot;)));
-        return 0;
-    } else {
-        length = static_cast&lt;int&gt;(value.asNumber());
-        if (length != value.asNumber()) {
-            vm.throwException(exec, createTypeError(exec, ASCIILiteral(&quot;Invalid array length argument (fractional lengths not allowed)&quot;)));
-            return 0;
-        }
-    }
-    
-    if (length &lt; 0) {
-        vm.throwException(exec, createRangeError(exec, ASCIILiteral(&quot;Requested length is negative&quot;)));
-        return 0;
-    }
-    
-    return bitwise_cast&lt;char*&gt;(ViewClass::create(exec, structure, length));
-}
-
</del><span class="cx"> extern &quot;C&quot; {
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
</span><span class="lines">@@ -664,7 +606,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSInt8Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSInt8Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewInt16ArrayWithSize(
</span><span class="lines">@@ -676,7 +618,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSInt16Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSInt16Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewInt32ArrayWithSize(
</span><span class="lines">@@ -688,7 +630,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSInt32Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSInt32Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewUint8ArrayWithSize(
</span><span class="lines">@@ -700,7 +642,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSUint8Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSUint8Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
</span><span class="lines">@@ -712,7 +654,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSUint8ClampedArray&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSUint8ClampedArray&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewUint16ArrayWithSize(
</span><span class="lines">@@ -724,7 +666,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSUint16Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSUint16Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewUint32ArrayWithSize(
</span><span class="lines">@@ -736,7 +678,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSUint32Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSUint32Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewFloat32ArrayWithSize(
</span><span class="lines">@@ -748,7 +690,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSFloat32Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSFloat32Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationNewFloat64ArrayWithSize(
</span><span class="lines">@@ -760,7 +702,7 @@
</span><span class="cx"> char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
</span><span class="cx">     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
</span><span class="cx"> {
</span><del>-    return newTypedArrayWithOneArgument&lt;JSFloat64Array&gt;(exec, structure, encodedValue);
</del><ins>+    return bitwise_cast&lt;char*&gt;(constructGenericTypedArrayViewWithFirstArgument&lt;JSFloat64Array&gt;(exec, structure, encodedValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewConstructorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h (191189 => 191190)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h        2015-10-16 18:30:23 UTC (rev 191189)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h        2015-10-16 18:37:14 UTC (rev 191190)
</span><span class="lines">@@ -77,23 +77,23 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename ViewClass&gt;
</span><del>-static EncodedJSValue constructGenericTypedArrayViewFromIterator(ExecState* exec, Structure* structure, JSValue iterator)
</del><ins>+static JSObject* constructGenericTypedArrayViewFromIterator(ExecState* exec, Structure* structure, JSValue iterator)
</ins><span class="cx"> {
</span><span class="cx">     if (!iterator.isObject())
</span><del>-        return JSValue::encode(throwTypeError(exec, &quot;Symbol.Iterator for the first argument did not return an object.&quot;));
</del><ins>+        return throwTypeError(exec, &quot;Symbol.Iterator for the first argument did not return an object.&quot;);
</ins><span class="cx"> 
</span><span class="cx">     MarkedArgumentBuffer storage;
</span><span class="cx">     while (true) {
</span><span class="cx">         JSValue next = iteratorStep(exec, iterator);
</span><span class="cx">         if (exec-&gt;hadException())
</span><del>-            return JSValue::encode(jsUndefined());
</del><ins>+            return nullptr;
</ins><span class="cx"> 
</span><span class="cx">         if (next.isFalse())
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         JSValue nextItem = iteratorValue(exec, next);
</span><span class="cx">         if (exec-&gt;hadException())
</span><del>-            return JSValue::encode(jsUndefined());
</del><ins>+            return nullptr;
</ins><span class="cx"> 
</span><span class="cx">         storage.append(nextItem);
</span><span class="cx">     }
</span><span class="lines">@@ -101,132 +101,146 @@
</span><span class="cx">     ViewClass* result = ViewClass::createUninitialized(exec, structure, storage.size());
</span><span class="cx">     if (!result) {
</span><span class="cx">         ASSERT(exec-&gt;hadException());
</span><del>-        return JSValue::encode(jsUndefined());
</del><ins>+        return nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; storage.size(); ++i) {
</span><span class="cx">         if (!result-&gt;setIndex(exec, i, storage.at(i))) {
</span><span class="cx">             ASSERT(exec-&gt;hadException());
</span><del>-            return JSValue::encode(jsUndefined());
</del><ins>+            return nullptr;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return JSValue::encode(result);
</del><ins>+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename ViewClass&gt;
-static EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState* exec)
</del><ins>+template&lt;typename ViewClass, bool checkForOtherArguments = false&gt;
+static JSObject* constructGenericTypedArrayViewWithFirstArgument(ExecState* exec, Structure* structure, EncodedJSValue firstArgument)
</ins><span class="cx"> {
</span><del>-    Structure* structure =
-        asInternalFunction(exec-&gt;callee())-&gt;globalObject()-&gt;typedArrayStructure(
-            ViewClass::TypedArrayStorageType);
-
</del><ins>+    JSValue firstValue = JSValue::decode(firstArgument);
</ins><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx"> 
</span><del>-    if (!exec-&gt;argumentCount()) {
-        if (ViewClass::TypedArrayStorageType == TypeDataView)
-            return throwVMError(exec, createTypeError(exec, &quot;DataView constructor requires at least one argument.&quot;));
-        
-        // Even though the documentation doesn't say so, it's correct to say
-        // &quot;new Int8Array()&quot;. This is the same as allocating an array of zero
-        // length.
-        return JSValue::encode(ViewClass::create(exec, structure, 0));
-    }
-    
-    if (JSArrayBuffer* jsBuffer = jsDynamicCast&lt;JSArrayBuffer*&gt;(exec-&gt;argument(0))) {
</del><ins>+    if (JSArrayBuffer* jsBuffer = jsDynamicCast&lt;JSArrayBuffer*&gt;(firstValue)) {
</ins><span class="cx">         RefPtr&lt;ArrayBuffer&gt; buffer = jsBuffer-&gt;impl();
</span><del>-        
-        unsigned offset = (exec-&gt;argumentCount() &gt; 1) ? exec-&gt;uncheckedArgument(1).toUInt32(exec) : 0;
-        if (exec-&gt;hadException())
-            return JSValue::encode(jsUndefined());
</del><ins>+
+        unsigned offset = 0;
</ins><span class="cx">         unsigned length = 0;
</span><del>-        if (exec-&gt;argumentCount() &gt; 2) {
</del><ins>+        if (checkForOtherArguments &amp;&amp; exec-&gt;argumentCount() &gt; 1) {
+            offset = exec-&gt;uncheckedArgument(1).toUInt32(exec);
+            if (exec-&gt;hadException())
+                return nullptr;
+        }
+
+        if (checkForOtherArguments &amp;&amp; exec-&gt;argumentCount() &gt; 2) {
</ins><span class="cx">             length = exec-&gt;uncheckedArgument(2).toUInt32(exec);
</span><span class="cx">             if (exec-&gt;hadException())
</span><del>-                return JSValue::encode(jsUndefined());
</del><ins>+                return nullptr;
</ins><span class="cx">         } else {
</span><span class="cx">             if ((buffer-&gt;byteLength() - offset) % ViewClass::elementSize)
</span><del>-                return throwVMError(exec, createRangeError(exec, &quot;ArrayBuffer length minus the byteOffset is not a multiple of the element size&quot;));
</del><ins>+                return throwRangeError(exec, &quot;ArrayBuffer length minus the byteOffset is not a multiple of the element size&quot;);
</ins><span class="cx">             length = (buffer-&gt;byteLength() - offset) / ViewClass::elementSize;
</span><ins>+
</ins><span class="cx">         }
</span><del>-        return JSValue::encode(ViewClass::create(exec, structure, buffer, offset, length));
</del><ins>+
+        return ViewClass::create(exec, structure, buffer, offset, length);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (ViewClass::TypedArrayStorageType == TypeDataView)
</span><del>-        return throwVMError(exec, createTypeError(exec, &quot;Expected ArrayBuffer for the first argument.&quot;));
</del><ins>+        return throwTypeError(exec, &quot;Expected ArrayBuffer for the first argument.&quot;);
</ins><span class="cx">     
</span><span class="cx">     // For everything but DataView, we allow construction with any of:
</span><span class="cx">     // - Another array. This creates a copy of the of that array.
</span><span class="cx">     // - An integer. This creates a new typed array of that length and zero-initializes it.
</span><del>-    
-    if (JSObject* object = jsDynamicCast&lt;JSObject*&gt;(exec-&gt;uncheckedArgument(0))) {
-        PropertySlot lengthSlot(object);
-        object-&gt;getPropertySlot(exec, vm.propertyNames-&gt;length, lengthSlot);
</del><span class="cx"> 
</span><del>-        if (!isTypedView(object-&gt;classInfo()-&gt;typedArrayStorageType)) {
</del><ins>+    if (JSObject* object = jsDynamicCast&lt;JSObject*&gt;(firstValue)) {
+        unsigned length;
+
+        if (isTypedView(object-&gt;classInfo()-&gt;typedArrayStorageType))
+            length = jsCast&lt;JSArrayBufferView*&gt;(object)-&gt;length();
+        else {
+            PropertySlot lengthSlot(object);
+            object-&gt;getPropertySlot(exec, vm.propertyNames-&gt;length, lengthSlot);
+
</ins><span class="cx">             JSValue iteratorFunc = object-&gt;get(exec, vm.propertyNames-&gt;iteratorSymbol);
</span><span class="cx">             if (exec-&gt;hadException())
</span><del>-                return JSValue::encode(jsUndefined());
</del><ins>+                return nullptr;
</ins><span class="cx"> 
</span><span class="cx">             // We would like not use the iterator as it is painfully slow. Fortunately, unless
</span><span class="cx">             // 1) The iterator is not a known iterator.
</span><span class="cx">             // 2) The base object does not have a length getter.
</span><del>-            // 3) Bad times are being had.
</del><ins>+            // 3) The base object might have indexed getters.
</ins><span class="cx">             // it should not be observable that we do not use the iterator.
</span><span class="cx"> 
</span><span class="cx">             if (!iteratorFunc.isUndefined()
</span><del>-                &amp;&amp; (iteratorFunc != exec-&gt;lexicalGlobalObject()-&gt;arrayProtoValuesFunction()
</del><ins>+                &amp;&amp; (iteratorFunc != object-&gt;globalObject()-&gt;arrayProtoValuesFunction()
</ins><span class="cx">                     || lengthSlot.isAccessor() || lengthSlot.isCustom()
</span><del>-                    || exec-&gt;lexicalGlobalObject()-&gt;isHavingABadTime())) {
</del><ins>+                    || hasAnyArrayStorage(object-&gt;indexingType()))) {
</ins><span class="cx"> 
</span><span class="cx">                     CallData callData;
</span><span class="cx">                     CallType callType = getCallData(iteratorFunc, callData);
</span><span class="cx">                     if (callType == CallTypeNone)
</span><del>-                        return JSValue::encode(throwTypeError(exec, &quot;Symbol.Iterator for the first argument cannot be called.&quot;));
</del><ins>+                        return throwTypeError(exec, &quot;Symbol.Iterator for the first argument cannot be called.&quot;);
</ins><span class="cx"> 
</span><span class="cx">                     ArgList arguments;
</span><span class="cx">                     JSValue iterator = call(exec, iteratorFunc, callType, callData, object, arguments);
</span><span class="cx">                     if (exec-&gt;hadException())
</span><del>-                        return JSValue::encode(jsUndefined());
</del><ins>+                        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">                     return constructGenericTypedArrayViewFromIterator&lt;ViewClass&gt;(exec, structure, iterator);
</span><ins>+            }
</ins><span class="cx"> 
</span><del>-            }
</del><ins>+            length = lengthSlot.isUnset() ? 0 : lengthSlot.getValue(exec, vm.propertyNames-&gt;length).toUInt32(exec);
+            if (exec-&gt;hadException())
+                return nullptr;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        unsigned length = lengthSlot.getValue(exec, vm.propertyNames-&gt;length).toUInt32(exec);
-        if (exec-&gt;hadException())
-            return JSValue::encode(jsUndefined());
</del><span class="cx">         
</span><span class="cx">         ViewClass* result = ViewClass::createUninitialized(exec, structure, length);
</span><span class="cx">         if (!result) {
</span><span class="cx">             ASSERT(exec-&gt;hadException());
</span><del>-            return JSValue::encode(jsUndefined());
</del><ins>+            return nullptr;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (!result-&gt;set(exec, object, 0, length))
</span><del>-            return JSValue::encode(jsUndefined());
</del><ins>+            return nullptr;
</ins><span class="cx">         
</span><del>-        return JSValue::encode(result);
</del><ins>+        return result;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     int length;
</span><del>-    if (exec-&gt;uncheckedArgument(0).isInt32())
-        length = exec-&gt;uncheckedArgument(0).asInt32();
-    else if (!exec-&gt;uncheckedArgument(0).isNumber())
-        return throwVMError(exec, createTypeError(exec, &quot;Invalid array length argument&quot;));
</del><ins>+    if (firstValue.isInt32())
+        length = firstValue.asInt32();
+    else if (!firstValue.isNumber())
+        return throwTypeError(exec, &quot;Invalid array length argument&quot;);
</ins><span class="cx">     else {
</span><del>-        length = static_cast&lt;int&gt;(exec-&gt;uncheckedArgument(0).asNumber());
-        if (length != exec-&gt;uncheckedArgument(0).asNumber())
-            return throwVMError(exec, createTypeError(exec, &quot;Invalid array length argument (fractional lengths not allowed)&quot;));
</del><ins>+        length = static_cast&lt;int&gt;(firstValue.asNumber());
+        if (length != firstValue.asNumber())
+            return throwTypeError(exec, &quot;Invalid array length argument (fractional lengths not allowed)&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (length &lt; 0)
</span><del>-        return throwVMError(exec, createRangeError(exec, &quot;Requested length is negative&quot;));
-    return JSValue::encode(ViewClass::create(exec, structure, length));
</del><ins>+        return throwRangeError(exec, &quot;Requested length is negative&quot;);
+    return ViewClass::create(exec, structure, length);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename ViewClass&gt;
</span><ins>+static EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState* exec)
+{
+    Structure* structure =
+        asInternalFunction(exec-&gt;callee())-&gt;globalObject()-&gt;typedArrayStructure(
+            ViewClass::TypedArrayStorageType);
+
+    if (!exec-&gt;argumentCount()) {
+        if (ViewClass::TypedArrayStorageType == TypeDataView)
+            return throwVMError(exec, createTypeError(exec, &quot;DataView constructor requires at least one argument.&quot;));
+
+        return JSValue::encode(ViewClass::create(exec, structure, 0));
+    }
+
+    return JSValue::encode(constructGenericTypedArrayViewWithFirstArgument&lt;ViewClass, true&gt;(exec, structure, JSValue::encode(exec-&gt;uncheckedArgument(0))));
+}
+
+template&lt;typename ViewClass&gt;
</ins><span class="cx"> ConstructType JSGenericTypedArrayViewConstructor&lt;ViewClass&gt;::getConstructData(JSCell*, ConstructData&amp; constructData)
</span><span class="cx"> {
</span><span class="cx">     constructData.native.function = constructGenericTypedArrayView&lt;ViewClass&gt;;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewPrototypeFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h (191189 => 191190)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h        2015-10-16 18:30:23 UTC (rev 191189)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h        2015-10-16 18:37:14 UTC (rev 191190)
</span><span class="lines">@@ -66,10 +66,6 @@
</span><span class="cx">     if (!exec-&gt;argumentCount())
</span><span class="cx">         return throwVMError(exec, createTypeError(exec, &quot;Expected at least one argument&quot;));
</span><span class="cx"> 
</span><del>-    JSObject* sourceArray = jsDynamicCast&lt;JSObject*&gt;(exec-&gt;uncheckedArgument(0));
-    if (!sourceArray)
-        return throwVMError(exec, createTypeError(exec, &quot;First argument should be an object&quot;));
-
</del><span class="cx">     unsigned offset;
</span><span class="cx">     if (exec-&gt;argumentCount() &gt;= 2) {
</span><span class="cx">         offset = exec-&gt;uncheckedArgument(1).toUInt32(exec);
</span><span class="lines">@@ -78,7 +74,16 @@
</span><span class="cx">     } else
</span><span class="cx">         offset = 0;
</span><span class="cx"> 
</span><del>-    unsigned length = sourceArray-&gt;get(exec, exec-&gt;vm().propertyNames-&gt;length).toUInt32(exec);
</del><ins>+    JSObject* sourceArray = jsDynamicCast&lt;JSObject*&gt;(exec-&gt;uncheckedArgument(0));
+    if (!sourceArray)
+        return throwVMError(exec, createTypeError(exec, &quot;First argument should be an object&quot;));
+
+    unsigned length;
+    if (isTypedView(sourceArray-&gt;classInfo()-&gt;typedArrayStorageType))
+        length = jsDynamicCast&lt;JSArrayBufferView*&gt;(sourceArray)-&gt;length();
+    else
+        length = sourceArray-&gt;get(exec, exec-&gt;vm().propertyNames-&gt;length).toUInt32(exec);
+
</ins><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return JSValue::encode(jsUndefined());
</span><span class="cx"> 
</span><span class="lines">@@ -283,7 +288,6 @@
</span><span class="cx">     return JSValue::encode(jsNumber(thisObject-&gt;byteOffset()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> template&lt;typename ViewClass&gt;
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncReverse(ExecState* exec)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayconstructiteratorjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typedarray-construct-iterator.js (0 => 191190)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typedarray-construct-iterator.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typedarray-construct-iterator.js        2015-10-16 18:37:14 UTC (rev 191190)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+// Test a bunch of things about typed array constructors with iterators.
+
+// Test that the dfg actually respects iterators.
+let foo = [1,2,3,4];
+
+function iterator() {
+    return { i: 0,
+             next: function() {
+                 if (this.i &lt; foo.length/2) {
+                     return { done: false,
+                              value: foo[this.i++]
+                            };
+                 }
+                 return { done: true };
+             }
+           };
+}
+
+foo[Symbol.iterator] = iterator;
+
+(function body() {
+
+    for (var i = 1; i &lt; 100000; i++) {
+        if (new Int32Array(foo).length !== 2)
+            throw &quot;iterator did not run&quot;;
+    }
+
+})();
+
+// Test that the optimizations used for iterators during construction is valid.
+
+foo = { 0:0, 1:1, 2:2, 3:3 };
+count = 4;
+foo.__defineGetter__(&quot;length&quot;, function() {
+    return count--;
+});
+
+foo[Symbol.iterator] = Array.prototype[Symbol.iterator];
+
+if (new Int32Array(foo).length !== 2)
+    throw &quot;iterator did not run&quot;;
+
+// Test that we handle length is unset... whoops.
+
+foo = { 0:0, 2:2, 3:3 };
+
+if (new Int32Array(foo).length !== 0)
+    throw &quot;did not handle object with unset length&quot;;
+
+// Test that we handle prototypes with accessors.
+
+foo = { 0:0, 2:2, 3:3 };
+foo[Symbol.iterator] = Array.prototype[Symbol.iterator];
+foo.length = 4;
+bar = { };
+
+bar.__defineGetter__(&quot;1&quot;, function() {
+    foo.length = 0;
+    return 1;
+});
+
+
+foo.__proto__ = bar;
+
+if (new Int32Array(foo).length !== 2)
+    throw &quot;did not handle object with accessor on prototype&quot;;
</ins></span></pre>
</div>
</div>

</body>
</html>