<!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>[200032] 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/200032">200032</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2016-04-25 10:31:29 -0700 (Mon, 25 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement latest File object spec (including its constructor).
https://bugs.webkit.org/show_bug.cgi?id=156511

Reviewed by Darin Adler.

Source/WebCore:

Test: fast/files/file-constructor.html

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:

* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue):
* bindings/js/JSDictionary.h:

* bindings/js/JSFileCustom.cpp: Added.
(WebCore::constructJSFile):

* fileapi/File.cpp:
(WebCore::File::File):
(WebCore::File::lastModified):
(WebCore::File::lastModifiedDate): Deleted.
* fileapi/File.h:
* fileapi/File.idl:

LayoutTests:

* fast/files/file-constructor-expected.txt: Added.
* fast/files/file-constructor.html: Added.

* http/tests/local/fileapi/file-last-modified-after-delete-expected.txt:
* http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js:

* http/tests/local/fileapi/file-last-modified-expected.txt:
* http/tests/local/fileapi/script-tests/file-last-modified.js:

* imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestslocalfileapifilelastmodifiedafterdeleteexpectedtxt">trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-after-delete-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestslocalfileapifilelastmodifiedexpectedtxt">trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestslocalfileapiscripttestsfilelastmodifiedafterdeletejs">trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js</a></li>
<li><a href="#trunkLayoutTestshttptestslocalfileapiscripttestsfilelastmodifiedjs">trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified.js</a></li>
<li><a href="#trunkLayoutTestsimportedblinkstorageindexeddbblobbasicsmetadataexpectedtxt">trunk/LayoutTests/imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDictionarycpp">trunk/Source/WebCore/bindings/js/JSDictionary.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDictionaryh">trunk/Source/WebCore/bindings/js/JSDictionary.h</a></li>
<li><a href="#trunkSourceWebCorefileapiFilecpp">trunk/Source/WebCore/fileapi/File.cpp</a></li>
<li><a href="#trunkSourceWebCorefileapiFileh">trunk/Source/WebCore/fileapi/File.h</a></li>
<li><a href="#trunkSourceWebCorefileapiFileidl">trunk/Source/WebCore/fileapi/File.idl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastfilesfileconstructorexpectedtxt">trunk/LayoutTests/fast/files/file-constructor-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastfilesfileconstructorhtml">trunk/LayoutTests/fast/files/file-constructor.html</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSFileCustomcpp">trunk/Source/WebCore/bindings/js/JSFileCustom.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/ChangeLog        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-04-25  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Implement latest File object spec (including its constructor).
+        https://bugs.webkit.org/show_bug.cgi?id=156511
+
+        Reviewed by Darin Adler.
+
+        * fast/files/file-constructor-expected.txt: Added.
+        * fast/files/file-constructor.html: Added.
+        
+        * http/tests/local/fileapi/file-last-modified-after-delete-expected.txt:
+        * http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js:
+
+        * http/tests/local/fileapi/file-last-modified-expected.txt:
+        * http/tests/local/fileapi/script-tests/file-last-modified.js:
+
+        * imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt:
+
</ins><span class="cx"> 2016-04-25  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r196012): Subresource may be blocked by Content Security Policy if it only matches 'self'
</span></span></pre></div>
<a id="trunkLayoutTestsfastfilesfileconstructorexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/files/file-constructor-expected.txt (0 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/files/file-constructor-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/files/file-constructor-expected.txt        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -0,0 +1,104 @@
</span><ins>+Test the File constructor.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File(['hello'], 'world.html')) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html'})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html', endings:'native'})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html', endings:'transparent'})) instanceof window.File is true
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File()) threw exception TypeError: First argument to File constructor must be a valid sequence, was undefined or null.
+PASS (new File([])) threw exception TypeError: Second argument to File constructor must be a valid string, was undefined.
+PASS (new File([], null)) instanceof window.File is true
+PASS (new File([], 1)) instanceof window.File is true
+PASS (new File([], '')) instanceof window.File is true
+PASS (new File([], document)) instanceof window.File is true
+PASS new File('hello', 'world.html') threw exception TypeError: Value is not a sequence.
+PASS new File(0, 'world.html') threw exception TypeError: Value is not a sequence.
+PASS new File(null, 'world.html') threw exception TypeError: First argument to File constructor must be a valid sequence, was undefined or null.
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File(['stringPrimitive'], 'world.html')) instanceof window.File is true
+PASS (new File([String('stringObject')], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob([new Blob])], 'world.html')) instanceof window.File is true
+PASS (new Blob([new File([], 'world.txt')])) instanceof window.Blob is true
+PASS (new Blob([new Blob([new File([new Blob], 'world.txt')])])) instanceof window.Blob is true
+PASS (new File([new File([], 'world.txt')], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob([new File([new Blob], 'world.txt')])], 'world.html')) instanceof window.File is true
+PASS (new File([12], 'world.html')).size is 2
+PASS (new File([[]], 'world.html')).size is 0
+PASS (new File([{}], 'world.html')).size is 15
+PASS (new File([document], 'world.html')).size is 21
+PASS (new File([toStringingObj], 'world.html')).size is 8
+PASS new File([throwingObj], 'world.html') threw exception Error.
+PASS (new File([], null)).name is 'null'
+PASS (new File([], 12)).name is '12'
+PASS (new File([], '')).name is ''
+PASS (new File([], {})).name is '[object Object]'
+PASS (new File([], document)).name is '[object HTMLDocument]'
+PASS (new File([], toStringingObj)).name is 'A string'
+PASS (new File([], throwingObj)).name threw exception Error.
+PASS (new File([], 'world.html', {unknownKey:'value'})) instanceof window.File is true
+PASS new File([], 'world.html', {type:throwingObj}) threw exception Error.
+PASS (new File([], 'world.html', {type:'helloî'})) instanceof window.File is true
+PASS (new File([], 'world.html', {type:'helloî'})).type is ''
+PASS (new File([], 'world.html', {lastModified: 555, type:'goodbye'})).lastModified is 555
+PASS (new File([], 'world.html', {lastModified: 555, type:'goodbyeî'})).lastModified is not 555
+PASS (new File([], 'world.html', null)) instanceof window.File is true
+PASS (new File([], 'world.html', undefined)) instanceof window.File is true
+PASS (new File([], 'world.html', 123)) instanceof window.File threw exception TypeError: Third argument of the constructor is not of type Object.
+PASS (new File([], 'world.html', 123.4)) instanceof window.File threw exception TypeError: Third argument of the constructor is not of type Object.
+PASS (new File([], 'world.html', true)) instanceof window.File threw exception TypeError: Third argument of the constructor is not of type Object.
+PASS (new File([], 'world.html', 'abc')) instanceof window.File threw exception TypeError: Third argument of the constructor is not of type Object.
+PASS (new File([], 'world.html', [])) instanceof window.File is true
+PASS (new File([], 'world.html', /abc/)) instanceof window.File is true
+PASS (new File([], 'world.html', function () {})) instanceof window.File is true
+PASS (new File([], 'world.html')).name is 'world.html'
+PASS (new File([], 'w/orld/ht/m.l')).name is 'w:orld:ht:m.l'
+PASS (new File([], 'world.html', {type:'text/html'})).name is 'world.html'
+PASS (new File([], 'world.html', {type:'text/html'})).type is 'text/html'
+PASS (new File([], 'world.html', {type:'text/html'})).size is 0
+PASS (new File([], 'world.html', {type:'text/plain;charset=UTF-8'})).type is 'text/plain;charset=utf-8'
+PASS (new File([], 'world.html', {lastModified: 441532800000})).lastModified is 441532800000
+PASS (new File([], 'world.html')).lastModified is equivalent to Date.now().
+PASS (new File([], 'world.html', {})).lastModified is equivalent to Date.now().
+PASS (new File([], 'world.html', {type: 'text/plain'})).lastModified is equivalent to Date.now().
+PASS (new File([], 'world.html', {lastModified: new Date(441532800000)})).lastModified is 441532800000
+PASS window.File.length is 2
+PASS new File([new DataView(new ArrayBuffer(100))], 'world.html').size is 100
+PASS new File([new Uint8Array(100)], 'world.html').size is 100
+PASS new File([new Uint8ClampedArray(100)], 'world.html').size is 100
+PASS new File([new Uint16Array(100)], 'world.html').size is 200
+PASS new File([new Uint32Array(100)], 'world.html').size is 400
+PASS new File([new Int8Array(100)], 'world.html').size is 100
+PASS new File([new Int16Array(100)], 'world.html').size is 200
+PASS new File([new Int32Array(100)], 'world.html').size is 400
+PASS new File([new Float32Array(100)], 'world.html').size is 400
+PASS new File([new Float64Array(100)], 'world.html').size is 800
+PASS new File([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1400
+PASS new File([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1000
+PASS new File([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1200
+PASS new File([(new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 100
+PASS new File([(new Uint8Array(100)).buffer], 'world.html').size is 100
+PASS new File([(new Uint8ClampedArray(100)).buffer], 'world.html').size is 100
+PASS new File([(new Uint16Array(100)).buffer], 'world.html').size is 200
+PASS new File([(new Uint32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Int8Array(100)).buffer], 'world.html').size is 100
+PASS new File([(new Int16Array(100)).buffer], 'world.html').size is 200
+PASS new File([(new Int32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Float32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Float64Array(100)).buffer], 'world.html').size is 800
+PASS new File([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1400
+PASS new File([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1000
+PASS new File([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1200
+PASS new Blob([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size is 1200
+PASS new Blob([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size is 1200
+PASS new File({length: 0}, 'world.txt').size is 0
+PASS new File({length: 1, 0: 'string'}, 'world.txt').size is 6
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastfilesfileconstructorhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/files/file-constructor.html (0 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/files/file-constructor.html                                (rev 0)
+++ trunk/LayoutTests/fast/files/file-constructor.html        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -0,0 +1,149 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+
+&lt;script src=&quot;../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+description(&quot;Test the File constructor.&quot;);
+
+// Test the different ways you can construct a File.
+shouldBeTrue(&quot;(new File([], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['hello'], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['hello'], 'world.html', {})) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['hello'], 'world.html', {type:'text/html'})) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['hello'], 'world.html', {type:'text/html', endings:'native'})) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['hello'], 'world.html', {type:'text/html', endings:'transparent'})) instanceof window.File&quot;);
+
+// Test that File inherits from File.
+shouldBeTrue(&quot;(new File([], 'world.html')) instanceof window.File&quot;)
+
+// Verify that the file name argument is required.
+shouldThrow(&quot;(new File())&quot;, '&quot;TypeError: First argument to File constructor must be a valid sequence, was undefined or null&quot;');
+shouldThrow(&quot;(new File([]))&quot;, '&quot;TypeError: Second argument to File constructor must be a valid string, was undefined&quot;');
+
+// Test valid file names.
+shouldBeTrue(&quot;(new File([], null)) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], 1)) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], '')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], document)) instanceof window.File&quot;);
+
+// Test invalid file parts.
+shouldThrow(&quot;new File('hello', 'world.html')&quot;, '&quot;TypeError: Value is not a sequence&quot;');
+shouldThrow(&quot;new File(0, 'world.html')&quot;, '&quot;TypeError: Value is not a sequence&quot;');
+shouldThrow(&quot;new File(null, 'world.html')&quot;, '&quot;TypeError: First argument to File constructor must be a valid sequence, was undefined or null&quot;');
+
+// Test valid file parts.
+shouldBeTrue(&quot;(new File([], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File(['stringPrimitive'], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([String('stringObject')], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([new Blob], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([new Blob([new Blob])], 'world.html')) instanceof window.File&quot;);
+
+// Test File instances used as blob parts.
+shouldBeTrue(&quot;(new Blob([new File([], 'world.txt')])) instanceof window.Blob&quot;);
+shouldBeTrue(&quot;(new Blob([new Blob([new File([new Blob], 'world.txt')])])) instanceof window.Blob&quot;);
+shouldBeTrue(&quot;(new File([new File([], 'world.txt')], 'world.html')) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([new Blob([new File([new Blob], 'world.txt')])], 'world.html')) instanceof window.File&quot;);
+
+// Test some conversions to string in the parts array.
+shouldBe(&quot;(new File([12], 'world.html')).size&quot;, &quot;2&quot;);
+shouldBe(&quot;(new File([[]], 'world.html')).size&quot;, &quot;0&quot;);         // [].toString() is the empty string
+shouldBe(&quot;(new File([{}], 'world.html')).size&quot;, &quot;15&quot;);;       // {}.toString() is the string &quot;[object Object]&quot;
+shouldBe(&quot;(new File([document], 'world.html')).size&quot;, &quot;21&quot;);  // document.toString() is the string &quot;[object HTMLDocument]&quot;
+
+var toStringingObj = { toString: function() { return &quot;A string&quot;; } };
+shouldBe(&quot;(new File([toStringingObj], 'world.html')).size&quot;, &quot;8&quot;);
+
+var throwingObj = { toString: function() { throw &quot;Error&quot;; } };
+shouldThrow(&quot;new File([throwingObj], 'world.html')&quot;, &quot;'Error'&quot;);
+
+// Test some conversions to string in the file name.
+shouldBe(&quot;(new File([], null)).name&quot;, &quot;'null'&quot;);
+shouldBe(&quot;(new File([], 12)).name&quot;, &quot;'12'&quot;);
+shouldBe(&quot;(new File([], '')).name&quot;, &quot;''&quot;);
+shouldBe(&quot;(new File([], {})).name&quot;, &quot;'[object Object]'&quot;);
+shouldBe(&quot;(new File([], document)).name&quot;, &quot;'[object HTMLDocument]'&quot;);
+shouldBe(&quot;(new File([], toStringingObj)).name&quot;, &quot;'A string'&quot;);
+shouldThrow(&quot;(new File([], throwingObj)).name&quot;, &quot;'Error'&quot;);
+
+// Test some invalid property bags.
+shouldBeTrue(&quot;(new File([], 'world.html', {unknownKey:'value'})) instanceof window.File&quot;);
+shouldThrow(&quot;new File([], 'world.html', {type:throwingObj})&quot;, &quot;'Error'&quot;);
+
+// Type with non-ascii characters should become the empty string.
+shouldBeTrue(&quot;(new File([], 'world.html', {type:'hello\u00EE'})) instanceof window.File&quot;);
+shouldBe(&quot;(new File([], 'world.html', {type:'hello\u00EE'})).type&quot;, &quot;''&quot;);
+
+// FilePropertyBag  substeps: Type with non-ascii characters should prevent lastModified from being extracted.
+shouldBe(&quot;(new File([], 'world.html', {lastModified: 555, type:'goodbye'})).lastModified&quot;, &quot;555&quot;); 
+shouldNotBe(&quot;(new File([], 'world.html', {lastModified: 555, type:'goodbye\u00EE'})).lastModified&quot;, &quot;555&quot;); 
+
+// Test various non-object literals being used as property bags.
+shouldBeTrue(&quot;(new File([], 'world.html', null)) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], 'world.html', undefined)) instanceof window.File&quot;);
+shouldThrow(&quot;(new File([], 'world.html', 123)) instanceof window.File&quot;, &quot;'TypeError: Third argument of the constructor is not of type Object'&quot;);
+shouldThrow(&quot;(new File([], 'world.html', 123.4)) instanceof window.File&quot;, &quot;'TypeError: Third argument of the constructor is not of type Object'&quot;);
+shouldThrow(&quot;(new File([], 'world.html', true)) instanceof window.File&quot;, &quot;'TypeError: Third argument of the constructor is not of type Object'&quot;);
+shouldThrow(&quot;(new File([], 'world.html', 'abc')) instanceof window.File&quot;, &quot;'TypeError: Third argument of the constructor is not of type Object'&quot;);
+shouldBeTrue(&quot;(new File([], 'world.html', [])) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], 'world.html', /abc/)) instanceof window.File&quot;);
+shouldBeTrue(&quot;(new File([], 'world.html', function () {})) instanceof window.File&quot;);
+
+// Test that the name/type/size are correctly added to the File.
+shouldBe(&quot;(new File([], 'world.html')).name&quot;, &quot;'world.html'&quot;);
+shouldBe(&quot;(new File([], 'w/orld/ht/m.l')).name&quot;, &quot;'w:orld:ht:m.l'&quot;);
+shouldBe(&quot;(new File([], 'world.html', {type:'text/html'})).name&quot;, &quot;'world.html'&quot;);
+shouldBe(&quot;(new File([], 'world.html', {type:'text/html'})).type&quot;, &quot;'text/html'&quot;);
+shouldBe(&quot;(new File([], 'world.html', {type:'text/html'})).size&quot;, &quot;0&quot;);
+shouldBe(&quot;(new File([], 'world.html', {type:'text/plain;charset=UTF-8'})).type&quot;, &quot;'text/plain;charset=utf-8'&quot;);
+
+// Test that the lastModified is correctly added to the File.
+var aDate = new Date(441532800000);
+shouldBe(&quot;(new File([], 'world.html', {lastModified: 441532800000})).lastModified&quot;, &quot;441532800000&quot;);
+// Unless specified, lastModified should default to now.
+shouldBeNow(&quot;(new File([], 'world.html')).lastModified&quot;, 20000);
+shouldBeNow(&quot;(new File([], 'world.html', {})).lastModified&quot;, 20000);
+shouldBeNow(&quot;(new File([], 'world.html', {type: 'text/plain'})).lastModified&quot;, 20000);
+// Test that Date instances are implicitly converted to numbers.
+shouldBe(&quot;(new File([], 'world.html', {lastModified: new Date(441532800000)})).lastModified&quot;, &quot;441532800000&quot;);
+
+// Test the number of expected arguments in the File constructor.
+shouldBe(&quot;window.File.length&quot;, &quot;2&quot;);
+
+// Test ArrayBufferView parameters.
+shouldBe(&quot;new File([new DataView(new ArrayBuffer(100))], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([new Uint8Array(100)], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([new Uint8ClampedArray(100)], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([new Uint16Array(100)], 'world.html').size&quot;, &quot;200&quot;);
+shouldBe(&quot;new File([new Uint32Array(100)], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([new Int8Array(100)], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([new Int16Array(100)], 'world.html').size&quot;, &quot;200&quot;);
+shouldBe(&quot;new File([new Int32Array(100)], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([new Float32Array(100)], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([new Float64Array(100)], 'world.html').size&quot;, &quot;800&quot;);
+shouldBe(&quot;new File([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size&quot;, &quot;1400&quot;);
+shouldBe(&quot;new File([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size&quot;, &quot;1000&quot;);
+shouldBe(&quot;new File([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size&quot;, &quot;1200&quot;);
+
+// Test ArrayBuffer parameters.
+shouldBe(&quot;new File([(new DataView(new ArrayBuffer(100))).buffer], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([(new Uint8Array(100)).buffer], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([(new Uint8ClampedArray(100)).buffer], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([(new Uint16Array(100)).buffer], 'world.html').size&quot;, &quot;200&quot;);
+shouldBe(&quot;new File([(new Uint32Array(100)).buffer], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([(new Int8Array(100)).buffer], 'world.html').size&quot;, &quot;100&quot;);
+shouldBe(&quot;new File([(new Int16Array(100)).buffer], 'world.html').size&quot;, &quot;200&quot;);
+shouldBe(&quot;new File([(new Int32Array(100)).buffer], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([(new Float32Array(100)).buffer], 'world.html').size&quot;, &quot;400&quot;);
+shouldBe(&quot;new File([(new Float64Array(100)).buffer], 'world.html').size&quot;, &quot;800&quot;);
+shouldBe(&quot;new File([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size&quot;, &quot;1400&quot;);
+shouldBe(&quot;new File([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size&quot;, &quot;1000&quot;);
+shouldBe(&quot;new File([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size&quot;, &quot;1200&quot;);
+
+// Test building Blobs with ArrayBuffer / ArrayBufferView parts enclosed in files.
+shouldBe(&quot;new Blob([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size&quot;, &quot;1200&quot;);
+shouldBe(&quot;new Blob([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size&quot;, &quot;1200&quot;);
+
+// Test passing blob parts in objects with indexed properties.
+// (This depends on the bindings code handling of sequence&lt;T&gt;)
+shouldBe(&quot;new File({length: 0}, 'world.txt').size&quot;, &quot;0&quot;);
+shouldBe(&quot;new File({length: 1, 0: 'string'}, 'world.txt').size&quot;, &quot;6&quot;);
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestslocalfileapifilelastmodifiedafterdeleteexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-after-delete-expected.txt (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-after-delete-expected.txt        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-after-delete-expected.txt        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -4,9 +4,9 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> PASS event.dataTransfer contains a File object on drop.
</span><del>-PASS lastModifiedDate is not null
-PASS lastModifiedDate is &gt;= testStartTime
-PASS (new Date()).getTime() is &gt;= lastModifiedDate
</del><ins>+PASS lastModified is not null
+PASS lastModified is &gt;= testStartTime.getTime()
+PASS (new Date()).getTime() is &gt;= lastModified
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestshttptestslocalfileapifilelastmodifiedexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-expected.txt (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-expected.txt        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/http/tests/local/fileapi/file-last-modified-expected.txt        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -4,7 +4,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> PASS event.dataTransfer contains a File object on drop.
</span><del>-PASS file.lastModifiedDate verified
</del><ins>+PASS file.lastModified verified
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestshttptestslocalfileapiscripttestsfilelastmodifiedafterdeletejs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified-after-delete.js        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -10,13 +10,13 @@
</span><span class="cx">     // Remove the temp file.
</span><span class="cx">     removeTempFile(tempFileName);
</span><span class="cx"> 
</span><del>-    // This synchronosly queries the file's lastModifiedDate (which should fail) until/unless we start capturing the file metadata at File construction time.
-    lastModifiedDate = file.lastModifiedDate;
</del><ins>+    // This synchronosly queries the file's lastModified (which should fail) until/unless we start capturing the file metadata at File construction time.
+    lastModified = file.lastModified;
</ins><span class="cx"> 
</span><span class="cx">     // The returned value should be equal to the current date/time since the file's modified date/time is not available.
</span><del>-    shouldNotBe('lastModifiedDate', 'null');
-    shouldBeGreaterThanOrEqual('lastModifiedDate', 'testStartTime');
-    shouldBeGreaterThanOrEqual('(new Date()).getTime()', 'lastModifiedDate');
</del><ins>+    shouldNotBe('lastModified', 'null');
+    shouldBeGreaterThanOrEqual('lastModified', 'testStartTime.getTime()');
+    shouldBeGreaterThanOrEqual('(new Date()).getTime()', 'lastModified');
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function runTest()
</span></span></pre></div>
<a id="trunkLayoutTestshttptestslocalfileapiscripttestsfilelastmodifiedjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified.js (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified.js        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/http/tests/local/fileapi/script-tests/file-last-modified.js        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -6,11 +6,11 @@
</span><span class="cx">     xhr.open(&quot;GET&quot;, &quot;http://127.0.0.1:8000/resources/file-last-modified.php?path=../local/fileapi/&quot; + filePath, false);
</span><span class="cx">     xhr.send();
</span><span class="cx">     var expectedDate = new Date(parseInt(xhr.responseText) * 1000);
</span><del>-    var actualDate = file.lastModifiedDate;
-    if (expectedDate.toString() == actualDate.toString())
-        testPassed(&quot;file.lastModifiedDate verified&quot;);
</del><ins>+    var actualDate = file.lastModified;
+    if (expectedDate.getTime() == actualDate)
+        testPassed(&quot;file.lastModified verified&quot;);
</ins><span class="cx">     else
</span><del>-        testFailed(&quot;file.lastModifiedDate incorrect&quot;);
</del><ins>+        testFailed(&quot;file.lastModified incorrect&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function runTest()
</span></span></pre></div>
<a id="trunkLayoutTestsimportedblinkstorageindexeddbblobbasicsmetadataexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/LayoutTests/imported/blink/storage/indexeddb/blob-basics-metadata-expected.txt        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -39,18 +39,16 @@
</span><span class="cx"> 
</span><span class="cx"> testNewFile():
</span><span class="cx"> newFile = new File([test_content], 'filename', {type:'text/plain'})
</span><del>-FAIL newFile = new File([test_content], 'filename', {type:'text/plain'}) threw exception TypeError: function is not a constructor (evaluating 'new File([test_content], 'filename', {type:'text/plain'})')
</del><span class="cx"> 
</span><span class="cx"> validateResult(newFile):
</span><del>-FAIL newFile.name == newFile.name should be true. Threw exception ReferenceError: Can't find variable: newFile
</del><ins>+PASS newFile.name == newFile.name is true
</ins><span class="cx"> transaction = db.transaction('storeName', 'readwrite')
</span><span class="cx"> store = transaction.objectStore('storeName')
</span><span class="cx"> store.put(newFile, 'newFilekey')
</span><del>-FAIL store.put(newFile, 'newFilekey') threw exception ReferenceError: Can't find variable: newFile
</del><span class="cx"> transaction = db.transaction('storeName', 'readwrite')
</span><span class="cx"> store = transaction.objectStore('storeName')
</span><span class="cx"> request = store.get('newFilekey')
</span><del>-FAIL event.target.result.name == newFile.name should be true. Threw exception TypeError: undefined is not an object (evaluating 'event.target.result.name')
</del><ins>+PASS event.target.result.name == newFile.name is true
</ins><span class="cx"> 
</span><span class="cx"> testFileList():
</span><span class="cx"> filelist = fileInput.files
</span><span class="lines">@@ -77,10 +75,10 @@
</span><span class="cx"> cursor.continue();
</span><span class="cx"> PASS cursor.value == 'value' is true
</span><span class="cx"> cursor.continue();
</span><del>-FAIL cursor.value.name == newFile.name should be true. Threw exception TypeError: null is not an object (evaluating 'cursor.value')
</del><ins>+PASS cursor.value.name == newFile.name is true
</ins><span class="cx"> cursor.continue();
</span><del>-FAIL Unexpected error: TypeError: null is not an object (evaluating 'cursor.continue')
-FAIL successfullyParsed should be true. Was false.
</del><ins>+PASS cursor is null
+PASS successfullyParsed is true
</ins><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -1143,6 +1143,7 @@
</span><span class="cx">     bindings/js/JSEventTargetCustom.cpp
</span><span class="cx">     bindings/js/JSExceptionBase.cpp
</span><span class="cx">     bindings/js/JSFetchResponseCustom.cpp
</span><ins>+    bindings/js/JSFileCustom.cpp
</ins><span class="cx">     bindings/js/JSFileReaderCustom.cpp
</span><span class="cx">     bindings/js/JSGeolocationCustom.cpp
</span><span class="cx">     bindings/js/JSHTMLAllCollectionCustom.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/ChangeLog        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2016-04-25  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Implement latest File object spec (including its constructor).
+        https://bugs.webkit.org/show_bug.cgi?id=156511
+
+        Reviewed by Darin Adler.
+
+        Test: fast/files/file-constructor.html
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * bindings/js/JSDictionary.cpp:
+        (WebCore::JSDictionary::convertValue):
+        * bindings/js/JSDictionary.h:
+
+        * bindings/js/JSFileCustom.cpp: Added.
+        (WebCore::constructJSFile):
+
+        * fileapi/File.cpp:
+        (WebCore::File::File):
+        (WebCore::File::lastModified):
+        (WebCore::File::lastModifiedDate): Deleted.
+        * fileapi/File.h:
+        * fileapi/File.idl:
+
</ins><span class="cx"> 2016-04-25  Antti Koivisto  &lt;antti@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r156846): Crashes with guard malloc
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -2058,6 +2058,7 @@
</span><span class="cx">                 516D7D701BB5F0BD00AF7C77 /* IDBConnectionToServerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5185FCBD1BB5CB770012898F /* IDBConnectionToServerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 516D7D711BB5F0BD00AF7C77 /* IDBConnectionToClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */; };
</span><span class="cx">                 516D7D721BB5F0BD00AF7C77 /* IDBConnectionToClientDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                516E54FA1CCB2EA80040D954 /* JSFileCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516E54F91CCB27FF0040D954 /* JSFileCustom.cpp */; };
</ins><span class="cx">                 516F7F6D1C31E39A00F111DC /* ServerOpenDBRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 516F7F6C1C31C79D00F111DC /* ServerOpenDBRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 516F7F6E1C31E39C00F111DC /* ServerOpenDBRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516F7F6B1C31C79D00F111DC /* ServerOpenDBRequest.cpp */; };
</span><span class="cx">                 517138EF1BED1D1A000D5F01 /* IndexKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138ED1BED1D17000D5F01 /* IndexKey.cpp */; };
</span><span class="lines">@@ -9644,6 +9645,7 @@
</span><span class="cx">                 516C62241950E2B900337E75 /* JSGamepadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGamepadEvent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBConnectionToClient.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBConnectionToClientDelegate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                516E54F91CCB27FF0040D954 /* JSFileCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFileCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 516F7F6B1C31C79D00F111DC /* ServerOpenDBRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServerOpenDBRequest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 516F7F6C1C31C79D00F111DC /* ServerOpenDBRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerOpenDBRequest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 517138ED1BED1D17000D5F01 /* IndexKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexKey.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -22447,6 +22449,7 @@
</span><span class="cx">                                 BC2ED5540C6B9BD300920BFF /* JSElementCustom.cpp */,
</span><span class="cx">                                 ADEC78F718EE5308001315C2 /* JSElementCustom.h */,
</span><span class="cx">                                 BCEFAF4D0C317E6900FA81F6 /* JSEventCustom.cpp */,
</span><ins>+                                516E54F91CCB27FF0040D954 /* JSFileCustom.cpp */,
</ins><span class="cx">                                 2E7582ED12764F260062628B /* JSFileReaderCustom.cpp */,
</span><span class="cx">                                 C28083411C6DC96A001451B6 /* JSFontFaceCustom.cpp */,
</span><span class="cx">                                 1C24EEAA1C72AA0A0080F8FC /* JSFontFaceSetCustom.cpp */,
</span><span class="lines">@@ -30243,6 +30246,7 @@
</span><span class="cx">                                 2E0888E6114884E200AF4265 /* JSDOMFormDataCustom.cpp in Sources */,
</span><span class="cx">                                 E1C36CBD0EB08062007410BC /* JSDOMGlobalObject.cpp in Sources */,
</span><span class="cx">                                 7C2BDD3D17C7F98C0038FF15 /* JSDOMGlobalObjectTask.cpp in Sources */,
</span><ins>+                                516E54FA1CCB2EA80040D954 /* JSFileCustom.cpp in Sources */,
</ins><span class="cx">                                 65DF31F709D1CC60000BE325 /* JSDOMImplementation.cpp in Sources */,
</span><span class="cx">                                 A9D248060D757E7D00FDF959 /* JSDOMMimeType.cpp in Sources */,
</span><span class="cx">                                 A9D248080D757E7D00FDF959 /* JSDOMMimeTypeArray.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDictionarycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDictionary.cpp (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDictionary.cpp        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/bindings/js/JSDictionary.cpp        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -98,6 +98,11 @@
</span><span class="cx">     result = value.toInt32(exec);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSDictionary::convertValue(ExecState* exec, JSValue value, long int&amp; result)
+{
+    result = value.toInt32(exec);
+}
+
</ins><span class="cx"> void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned&amp; result)
</span><span class="cx"> {
</span><span class="cx">     result = value.toUInt32(exec);
</span><span class="lines">@@ -119,6 +124,12 @@
</span><span class="cx">     doubleToInteger(d, result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSDictionary::convertValue(ExecState* exec, JSValue value, long long&amp; result)
+{
+    double d = value.toNumber(exec);
+    result = llrint(d);
+}
+
</ins><span class="cx"> void JSDictionary::convertValue(ExecState* exec, JSValue value, double&amp; result)
</span><span class="cx"> {
</span><span class="cx">     result = value.toNumber(exec);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDictionaryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDictionary.h (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDictionary.h        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/bindings/js/JSDictionary.h        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -117,10 +117,12 @@
</span><span class="cx">     
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, bool&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, int&amp; result);
</span><ins>+    static void convertValue(JSC::ExecState*, JSC::JSValue, long int&amp; result);
</ins><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned short&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long long&amp; result);
</span><ins>+    static void convertValue(JSC::ExecState*, JSC::JSValue, long long&amp; result);
</ins><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, double&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, Dictionary&amp; result);
</span><span class="cx">     static void convertValue(JSC::ExecState*, JSC::JSValue, String&amp; result);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSFileCustomcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/bindings/js/JSFileCustom.cpp (0 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSFileCustom.cpp                                (rev 0)
+++ trunk/Source/WebCore/bindings/js/JSFileCustom.cpp        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;JSFile.h&quot;
+
+#include &quot;JSDOMBinding.h&quot;
+#include &quot;JSDictionary.h&quot;
+#include &quot;WebKitBlobBuilder.h&quot;
+#include &lt;runtime/Error.h&gt;
+#include &lt;runtime/JSArray.h&gt;
+#include &lt;runtime/JSArrayBuffer.h&gt;
+#include &lt;runtime/JSArrayBufferView.h&gt;
+#include &lt;wtf/Assertions.h&gt;
+#include &lt;wtf/CurrentTime.h&gt;
+
+using namespace JSC;
+
+namespace WebCore {
+
+EncodedJSValue JSC_HOST_CALL constructJSFile(ExecState* exec)
+{
+    auto* constructor = jsCast&lt;DOMConstructorObject*&gt;(exec-&gt;callee());
+    ScriptExecutionContext* context = constructor-&gt;scriptExecutionContext();
+    if (!context)
+        return throwVMError(exec, createReferenceError(exec, &quot;File constructor associated document is unavailable&quot;));
+
+    JSValue arg = exec-&gt;argument(0);
+    if (arg.isUndefinedOrNull())
+        return throwVMError(exec, createTypeError(exec, &quot;First argument to File constructor must be a valid sequence, was undefined or null&quot;));
+
+    unsigned blobPartsLength = 0;
+    JSObject* blobParts = toJSSequence(exec, arg, blobPartsLength);
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+    ASSERT(blobParts);
+
+    arg = exec-&gt;argument(1);
+    if (arg.isUndefined())
+        return throwVMError(exec, createTypeError(exec, &quot;Second argument to File constructor must be a valid string, was undefined&quot;));
+
+    String filename = arg.toWTFString(exec).replace('/', ':');
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    String normalizedType;
+    Optional&lt;int64_t&gt; lastModified;
+
+    arg = exec-&gt;argument(2);
+    if (!arg.isUndefinedOrNull()) {
+        JSObject* filePropertyBagObject = arg.getObject();
+        if (!filePropertyBagObject)
+            return throwVMError(exec, createTypeError(exec, &quot;Third argument of the constructor is not of type Object&quot;));
+
+        // Create the dictionary wrapper from the initializer object.
+        JSDictionary dictionary(exec, filePropertyBagObject);
+
+        // Attempt to get the type property.
+        String type;
+        dictionary.get(&quot;type&quot;, type);
+        if (exec-&gt;hadException())
+            return JSValue::encode(jsUndefined());
+
+        normalizedType = Blob::normalizedContentType(type);
+
+        // Only try to parse the lastModified date if there was not an invalid type argument.
+        if (type.isEmpty() ||  !normalizedType.isEmpty()) {
+            dictionary.get(&quot;lastModified&quot;, lastModified);
+            if (exec-&gt;hadException())
+                return JSValue::encode(jsUndefined());
+        }
+    }
+
+    if (!lastModified)
+        lastModified = currentTimeMS();
+
+    BlobBuilder blobBuilder;
+
+    for (unsigned i = 0; i &lt; blobPartsLength; ++i) {
+        JSValue item = blobParts-&gt;get(exec, i);
+        if (exec-&gt;hadException())
+            return JSValue::encode(jsUndefined());
+
+        if (ArrayBuffer* arrayBuffer = toArrayBuffer(item))
+            blobBuilder.append(arrayBuffer);
+        else if (RefPtr&lt;ArrayBufferView&gt; arrayBufferView = toArrayBufferView(item))
+            blobBuilder.append(WTFMove(arrayBufferView));
+        else if (Blob* blob = JSBlob::toWrapped(item))
+            blobBuilder.append(blob);
+        else {
+            String string = item.toWTFString(exec);
+            if (exec-&gt;hadException())
+                return JSValue::encode(jsUndefined());
+            blobBuilder.append(string, ASCIILiteral(&quot;transparent&quot;));
+        }
+    }
+
+    auto file = File::create(blobBuilder.finalize(), filename, normalizedType, lastModified.value());
+
+    return JSValue::encode(CREATE_DOM_WRAPPER(constructor-&gt;globalObject(), File, &amp;file.get()));
+}
+
+} // namespace WebCore
+
</ins></span></pre></div>
<a id="trunkSourceWebCorefileapiFilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/fileapi/File.cpp (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/fileapi/File.cpp        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/fileapi/File.cpp        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -64,8 +64,21 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-double File::lastModifiedDate() const
</del><ins>+File::File(Vector&lt;BlobPart&gt;&amp;&amp; blobParts, const String&amp; filename, const String&amp; contentType, int64_t lastModified)
+    : Blob(WTFMove(blobParts), contentType)
+    , m_name(filename)
+    , m_overrideLastModifiedDate(lastModified)
</ins><span class="cx"> {
</span><ins>+}
+
+double File::lastModified() const
+{
+    if (m_overrideLastModifiedDate)
+        return m_overrideLastModifiedDate.value();
+
+    // FIXME: This does sync-i/o on the main thread and also recalculates every time the method is called.
+    // The i/o should be performed on a background thread,
+    // and the result should be cached along with an asynchronous monitor for changes to the file.
</ins><span class="cx">     time_t modificationTime;
</span><span class="cx">     if (getFileModificationTime(m_path, modificationTime) &amp;&amp; isValidFileTime(modificationTime))
</span><span class="cx">         return modificationTime * msPerSecond;
</span></span></pre></div>
<a id="trunkSourceWebCorefileapiFileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/fileapi/File.h (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/fileapi/File.h        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/fileapi/File.h        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define File_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Blob.h&quot;
</span><ins>+#include &lt;wtf/Optional.h&gt;
</ins><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> #include &lt;wtf/TypeCasts.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="lines">@@ -42,6 +43,12 @@
</span><span class="cx">         return adoptRef(*new File(path));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Create a File using the 'new File' constructor.
+    static Ref&lt;File&gt; create(Vector&lt;BlobPart&gt; blobParts, const String&amp; filename, const String&amp; contentType, int64_t lastModified)
+    {
+        return adoptRef(*new File(WTFMove(blobParts), filename, contentType, lastModified));
+    }
+
</ins><span class="cx">     static Ref&lt;File&gt; deserialize(const String&amp; path, const URL&amp; srcURL, const String&amp; type, const String&amp; name)
</span><span class="cx">     {
</span><span class="cx">         return adoptRef(*new File(deserializationContructor, path, srcURL, type, name));
</span><span class="lines">@@ -59,10 +66,8 @@
</span><span class="cx"> 
</span><span class="cx">     const String&amp; path() const { return m_path; }
</span><span class="cx">     const String&amp; name() const { return m_name; }
</span><ins>+    double lastModified() const;
</ins><span class="cx"> 
</span><del>-    // This returns the current date and time if the file's last modification date is not known (per spec: http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate).
-    double lastModifiedDate() const;
-
</del><span class="cx">     static String contentTypeForFile(const String&amp; path);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FILE_REPLACEMENT)
</span><span class="lines">@@ -72,6 +77,7 @@
</span><span class="cx"> private:
</span><span class="cx">     WEBCORE_EXPORT explicit File(const String&amp; path);
</span><span class="cx">     File(const String&amp; path, const String&amp; nameOverride);
</span><ins>+    File(Vector&lt;BlobPart&gt;&amp;&amp; blobParts, const String&amp; filename, const String&amp; contentType, int64_t lastModified);
</ins><span class="cx"> 
</span><span class="cx">     File(DeserializationContructor, const String&amp; path, const URL&amp; srcURL, const String&amp; type, const String&amp; name);
</span><span class="cx"> 
</span><span class="lines">@@ -82,6 +88,9 @@
</span><span class="cx"> 
</span><span class="cx">     String m_path;
</span><span class="cx">     String m_name;
</span><ins>+
+    Optional&lt;String&gt; m_overrideFilename;
+    Optional&lt;int64_t&gt; m_overrideLastModifiedDate;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorefileapiFileidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/fileapi/File.idl (200031 => 200032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/fileapi/File.idl        2016-04-25 17:03:04 UTC (rev 200031)
+++ trunk/Source/WebCore/fileapi/File.idl        2016-04-25 17:31:29 UTC (rev 200032)
</span><span class="lines">@@ -24,13 +24,13 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> [
</span><ins>+    Exposed=(Window),
</ins><span class="cx">     JSGenerateToNativeObject,
</span><span class="cx">     JSGenerateToJSObject,
</span><span class="cx">     ExportMacro=WEBCORE_EXPORT,
</span><ins>+    CustomConstructor(sequence&lt;any&gt; fileBits, DOMString fileName, optional FilePropertyBag options),
</ins><span class="cx"> ] interface File : Blob {
</span><span class="cx">     readonly attribute DOMString name;
</span><del>-#if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT
-    readonly attribute Date lastModifiedDate;
-#endif
</del><ins>+    readonly attribute long long lastModified;
</ins><span class="cx"> };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>