aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorJonas Reinwald <jonas.reinwald@htwg-konstanz.de>2017-12-07 16:57:06 +0100
committerJosh Matthews <josh@joshmatthews.net>2018-06-04 15:53:08 -0400
commit0fdafb08c8813229fb756bd0900ac54278cf1c85 (patch)
tree4571f448807c214fe50903279cf536c4e4b87f71 /components
parent3e8caa46792b552c6a7559714077d1b3d9f33194 (diff)
downloadservo-0fdafb08c8813229fb756bd0900ac54278cf1c85.tar.gz
servo-0fdafb08c8813229fb756bd0900ac54278cf1c85.zip
Implement read methods on FileReaderSync
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/bindings/error.rs3
-rw-r--r--components/script/dom/domexception.rs2
-rw-r--r--components/script/dom/filereader.rs208
-rw-r--r--components/script/dom/filereadersync.rs86
-rw-r--r--components/script/dom/webidls/DOMException.webidl1
-rw-r--r--components/script/dom/webidls/FileReaderSync.webidl12
6 files changed, 234 insertions, 78 deletions
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index ed46fa3a924..dee6e9766f0 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -69,6 +69,8 @@ pub enum Error {
TypeMismatch,
/// InvalidModificationError DOMException
InvalidModification,
+ /// NotReadableError DOMException
+ NotReadable,
/// TypeError JavaScript Error
Type(String),
@@ -110,6 +112,7 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, resu
Error::QuotaExceeded => DOMErrorName::QuotaExceededError,
Error::TypeMismatch => DOMErrorName::TypeMismatchError,
Error::InvalidModification => DOMErrorName::InvalidModificationError,
+ Error::NotReadable => DOMErrorName::NotReadableError,
Error::Type(message) => {
assert!(!JS_IsExceptionPending(cx));
throw_type_error(cx, &message);
diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs
index e94689b242b..4f2c076ec66 100644
--- a/components/script/dom/domexception.rs
+++ b/components/script/dom/domexception.rs
@@ -35,6 +35,7 @@ pub enum DOMErrorName {
TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
+ NotReadableError = DOMExceptionConstants::NOT_READABLE_ERR,
}
#[dom_struct]
@@ -94,6 +95,7 @@ impl DOMExceptionMethods for DOMException {
DOMErrorName::InvalidNodeTypeError =>
"The supplied node is incorrect or has an incorrect ancestor for this operation.",
DOMErrorName::DataCloneError => "The object can not be cloned.",
+ DOMErrorName::NotReadableError => "The I/O read operation failed."
};
DOMString::from(message)
diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs
index 7475e4adbd6..037e54907c0 100644
--- a/components/script/dom/filereader.rs
+++ b/components/script/dom/filereader.rs
@@ -51,12 +51,15 @@ pub type TrustedFileReader = Trusted<FileReader>;
pub struct ReadMetaData {
pub blobtype: String,
pub label: Option<String>,
- pub function: FileReaderFunction
+ pub function: FileReaderFunction,
}
impl ReadMetaData {
- pub fn new(blobtype: String,
- label: Option<String>, function: FileReaderFunction) -> ReadMetaData {
+ pub fn new(
+ blobtype: String,
+ label: Option<String>,
+ function: FileReaderFunction,
+ ) -> ReadMetaData {
ReadMetaData {
blobtype: blobtype,
label: label,
@@ -82,6 +85,54 @@ pub enum FileReaderResult {
String(DOMString),
}
+pub struct FileReaderSharedFunctionality;
+
+impl FileReaderSharedFunctionality {
+ pub fn dataurl_format(blob_contents: &[u8], blob_type: String) -> DOMString {
+ let base64 = base64::encode(&blob_contents);
+
+ let dataurl = if blob_type.is_empty() {
+ format!("data:base64,{}", base64)
+ } else {
+ format!("data:{};base64,{}", blob_type, base64)
+ };
+
+ DOMString::from(dataurl)
+ }
+
+ pub fn text_decode(
+ blob_contents: &[u8],
+ blob_type: &str,
+ blob_label: &Option<String>,
+ ) -> DOMString {
+ //https://w3c.github.io/FileAPI/#encoding-determination
+ // Steps 1 & 2 & 3
+ let mut encoding = blob_label
+ .as_ref()
+ .map(|string| string.as_bytes())
+ .and_then(Encoding::for_label);
+
+ // Step 4 & 5
+ encoding = encoding.or_else(|| {
+ let resultmime = blob_type.parse::<Mime>().ok();
+ resultmime.and_then(|Mime(_, _, ref parameters)| {
+ parameters
+ .iter()
+ .find(|&&(ref k, _)| &Attr::Charset == k)
+ .and_then(|&(_, ref v)| Encoding::for_label(v.as_str().as_bytes()))
+ })
+ });
+
+ // Step 6
+ let enc = encoding.unwrap_or(UTF_8);
+
+ let convert = blob_contents;
+ // Step 7
+ let (output, _, _) = enc.decode(convert);
+ DOMString::from(output)
+ }
+}
+
#[dom_struct]
pub struct FileReader {
eventtarget: EventTarget,
@@ -103,8 +154,11 @@ impl FileReader {
}
pub fn new(global: &GlobalScope) -> DomRoot<FileReader> {
- reflect_dom_object(Box::new(FileReader::new_inherited()),
- global, FileReaderBinding::Wrap)
+ reflect_dom_object(
+ Box::new(FileReader::new_inherited()),
+ global,
+ FileReaderBinding::Wrap,
+ )
}
pub fn Constructor(global: &GlobalScope) -> Fallible<DomRoot<FileReader>> {
@@ -112,7 +166,11 @@ impl FileReader {
}
//https://w3c.github.io/FileAPI/#dfn-error-steps
- pub fn process_read_error(filereader: TrustedFileReader, gen_id: GenerationId, error: DOMErrorName) {
+ pub fn process_read_error(
+ filereader: TrustedFileReader,
+ gen_id: GenerationId,
+ error: DOMErrorName,
+ ) {
let fr = filereader.root();
macro_rules! return_on_abort(
@@ -174,8 +232,12 @@ impl FileReader {
// https://w3c.github.io/FileAPI/#dfn-readAsText
#[allow(unsafe_code)]
- pub fn process_read_eof(filereader: TrustedFileReader, gen_id: GenerationId,
- data: ReadMetaData, blob_contents: Arc<Vec<u8>>) {
+ pub fn process_read_eof(
+ filereader: TrustedFileReader,
+ gen_id: GenerationId,
+ data: ReadMetaData,
+ blob_contents: Arc<Vec<u8>>,
+ ) {
let fr = filereader.root();
macro_rules! return_on_abort(
@@ -192,13 +254,21 @@ impl FileReader {
// Step 8.2
match data.function {
- FileReaderFunction::ReadAsDataUrl =>
- FileReader::perform_readasdataurl(&fr.result, data, &blob_contents),
- FileReaderFunction::ReadAsText =>
- FileReader::perform_readastext(&fr.result, data, &blob_contents),
+ FileReaderFunction::ReadAsDataUrl => {
+ FileReader::perform_readasdataurl(&fr.result, data, &blob_contents)
+ },
+ FileReaderFunction::ReadAsText => {
+ FileReader::perform_readastext(&fr.result, data, &blob_contents)
+ },
FileReaderFunction::ReadAsArrayBuffer => {
- let _ac = JSAutoCompartment::new(fr.global().get_cx(), *fr.reflector().get_jsobject());
- FileReader::perform_readasarraybuffer(&fr.result, fr.global().get_cx(), data, &blob_contents)
+ let _ac =
+ JSAutoCompartment::new(fr.global().get_cx(), *fr.reflector().get_jsobject());
+ FileReader::perform_readasarraybuffer(
+ &fr.result,
+ fr.global().get_cx(),
+ data,
+ &blob_contents,
+ )
},
};
@@ -215,55 +285,43 @@ impl FileReader {
}
// https://w3c.github.io/FileAPI/#dfn-readAsText
- fn perform_readastext(result: &DomRefCell<Option<FileReaderResult>>, data: ReadMetaData, blob_bytes: &[u8]) {
+ fn perform_readastext(
+ result: &DomRefCell<Option<FileReaderResult>>,
+ data: ReadMetaData,
+ blob_bytes: &[u8],
+ ) {
let blob_label = &data.label;
let blob_type = &data.blobtype;
- //https://w3c.github.io/FileAPI/#encoding-determination
- // Steps 1 & 2 & 3
- let mut encoding = blob_label.as_ref()
- .map(|string| string.as_bytes())
- .and_then(Encoding::for_label);
-
- // Step 4 & 5
- encoding = encoding.or_else(|| {
- let resultmime = blob_type.parse::<Mime>().ok();
- resultmime.and_then(|Mime(_, _, ref parameters)| {
- parameters.iter()
- .find(|&&(ref k, _)| &Attr::Charset == k)
- .and_then(|&(_, ref v)| Encoding::for_label(v.as_str().as_bytes()))
- })
- });
-
- // Step 6
- let enc = encoding.unwrap_or(UTF_8);
-
- let convert = blob_bytes;
- // Step 7
- let (output, _, _) = enc.decode(convert);
- *result.borrow_mut() = Some(FileReaderResult::String(DOMString::from(output)));
+ let output = FileReaderSharedFunctionality::text_decode(blob_bytes, blob_type, blob_label);
+ *result.borrow_mut() = Some(FileReaderResult::String(output));
}
//https://w3c.github.io/FileAPI/#dfn-readAsDataURL
- fn perform_readasdataurl(result: &DomRefCell<Option<FileReaderResult>>, data: ReadMetaData, bytes: &[u8]) {
- let base64 = base64::encode(bytes);
-
- let output = if data.blobtype.is_empty() {
- format!("data:base64,{}", base64)
- } else {
- format!("data:{};base64,{}", data.blobtype, base64)
- };
-
- *result.borrow_mut() = Some(FileReaderResult::String(DOMString::from(output)));
+ fn perform_readasdataurl(
+ result: &DomRefCell<Option<FileReaderResult>>,
+ data: ReadMetaData,
+ bytes: &[u8],
+ ) {
+ let output = FileReaderSharedFunctionality::dataurl_format(bytes, data.blobtype);
+
+ *result.borrow_mut() = Some(FileReaderResult::String(output));
}
// https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer
#[allow(unsafe_code)]
- fn perform_readasarraybuffer(result: &DomRefCell<Option<FileReaderResult>>,
- cx: *mut JSContext, _: ReadMetaData, bytes: &[u8]) {
+ fn perform_readasarraybuffer(
+ result: &DomRefCell<Option<FileReaderResult>>,
+ cx: *mut JSContext,
+ _: ReadMetaData,
+ bytes: &[u8],
+ ) {
unsafe {
rooted!(in(cx) let mut array_buffer = ptr::null_mut::<JSObject>());
- assert!(ArrayBuffer::create(cx, CreateWith::Slice(bytes), array_buffer.handle_mut()).is_ok());
+ assert!(
+ ArrayBuffer::create(cx, CreateWith::Slice(bytes), array_buffer.handle_mut())
+ .is_ok()
+ );
*result.borrow_mut() = Some(FileReaderResult::ArrayBuffer(Heap::default()));
@@ -335,13 +393,12 @@ impl FileReaderMethods for FileReader {
// https://w3c.github.io/FileAPI/#dfn-result
unsafe fn GetResult(&self, _: *mut JSContext) -> Option<StringOrObject> {
self.result.borrow().as_ref().map(|r| match *r {
- FileReaderResult::String(ref string) =>
- StringOrObject::String(string.clone()),
+ FileReaderResult::String(ref string) => StringOrObject::String(string.clone()),
FileReaderResult::ArrayBuffer(ref arr_buffer) => {
let result = RootedTraceableBox::new(Heap::default());
result.set((*arr_buffer.ptr.get()).to_object());
StringOrObject::Object(result)
- }
+ },
})
}
@@ -351,12 +408,17 @@ impl FileReaderMethods for FileReader {
}
}
-
impl FileReader {
fn dispatch_progress_event(&self, type_: Atom, loaded: u64, total: Option<u64>) {
- let progressevent = ProgressEvent::new(&self.global(),
- type_, EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
- total.is_some(), loaded, total.unwrap_or(0));
+ let progressevent = ProgressEvent::new(
+ &self.global(),
+ type_,
+ EventBubbles::DoesNotBubble,
+ EventCancelable::NotCancelable,
+ total.is_some(),
+ loaded,
+ total.unwrap_or(0),
+ );
progressevent.upcast::<Event>().fire(self.upcast());
}
@@ -365,7 +427,12 @@ impl FileReader {
self.generation_id.set(GenerationId(prev_id + 1));
}
- fn read(&self, function: FileReaderFunction, blob: &Blob, label: Option<DOMString>) -> ErrorResult {
+ fn read(
+ &self,
+ function: FileReaderFunction,
+ blob: &Blob,
+ label: Option<DOMString>,
+ ) -> ErrorResult {
// Step 1
if self.ready_state.get() == FileReaderReadyState::Loading {
return Err(Error::InvalidState);
@@ -388,16 +455,19 @@ impl FileReader {
let canceller = global.task_canceller();
let task_source = global.file_reading_task_source();
- thread::Builder::new().name("file reader async operation".to_owned()).spawn(move || {
- perform_annotated_read_operation(
- gen_id,
- load_data,
- blob_contents,
- fr,
- task_source,
- canceller,
- )
- }).expect("Thread spawning failed");
+ thread::Builder::new()
+ .name("file reader async operation".to_owned())
+ .spawn(move || {
+ perform_annotated_read_operation(
+ gen_id,
+ load_data,
+ blob_contents,
+ fr,
+ task_source,
+ canceller,
+ )
+ })
+ .expect("Thread spawning failed");
Ok(())
}
diff --git a/components/script/dom/filereadersync.rs b/components/script/dom/filereadersync.rs
index bbdb83a23a9..cc9a821a073 100644
--- a/components/script/dom/filereadersync.rs
+++ b/components/script/dom/filereadersync.rs
@@ -2,17 +2,25 @@
* 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/. */
-use dom::bindings::codegen::Bindings::FileReaderSyncBinding;
-use dom::bindings::error::Fallible;
+use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
+use dom::bindings::codegen::Bindings::FileReaderSyncBinding::{FileReaderSyncBinding, FileReaderSyncMethods};
+use dom::bindings::error::{Error, Fallible};
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::root::DomRoot;
+use dom::bindings::str::DOMString;
+use dom::blob::Blob;
use dom::eventtarget::EventTarget;
+use dom::filereader::FileReaderSharedFunctionality;
use dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
+use js::jsapi::{JSContext, JSObject};
+use js::typedarray::{ArrayBuffer, CreateWith};
+use std::ptr;
+use std::ptr::NonNull;
#[dom_struct]
pub struct FileReaderSync {
- eventtarget: EventTarget
+ eventtarget: EventTarget,
}
impl FileReaderSync {
@@ -23,11 +31,79 @@ impl FileReaderSync {
}
pub fn new(global: &GlobalScope) -> DomRoot<FileReaderSync> {
- reflect_dom_object(Box::new(FileReaderSync::new_inherited()),
- global, FileReaderSyncBinding::Wrap)
+ reflect_dom_object(
+ Box::new(FileReaderSync::new_inherited()),
+ global,
+ FileReaderSyncBinding::Wrap,
+ )
}
pub fn Constructor(global: &GlobalScope) -> Fallible<DomRoot<FileReaderSync>> {
Ok(FileReaderSync::new(global))
}
+
+ fn get_blob_bytes(blob: &Blob) -> Result<Vec<u8>, Error> {
+ blob.get_bytes().map_err(|_| Error::NotReadable)
+ }
+}
+
+impl FileReaderSyncMethods for FileReaderSync {
+ // https://w3c.github.io/FileAPI/#readAsBinaryStringSyncSection
+ fn ReadAsBinaryString(&self, blob: &Blob) -> Fallible<DOMString> {
+ // step 1
+ let blob_contents = FileReaderSync::get_blob_bytes(blob)?;
+
+ // step 2
+ Ok(DOMString::from(String::from_utf8_lossy(&blob_contents)))
+ }
+
+ // https://w3c.github.io/FileAPI/#readAsTextSync
+ fn ReadAsText(&self, blob: &Blob, label: Option<DOMString>) -> Fallible<DOMString> {
+ // step 1
+ let blob_contents = FileReaderSync::get_blob_bytes(blob)?;
+
+ // step 2
+ let blob_label = label.map(String::from);
+ let blob_type = String::from(blob.Type());
+
+ let output =
+ FileReaderSharedFunctionality::text_decode(&blob_contents, &blob_type, &blob_label);
+
+ Ok(output)
+ }
+
+ // https://w3c.github.io/FileAPI/#readAsDataURLSync-section
+ fn ReadAsDataURL(&self, blob: &Blob) -> Fallible<DOMString> {
+ // step 1
+ let blob_contents = FileReaderSync::get_blob_bytes(blob)?;
+
+ // step 2
+ let output =
+ FileReaderSharedFunctionality::dataurl_format(&blob_contents, blob.Type().to_string());
+
+ Ok(output)
+ }
+
+ #[allow(unsafe_code)]
+ // https://w3c.github.io/FileAPI/#readAsArrayBufferSyncSection
+ unsafe fn ReadAsArrayBuffer(
+ &self,
+ cx: *mut JSContext,
+ blob: &Blob,
+ ) -> Fallible<NonNull<JSObject>> {
+ // step 1
+ let blob_contents = FileReaderSync::get_blob_bytes(blob)?;
+
+ // step 2
+ rooted!(in(cx) let mut array_buffer = ptr::null_mut::<JSObject>());
+ assert!(
+ ArrayBuffer::create(
+ cx,
+ CreateWith::Slice(&blob_contents),
+ array_buffer.handle_mut()
+ ).is_ok()
+ );
+
+ Ok(NonNull::new_unchecked(array_buffer.get()))
+ }
}
diff --git a/components/script/dom/webidls/DOMException.webidl b/components/script/dom/webidls/DOMException.webidl
index 69866372cb6..fb39af05488 100644
--- a/components/script/dom/webidls/DOMException.webidl
+++ b/components/script/dom/webidls/DOMException.webidl
@@ -34,6 +34,7 @@ interface DOMException {
const unsigned short TIMEOUT_ERR = 23;
const unsigned short INVALID_NODE_TYPE_ERR = 24;
const unsigned short DATA_CLONE_ERR = 25;
+ const unsigned short NOT_READABLE_ERR = 26;
// Error code as u16
readonly attribute unsigned short code;
diff --git a/components/script/dom/webidls/FileReaderSync.webidl b/components/script/dom/webidls/FileReaderSync.webidl
index cbc18a47921..40a0d75df2b 100644
--- a/components/script/dom/webidls/FileReaderSync.webidl
+++ b/components/script/dom/webidls/FileReaderSync.webidl
@@ -8,8 +8,12 @@
interface FileReaderSync {
// Synchronously return strings
- // ArrayBuffer readAsArrayBuffer(Blob blob);
- // DOMString readAsBinaryString(Blob blob);
- // DOMString readAsText(Blob blob, optional DOMString label);
- // DOMString readAsDataURL(Blob blob);
+ [Throws]
+ ArrayBuffer readAsArrayBuffer(Blob blob);
+ [Throws]
+ DOMString readAsBinaryString(Blob blob);
+ [Throws]
+ DOMString readAsText(Blob blob, optional DOMString label);
+ [Throws]
+ DOMString readAsDataURL(Blob blob);
};