diff options
author | Shing Lyu <shing.lyu@gmail.com> | 2014-12-22 23:45:00 +0800 |
---|---|---|
committer | Shing Lyu <shing.lyu@gmail.com> | 2015-01-01 16:23:21 +0800 |
commit | 6df9b7fd3a68fb4a020641192c8ee59a98ae08dd (patch) | |
tree | 91104c0bcbb9b42a27347ed46049256503efcb85 | |
parent | 37a97f3273c442fa59a3f65e8300a2527b004036 (diff) | |
download | servo-6df9b7fd3a68fb4a020641192c8ee59a98ae08dd.tar.gz servo-6df9b7fd3a68fb4a020641192c8ee59a98ae08dd.zip |
Bug #1820, add the optional "type" parameter to Blob
-rw-r--r-- | components/script/dom/blob.rs | 46 | ||||
-rw-r--r-- | components/script/dom/file.rs | 3 | ||||
-rw-r--r-- | components/script/dom/testbinding.rs | 8 | ||||
-rw-r--r-- | components/script/dom/webidls/Blob.webidl | 2 | ||||
-rw-r--r-- | tests/content/test_blob.html | 28 | ||||
-rw-r--r-- | tests/wpt/metadata/FileAPI/Blob-constructor.html.ini | 30 |
6 files changed, 66 insertions, 51 deletions
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index 042536efc52..8532f37751a 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -12,6 +12,7 @@ use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use servo_util::str::DOMString; use std::cmp::{min, max}; +use std::ascii::AsciiExt; #[jstraceable] pub enum BlobTypeId { @@ -29,34 +30,46 @@ pub struct Blob { // isClosed_: bool } +fn is_ascii_printable(string: &DOMString) -> bool{ + // Step 5.1 in Sec 5.1 of File API spec + // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob + return string.chars().all(|c| { c >= '\x20' && c <= '\x7E' }) +} + impl Blob { pub fn new_inherited(global: &GlobalRef, type_: BlobTypeId, - bytes: Option<Vec<u8>>) -> Blob { + bytes: Option<Vec<u8>>, typeString: &str) -> Blob { Blob { reflector_: Reflector::new(), type_: type_, bytes: bytes, - typeString: "".into_string(), + typeString: typeString.into_string(), global: GlobalField::from_rooted(global) //isClosed_: false } } - pub fn new(global: &GlobalRef, bytes: Option<Vec<u8>>) -> Temporary<Blob> { - reflect_dom_object(box Blob::new_inherited(global, BlobTypeId::Blob, bytes), + pub fn new(global: &GlobalRef, bytes: Option<Vec<u8>>, + typeString: &str) -> Temporary<Blob> { + reflect_dom_object(box Blob::new_inherited(global, BlobTypeId::Blob, bytes, typeString), *global, BlobBinding::Wrap) } pub fn Constructor(global: &GlobalRef) -> Fallible<Temporary<Blob>> { - Ok(Blob::new(global, None)) + Ok(Blob::new(global, None, "")) } - pub fn Constructor_(global: &GlobalRef, blobParts: DOMString) -> Fallible<Temporary<Blob>> { + pub fn Constructor_(global: &GlobalRef, blobParts: DOMString, blobPropertyBag: &BlobBinding::BlobPropertyBag) -> Fallible<Temporary<Blob>> { //TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob - //TODO: accept options parameter let bytes: Option<Vec<u8>> = Some(blobParts.into_bytes()); - Ok(Blob::new(global, bytes)) + let typeString = if is_ascii_printable(&blobPropertyBag.type_) { + blobPropertyBag.type_.as_slice() + } else { + "" + }; + let typeStrLower = typeString.as_slice().to_ascii_lower(); + Ok(Blob::new(global, bytes, typeStrLower.as_slice())) } } @@ -73,7 +86,7 @@ impl<'a> BlobMethods for JSRef<'a, Blob> { } fn Slice(self, start: Option<i64>, end: Option<i64>, - _contentType: Option<DOMString>) -> Temporary<Blob> { + contentType: Option<DOMString>) -> Temporary<Blob> { let size: i64 = self.Size().to_i64().unwrap(); let relativeStart: i64 = match start { None => 0, @@ -95,23 +108,26 @@ impl<'a> BlobMethods for JSRef<'a, Blob> { } } }; - /* let relativeContentType = match contentType { None => "".into_string(), - Some(str) => str + Some(str) => { + if is_ascii_printable(&str) { + str.as_slice().to_ascii_lower().into_string() + } else { + "".into_string() + } + } }; - */ - //TODO: actually use relativeContentType in constructor let span: i64 = max(relativeEnd - relativeStart, 0); let global = self.global.root(); match self.bytes { - None => Blob::new(&global.root_ref(), None), + None => Blob::new(&global.root_ref(), None, relativeContentType.as_slice()), Some(ref vec) => { let start = relativeStart.to_uint().unwrap(); let end = (relativeStart + span).to_uint().unwrap(); let mut bytes: Vec<u8> = Vec::new(); bytes.push_all(vec.slice(start, end)); - Blob::new(&global.root_ref(), Some(bytes)) + Blob::new(&global.root_ref(), Some(bytes), relativeContentType.as_slice()) } } } diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs index 5ac612e8ecd..ce0a4b766b1 100644 --- a/components/script/dom/file.rs +++ b/components/script/dom/file.rs @@ -20,7 +20,8 @@ impl File { fn new_inherited(global: &GlobalRef, type_: BlobTypeId, _file_bits: JSRef<Blob>, name: DOMString) -> File { File { - blob: Blob::new_inherited(global, type_, None), + //TODO: get type from the underlying filesystem instead of "".to_string() + blob: Blob::new_inherited(global, type_, None, ""), name: name, } // XXXManishearth Once Blob is able to store data diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 3b8a9451a01..9bf48116145 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -59,7 +59,7 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { fn SetEnumAttribute(self, _: TestEnum) {} fn InterfaceAttribute(self) -> Temporary<Blob> { let global = self.global.root(); - Blob::new(&global.root_ref(), None) + Blob::new(&global.root_ref(), None, "") } fn SetInterfaceAttribute(self, _: JSRef<Blob>) {} fn UnionAttribute(self) -> HTMLElementOrLong { eLong(0) } @@ -99,7 +99,7 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { fn GetEnumAttributeNullable(self) -> Option<TestEnum> { Some(_empty) } fn GetInterfaceAttributeNullable(self) -> Option<Temporary<Blob>> { let global = self.global.root(); - Some(Blob::new(&global.root_ref(), None)) + Some(Blob::new(&global.root_ref(), None, "")) } fn SetInterfaceAttributeNullable(self, _: Option<JSRef<Blob>>) {} fn GetUnionAttributeNullable(self) -> Option<HTMLElementOrLong> { Some(eLong(0)) } @@ -123,7 +123,7 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { fn ReceiveEnum(self) -> TestEnum { _empty } fn ReceiveInterface(self) -> Temporary<Blob> { let global = self.global.root(); - Blob::new(&global.root_ref(), None) + Blob::new(&global.root_ref(), None, "") } fn ReceiveAny(self, _: *mut JSContext) -> JSVal { NullValue() } fn ReceiveUnion(self) -> HTMLElementOrLong { eLong(0) } @@ -145,7 +145,7 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { fn ReceiveNullableEnum(self) -> Option<TestEnum> { Some(_empty) } fn ReceiveNullableInterface(self) -> Option<Temporary<Blob>> { let global = self.global.root(); - Some(Blob::new(&global.root_ref(), None)) + Some(Blob::new(&global.root_ref(), None, "")) } fn ReceiveNullableUnion(self) -> Option<HTMLElementOrLong> { Some(eLong(0)) } fn ReceiveNullableUnion2(self) -> Option<EventOrString> { Some(eString("".into_string())) } diff --git a/components/script/dom/webidls/Blob.webidl b/components/script/dom/webidls/Blob.webidl index 6c8bbed1935..70bbdc8c9ef 100644 --- a/components/script/dom/webidls/Blob.webidl +++ b/components/script/dom/webidls/Blob.webidl @@ -7,7 +7,7 @@ //[Exposed=Window,Worker][Constructor, // Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options)] [Constructor, - Constructor(DOMString blobParts)] + Constructor(DOMString blobParts, optional BlobPropertyBag options)] interface Blob { readonly attribute unsigned long long size; diff --git a/tests/content/test_blob.html b/tests/content/test_blob.html index e2b8b897eb4..a9d5d69098d 100644 --- a/tests/content/test_blob.html +++ b/tests/content/test_blob.html @@ -10,6 +10,34 @@ var bs = b.slice(0, 5); is(bs.size, 5); is(b.type, ""); + + var bc = new Blob(testData, {type:"text/plain"}); // the blob + is(bc.size, 32); + is(bc.type, "text/plain"); + + var bss = new Blob(testData, {type:" text/plain "}); // spaces + is(bss.size, 32); + is(bss.type, " text/plain "); + + var bcs = bc.slice(0, 7); + is(bcs.size, 7); + is(bcs.type, ""); + + var bcsc = bc.slice(0, 7, "text/xml"); + is(bcsc.size, 7); + is(bcsc.type, "text/xml"); + + var bu = new Blob(testData, {type:"TEXT/PLAIN"}); // the blob + is(bu.size, 32); + is(bu.type, "text/plain"); + + var bj = new Blob(testData, {type:"☃"}); // the blob + is(bj.size, 32); + is(bj.type, ""); + + var bjs = bj.slice(0, 7, "☃"); + is(bjs.size, 7); + is(bjs.type, ""); </script> </head> </html> diff --git a/tests/wpt/metadata/FileAPI/Blob-constructor.html.ini b/tests/wpt/metadata/FileAPI/Blob-constructor.html.ini index ad07b556982..606df7ef708 100644 --- a/tests/wpt/metadata/FileAPI/Blob-constructor.html.ini +++ b/tests/wpt/metadata/FileAPI/Blob-constructor.html.ini @@ -1,7 +1,5 @@ [Blob-constructor.html] type: testharness - [Blob interface object] - expected: FAIL [Passing non-objects, Dates and RegExps for blobParts should throw a TypeError.] expected: FAIL @@ -78,9 +76,6 @@ [Array with mixed types] expected: FAIL - [options properties should be accessed in lexicographic order.] - expected: FAIL - [Passing null (index 0) for options should use the defaults.] expected: FAIL @@ -122,28 +117,3 @@ [Newlines should not change when endings is \'native\'.] expected: FAIL - - [Blob with type "a"] - expected: FAIL - - [Blob with type "A"] - expected: FAIL - - [Blob with type "text/html"] - expected: FAIL - - [Blob with type "TEXT/HTML"] - expected: FAIL - - [Blob with type " image/gif "] - expected: FAIL - - [Blob with type "unknown/unknown"] - expected: FAIL - - [Blob with type "text/plain"] - expected: FAIL - - [Blob with type "image/png"] - expected: FAIL - |