aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/blob.rs101
-rw-r--r--components/script/dom/file.rs10
-rw-r--r--components/script/dom/formdata.rs2
-rw-r--r--components/script/dom/testbinding.rs8
-rw-r--r--components/script/dom/webidls/Blob.webidl11
-rw-r--r--tests/content/test_blob.html15
6 files changed, 125 insertions, 22 deletions
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index 3380670d4f5..b0d0b155821 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -3,11 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::InheritTypes::FileDerived;
-use dom::bindings::global::GlobalRef;
-use dom::bindings::js::Temporary;
+use dom::bindings::global::{GlobalRef, GlobalField};
+use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible;
use dom::bindings::codegen::Bindings::BlobBinding;
+use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
+
+use servo_util::str::DOMString;
+use std::cmp::{min, max};
#[jstraceable]
pub enum BlobType {
@@ -18,28 +22,107 @@ pub enum BlobType {
#[dom_struct]
pub struct Blob {
reflector_: Reflector,
- type_: BlobType
+ type_: BlobType,
+ bytes: Option<Vec<u8>>,
+ typeString: DOMString,
+ global: GlobalField
+ // isClosed_: bool
}
impl Blob {
- pub fn new_inherited() -> Blob {
+ pub fn new_inherited(global: &GlobalRef, bytes: Option<Vec<u8>>) -> Blob {
Blob {
reflector_: Reflector::new(),
- type_: BlobTypeId
+ type_: BlobTypeId,
+ bytes: bytes,
+ typeString: "".to_string(),
+ global: GlobalField::from_rooted(global)
+ //isClosed_: false
}
}
- pub fn new(global: GlobalRef) -> Temporary<Blob> {
- reflect_dom_object(box Blob::new_inherited(),
- global,
+ pub fn new(global: &GlobalRef, bytes: Option<Vec<u8>>) -> Temporary<Blob> {
+ reflect_dom_object(box Blob::new_inherited(global, bytes),
+ *global,
BlobBinding::Wrap)
}
pub fn Constructor(global: &GlobalRef) -> Fallible<Temporary<Blob>> {
- Ok(Blob::new(*global))
+ Ok(Blob::new(global, None))
+ }
+
+ pub fn Constructor_(global: &GlobalRef, blobParts: DOMString) -> 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))
}
}
+impl<'a> BlobMethods for JSRef<'a, Blob> {
+ fn Size(self) -> u64{
+ match self.bytes {
+ None => 0,
+ Some(ref bytes) => bytes.len() as u64
+ }
+ }
+
+ fn Type(self) -> DOMString {
+ self.typeString.clone()
+ }
+
+ fn Slice(self, start: Option<i64>, end: Option<i64>,
+ _contentType: Option<DOMString>) -> Temporary<Blob> {
+ let size: i64 = self.Size().to_i64().unwrap();
+ let relativeStart: i64 = match start {
+ None => 0,
+ Some(start) => {
+ if start < 0 {
+ max(size.to_i64().unwrap() + start, 0)
+ } else {
+ min(start, size)
+ }
+ }
+ };
+ let relativeEnd: i64 = match end {
+ None => size,
+ Some(end) => {
+ if end < 0 {
+ max(size + end, 0)
+ } else {
+ min(end, size)
+ }
+ }
+ };
+ /*
+ let relativeContentType = match contentType {
+ None => "".to_string(),
+ Some(str) => str
+ };
+ */
+ //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),
+ 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))
+ }
+ }
+ }
+
+ //fn IsClosed(self) -> bool {
+ // self.isClosed_.clone()
+ //}
+
+ //fn Close(self) {
+ // TODO
+ //}
+}
impl Reflectable for Blob {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs
index 26555755401..52fb22abd12 100644
--- a/components/script/dom/file.rs
+++ b/components/script/dom/file.rs
@@ -18,9 +18,9 @@ pub struct File {
}
impl File {
- fn new_inherited(_file_bits: JSRef<Blob>, name: DOMString) -> File {
+ fn new_inherited(global: &GlobalRef, _file_bits: JSRef<Blob>, name: DOMString) -> File {
File {
- blob: Blob::new_inherited(),
+ blob: Blob::new_inherited(global, None),
name: name,
type_: FileTypeId
}
@@ -28,9 +28,9 @@ impl File {
// the relevant subfields of file_bits should be copied over
}
- pub fn new(global: GlobalRef, file_bits: JSRef<Blob>, name: DOMString) -> Temporary<File> {
- reflect_dom_object(box File::new_inherited(file_bits, name),
- global,
+ pub fn new(global: &GlobalRef, file_bits: JSRef<Blob>, name: DOMString) -> Temporary<File> {
+ reflect_dom_object(box File::new_inherited(global, file_bits, name),
+ *global,
FileBinding::Wrap)
}
diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs
index 4334ca379cc..0c9a5e81f8b 100644
--- a/components/script/dom/formdata.rs
+++ b/components/script/dom/formdata.rs
@@ -121,6 +121,6 @@ impl PrivateFormDataHelpers for FormData {
let global = self.global.root();
let f: Option<JSRef<File>> = FileCast::to_ref(value);
let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_string()));
- File::new(global.root_ref(), value, name)
+ File::new(&global.root_ref(), value, name)
}
}
diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs
index 47bc333475b..bdae481dcea 100644
--- a/components/script/dom/testbinding.rs
+++ b/components/script/dom/testbinding.rs
@@ -57,7 +57,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())
+ Blob::new(&global.root_ref(), None)
}
fn SetInterfaceAttribute(self, _: JSRef<Blob>) {}
fn UnionAttribute(self) -> HTMLElementOrLong { eLong(0) }
@@ -96,7 +96,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()))
+ Some(Blob::new(&global.root_ref(), None))
}
fn SetInterfaceAttributeNullable(self, _: Option<JSRef<Blob>>) {}
fn GetUnionAttributeNullable(self) -> Option<HTMLElementOrLong> { Some(eLong(0)) }
@@ -120,7 +120,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())
+ Blob::new(&global.root_ref(), None)
}
fn ReceiveAny(self, _: *mut JSContext) -> JSVal { NullValue() }
fn ReceiveUnion(self) -> HTMLElementOrLong { eLong(0) }
@@ -142,7 +142,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()))
+ Some(Blob::new(&global.root_ref(), None))
}
fn ReceiveNullableUnion(self) -> Option<HTMLElementOrLong> { Some(eLong(0)) }
fn ReceiveNullableUnion2(self) -> Option<EventOrString> { Some(eString("".to_string())) }
diff --git a/components/script/dom/webidls/Blob.webidl b/components/script/dom/webidls/Blob.webidl
index 3a544024338..6c8bbed1935 100644
--- a/components/script/dom/webidls/Blob.webidl
+++ b/components/script/dom/webidls/Blob.webidl
@@ -6,18 +6,23 @@
// http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob
//[Exposed=Window,Worker][Constructor,
// Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options)]
-[Constructor]
+[Constructor,
+ Constructor(DOMString blobParts)]
interface Blob {
- //readonly attribute unsigned long long size;
- //readonly attribute DOMString type;
+ readonly attribute unsigned long long size;
+ readonly attribute DOMString type;
//readonly attribute boolean isClosed;
//slice Blob into byte-ranged chunks
+ //TODO: implement slice with [Clamp]
//Blob slice([Clamp] optional long long start,
// [Clamp] optional long long end,
// optional DOMString contentType);
+ Blob slice(optional long long start,
+ optional long long end,
+ optional DOMString contentType);
//void close();
};
diff --git a/tests/content/test_blob.html b/tests/content/test_blob.html
new file mode 100644
index 00000000000..e2b8b897eb4
--- /dev/null
+++ b/tests/content/test_blob.html
@@ -0,0 +1,15 @@
+<html>
+ <head>
+ <script src="harness.js"></script>
+ <script>
+ var testData = ['<a id="a"><b id="b">hey!</b></a>'];
+ var b = new Blob(testData); // the blob
+ is(b.size, 32);
+ is(b.type, "");
+
+ var bs = b.slice(0, 5);
+ is(bs.size, 5);
+ is(b.type, "");
+ </script>
+ </head>
+</html>