diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index 2ef0479ab9b..e0d260b2b78 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -119,23 +119,11 @@ impl Blob { // TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView let bytes: Vec = match blobParts { None => Vec::new(), - Some(blobs) => { - blobs.iter().flat_map(|bPart| { - match bPart { - &BlobOrString::String(ref s) => { - UTF_8.encode(s, EncoderTrap::Replace).unwrap() - }, - &BlobOrString::Blob(ref b) => { - b.get_data().get_bytes().to_vec() - }, - } - }) - .collect() - } + Some(blobparts) => blob_parts_to_bytes(blobparts), }; let slice = DataSlice::new(Arc::new(bytes), None, None); - Ok(Blob::new(global, slice, blobPropertyBag.get_typestring())) + Ok(Blob::new(global, slice, &blobPropertyBag.get_typestring())) } pub fn get_data(&self) -> &DataSlice { @@ -143,6 +131,19 @@ impl Blob { } } +pub fn blob_parts_to_bytes(blobparts: Vec) -> Vec { + blobparts.iter().flat_map(|blobpart| { + match blobpart { + &BlobOrString::String(ref s) => { + UTF_8.encode(s, EncoderTrap::Replace).unwrap() + }, + &BlobOrString::Blob(ref b) => { + b.get_data().get_bytes().to_vec() + }, + } + }).collect::>() +} + impl BlobMethods for Blob { // https://w3c.github.io/FileAPI/#dfn-size fn Size(&self) -> u64 { @@ -199,11 +200,11 @@ impl BlobMethods for Blob { impl BlobBinding::BlobPropertyBag { - pub fn get_typestring(&self) -> &str { + pub fn get_typestring(&self) -> String { if is_ascii_printable(&self.type_) { - &*self.type_ + self.type_.to_lowercase() } else { - "" + "".to_string() } } } diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs index 598537cbe00..9667182671a 100644 --- a/components/script/dom/file.rs +++ b/components/script/dom/file.rs @@ -4,45 +4,78 @@ use dom::bindings::codegen::Bindings::FileBinding; use dom::bindings::codegen::Bindings::FileBinding::FileMethods; +use dom::bindings::codegen::UnionTypes::BlobOrString; +use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::reflector::reflect_dom_object; -use dom::blob::Blob; +use dom::blob::{Blob, DataSlice, blob_parts_to_bytes}; use std::sync::Arc; +use time; use util::str::DOMString; #[dom_struct] pub struct File { blob: Blob, name: DOMString, + modified: i64, } impl File { - fn new_inherited(file_bits: &Blob, name: DOMString) -> File { - // TODO: FilePropertyBag - let mut bytes = Vec::new(); - bytes.extend_from_slice(file_bits.get_data().get_all_bytes().as_slice()); - + fn new_inherited(slice: DataSlice, name: DOMString, + modified: Option, typeString: &str) -> File { File { - blob: Blob::new_inherited(Arc::new(bytes), None, None, ""), + blob: Blob::new_inherited(slice, typeString), name: name, + // https://w3c.github.io/FileAPI/#dfn-lastModified + modified: match modified { + Some(m) => m, + None => { + let time = time::get_time(); + time.sec * 1000 + (time.nsec / 1000000) as i64 + } + }, } } - pub fn new(global: GlobalRef, file_bits: &Blob, name: DOMString) -> Root { - reflect_dom_object(box File::new_inherited(file_bits, name), + pub fn new(global: GlobalRef, slice: DataSlice, + name: DOMString, modified: Option, typeString: &str) -> Root { + reflect_dom_object(box File::new_inherited(slice, name, modified, typeString), global, FileBinding::Wrap) } + // https://w3c.github.io/FileAPI/#file-constructor + pub fn Constructor(global: GlobalRef, + fileBits: Vec, + filename: DOMString, + filePropertyBag: &FileBinding::FilePropertyBag) + -> Fallible> { + let bytes: Vec = blob_parts_to_bytes(fileBits); + + let ref blobPropertyBag = filePropertyBag.parent; + let typeString = blobPropertyBag.get_typestring(); + + let slice = DataSlice::new(Arc::new(bytes), None, None); + let modified = filePropertyBag.lastModified; + Ok(File::new(global, slice, filename, modified, &typeString)) + } + pub fn name(&self) -> &DOMString { &self.name } + } impl FileMethods for File { + // https://w3c.github.io/FileAPI/#dfn-name fn Name(&self) -> DOMString { self.name.clone() } + + // https://w3c.github.io/FileAPI/#dfn-lastModified + fn LastModified(&self) -> i64 { + self.modified + } } diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs index 6f6b47d42ce..f396a79660c 100644 --- a/components/script/dom/formdata.rs +++ b/components/script/dom/formdata.rs @@ -128,7 +128,7 @@ impl FormData { Some(fname) => { let global = self.global(); let name = DOMString::from(fname.0); - Root::upcast(File::new(global.r(), value, name)) + Root::upcast(File::new(global.r(), value.get_data().clone(), name, None, "")) } None => Root::from_ref(value) } diff --git a/components/script/dom/webidls/File.webidl b/components/script/dom/webidls/File.webidl index 7c0d4be7c29..6e7797c4d5e 100644 --- a/components/script/dom/webidls/File.webidl +++ b/components/script/dom/webidls/File.webidl @@ -2,13 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// http://dev.w3.org/2006/webapi/FileAPI/#dfn-file +// https://w3c.github.io/FileAPI/#file -// [Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits, -// [EnsureUTF16] DOMString fileName, optional FilePropertyBag options)] +[Constructor(sequence fileBits, + DOMString fileName, + optional FilePropertyBag options), + Exposed=Window/*,Worker*/] interface File : Blob { - readonly attribute DOMString name; - // readonly attribute Date lastModifiedDate; - + readonly attribute long long lastModified; +}; + +dictionary FilePropertyBag : BlobPropertyBag { + long long lastModified; }; diff --git a/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini b/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini index 88e2fe94e2f..a0c942de8ce 100644 --- a/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini +++ b/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini @@ -1,17 +1,5 @@ [File-constructor.html] type: testharness - [DOMString fileBits] - expected: FAIL - - [Unicode DOMString fileBits] - expected: FAIL - - [Empty Blob fileBits] - expected: FAIL - - [Blob fileBits] - expected: FAIL - [ArrayBuffer fileBits] expected: FAIL @@ -21,24 +9,5 @@ [Various fileBits] expected: FAIL - [Using fileName] - expected: FAIL - [Using special character in fileName] expected: FAIL - - [Using type on the File constructor] - expected: FAIL - - [Using uppercase characters in type] - expected: FAIL - - [Using illegal character for type] - expected: FAIL - - [Using lastModified] - expected: FAIL - - [Misusing name] - expected: FAIL - diff --git a/tests/wpt/metadata/FileAPI/file/Worker-read-file-constructor.worker.js.ini b/tests/wpt/metadata/FileAPI/file/Worker-read-file-constructor.worker.js.ini deleted file mode 100644 index 0a9b6879919..00000000000 --- a/tests/wpt/metadata/FileAPI/file/Worker-read-file-constructor.worker.js.ini +++ /dev/null @@ -1,5 +0,0 @@ -[Worker-read-file-constructor.worker] - type: testharness - [FileReader in Worker] - expected: FAIL - diff --git a/tests/wpt/metadata/FileAPI/idlharness.html.ini b/tests/wpt/metadata/FileAPI/idlharness.html.ini index c91eb848d80..33a274d116f 100644 --- a/tests/wpt/metadata/FileAPI/idlharness.html.ini +++ b/tests/wpt/metadata/FileAPI/idlharness.html.ini @@ -9,42 +9,6 @@ [URL interface: operation revokeObjectURL(DOMString)] expected: FAIL - [File interface object length] - expected: FAIL - - [File interface: attribute lastModified] - expected: FAIL - - [File must be primary interface of new File(["myFileBits"\], "myFileName")] - expected: FAIL - - [Stringification of new File(["myFileBits"\], "myFileName")] - expected: FAIL - - [File interface: new File(["myFileBits"\], "myFileName") must inherit property "name" with the proper type (0)] - expected: FAIL - - [File interface: new File(["myFileBits"\], "myFileName") must inherit property "lastModified" with the proper type (1)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "size" with the proper type (0)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "type" with the proper type (1)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "isClosed" with the proper type (2)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "slice" with the proper type (3)] - expected: FAIL - - [Blob interface: calling slice(long long,long long,DOMString) on new File(["myFileBits"\], "myFileName") with too few arguments must throw TypeError] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "close" with the proper type (4)] - expected: FAIL - [FileList must be primary interface of file_input.files] expected: FAIL diff --git a/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini b/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini index 33363991f7e..d9f9c83bdc3 100644 --- a/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini +++ b/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini @@ -9,42 +9,6 @@ [URL interface: operation revokeObjectURL(DOMString)] expected: FAIL - [File interface object length] - expected: FAIL - - [File interface: attribute lastModified] - expected: FAIL - - [File must be primary interface of new File(["myFileBits"\], "myFileName")] - expected: FAIL - - [Stringification of new File(["myFileBits"\], "myFileName")] - expected: FAIL - - [File interface: new File(["myFileBits"\], "myFileName") must inherit property "name" with the proper type (0)] - expected: FAIL - - [File interface: new File(["myFileBits"\], "myFileName") must inherit property "lastModified" with the proper type (1)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "size" with the proper type (0)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "type" with the proper type (1)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "isClosed" with the proper type (2)] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "slice" with the proper type (3)] - expected: FAIL - - [Blob interface: calling slice(long long,long long,DOMString) on new File(["myFileBits"\], "myFileName") with too few arguments must throw TypeError] - expected: FAIL - - [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "close" with the proper type (4)] - expected: FAIL - [FileReader interface: operation readAsArrayBuffer(Blob)] expected: FAIL