From 51ef05bf3dce801be0eb3a777b5ade72e4ece3dd Mon Sep 17 00:00:00 2001 From: Nikhil Shagrithaya Date: Wed, 10 Aug 2016 23:49:43 +0530 Subject: [PATCH] Implemented FileReader::readAsArrayBuffer --- .../dom/bindings/codegen/CodegenRust.py | 13 +++- components/script/dom/filereader.rs | 74 +++++++++++++++---- .../script/dom/webidls/FileReader.webidl | 9 +-- .../wpt/metadata/FileAPI/fileReader.html.ini | 8 -- .../wpt/metadata/FileAPI/idlharness.html.ini | 9 --- .../metadata/FileAPI/idlharness.worker.js.ini | 9 --- .../FileReader-multiple-reads.html.ini | 6 -- 7 files changed, 73 insertions(+), 55 deletions(-) delete mode 100644 tests/wpt/metadata/FileAPI/fileReader.html.ini diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 4c67f61af2d..b65d2e65cdb 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -2237,6 +2237,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): 'js::error::throw_type_error', 'js::jsapi::HandleValue', 'js::jsapi::JSContext', + 'js::jsapi::JSObject', 'js::jsapi::MutableHandleValue', 'js::jsval::JSVal', ] @@ -4047,6 +4048,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider): elif type.isPrimitive(): name = type.name typeName = builtinNames[type.tag()] + elif type.isObject(): + name = type.name + typeName = "*mut JSObject" else: raise TypeError("Can't handle %s in unions yet" % type) @@ -4056,7 +4060,6 @@ def getUnionTypeTemplateVars(type, descriptorProvider): isDefinitelyObject=True) template = info.template - assert not type.isObject() jsConversion = string.Template(template).substitute({ "val": "value", }) @@ -4176,7 +4179,10 @@ class CGUnionConversionStruct(CGThing): objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) if len(objectMemberTypes) > 0: - raise TypeError("Can't handle objects in unions.") + assert len(objectMemberTypes) == 1 + typeName = objectMemberTypes[0].name + object = CGGeneric(get_match(typeName)) + names.append(typeName) else: object = None @@ -4191,7 +4197,8 @@ class CGUnionConversionStruct(CGThing): hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object or mozMapObject if hasObjectTypes: - assert interfaceObject or arrayObject or mozMapObject + # "object" is not distinguishable from other types + assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject) templateBody = CGList([], "\n") if interfaceObject: templateBody.append(interfaceObject) diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index 296a6461b55..d9fd00630de 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -6,6 +6,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::FileReaderBinding::{self, FileReaderConstants, FileReaderMethods}; +use dom::bindings::codegen::UnionTypes::StringOrObject; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap, Root}; @@ -22,9 +23,15 @@ use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncodingRef}; use hyper::mime::{Attr, Mime}; +use js::jsapi::Heap; +use js::jsapi::JSAutoCompartment; +use js::jsapi::JSContext; +use js::jsval::{self, JSVal}; +use js::typedarray::Uint8Array; use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64}; use script_thread::RunnableWrapper; use std::cell::Cell; +use std::ptr; use std::sync::Arc; use string_cache::Atom; use task_source::TaskSource; @@ -35,6 +42,7 @@ use util::thread::spawn_named; pub enum FileReaderFunction { ReadAsText, ReadAsDataUrl, + ReadAsArrayBuffer, } pub type TrustedFileReader = Trusted; @@ -68,12 +76,18 @@ pub enum FileReaderReadyState { Done = FileReaderConstants::DONE, } +#[derive(HeapSizeOf, JSTraceable)] +pub enum FileReaderResult { + ArrayBuffer(Heap), + String(DOMString), +} + #[dom_struct] pub struct FileReader { eventtarget: EventTarget, ready_state: Cell, error: MutNullableHeap>, - result: DOMRefCell>, + result: DOMRefCell>, generation_id: Cell, } @@ -159,6 +173,7 @@ 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>) { let fr = filereader.root(); @@ -176,15 +191,17 @@ impl FileReader { fr.change_ready_state(FileReaderReadyState::Done); // Step 8.2 - let output = match data.function { + match data.function { FileReaderFunction::ReadAsDataUrl => - FileReader::perform_readasdataurl(data, &blob_contents), + FileReader::perform_readasdataurl(&fr.result, data, &blob_contents), FileReaderFunction::ReadAsText => - FileReader::perform_readastext(data, &blob_contents), + 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) + }, }; - *fr.result.borrow_mut() = Some(output); - // Step 8.3 fr.dispatch_progress_event(atom!("load"), 0, None); return_on_abort!(); @@ -198,8 +215,7 @@ impl FileReader { } // https://w3c.github.io/FileAPI/#dfn-readAsText - fn perform_readastext(data: ReadMetaData, blob_bytes: &[u8]) - -> DOMString { + fn perform_readastext(result: &DOMRefCell>, data: ReadMetaData, blob_bytes: &[u8]) { let blob_label = &data.label; let blob_type = &data.blobtype; @@ -225,12 +241,11 @@ impl FileReader { let convert = blob_bytes; // Step 7 let output = enc.decode(convert, DecoderTrap::Replace).unwrap(); - DOMString::from(output) + *result.borrow_mut() = Some(FileReaderResult::String(DOMString::from(output))); } //https://w3c.github.io/FileAPI/#dfn-readAsDataURL - fn perform_readasdataurl(data: ReadMetaData, bytes: &[u8]) - -> DOMString { + fn perform_readasdataurl(result: &DOMRefCell>, data: ReadMetaData, bytes: &[u8]) { let config = Config { char_set: CharacterSet::UrlSafe, newline: Newline::LF, @@ -245,7 +260,23 @@ impl FileReader { format!("data:{};base64,{}", data.blobtype, base64) }; - DOMString::from(output) + *result.borrow_mut() = Some(FileReaderResult::String(DOMString::from(output))); + } + + // https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + #[allow(unsafe_code)] + fn perform_readasarraybuffer(result: &DOMRefCell>, + cx: *mut JSContext, _: ReadMetaData, bytes: &[u8]) { + unsafe { + rooted!(in(cx) let mut array_buffer = ptr::null_mut()); + assert!(Uint8Array::create(cx, bytes.len() as u32, Some(bytes), array_buffer.handle_mut()).is_ok()); + + *result.borrow_mut() = Some(FileReaderResult::ArrayBuffer(Heap::default())); + + if let Some(FileReaderResult::ArrayBuffer(ref mut heap)) = *result.borrow_mut() { + heap.set(jsval::ObjectValue(&*array_buffer.get())); + }; + } } } @@ -268,7 +299,11 @@ impl FileReaderMethods for FileReader { // https://w3c.github.io/FileAPI/#dfn-onloadend event_handler!(loadend, GetOnloadend, SetOnloadend); - //TODO https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + // https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + fn ReadAsArrayBuffer(&self, blob: &Blob) -> ErrorResult { + self.read(FileReaderFunction::ReadAsArrayBuffer, blob, None) + } + // https://w3c.github.io/FileAPI/#dfn-readAsDataURL fn ReadAsDataURL(&self, blob: &Blob) -> ErrorResult { self.read(FileReaderFunction::ReadAsDataUrl, blob, None) @@ -302,9 +337,18 @@ impl FileReaderMethods for FileReader { self.error.get() } + #[allow(unsafe_code)] // https://w3c.github.io/FileAPI/#dfn-result - fn GetResult(&self) -> Option { - self.result.borrow().clone() + fn GetResult(&self, _: *mut JSContext) -> Option { + self.result.borrow().as_ref().map(|r| match *r { + FileReaderResult::String(ref string) => + StringOrObject::String(string.clone()), + FileReaderResult::ArrayBuffer(ref arr_buffer) => { + unsafe { + StringOrObject::Object((*arr_buffer.ptr.get()).to_object()) + } + } + }) } // https://w3c.github.io/FileAPI/#dfn-readyState diff --git a/components/script/dom/webidls/FileReader.webidl b/components/script/dom/webidls/FileReader.webidl index 45ae6ea1b2c..be00e39fd77 100644 --- a/components/script/dom/webidls/FileReader.webidl +++ b/components/script/dom/webidls/FileReader.webidl @@ -4,13 +4,13 @@ // http://dev.w3.org/2006/webapi/FileAPI/#APIASynch -//typedef (DOMString or ArrayBuffer) FileReaderResult; +typedef (DOMString or object) FileReaderResult; [Constructor, Exposed=(Window,Worker)] interface FileReader: EventTarget { // async read methods - //[Throws] - //void readAsArrayBuffer(Blob blob); + [Throws] + void readAsArrayBuffer(Blob blob); [Throws] void readAsText(Blob blob, optional DOMString label); [Throws] @@ -25,8 +25,7 @@ interface FileReader: EventTarget { readonly attribute unsigned short readyState; // File or Blob data - //readonly attribute FileReaderResult? result; - readonly attribute DOMString? result; + readonly attribute FileReaderResult? result; readonly attribute DOMException? error; diff --git a/tests/wpt/metadata/FileAPI/fileReader.html.ini b/tests/wpt/metadata/FileAPI/fileReader.html.ini deleted file mode 100644 index 30f5d00d2cf..00000000000 --- a/tests/wpt/metadata/FileAPI/fileReader.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[fileReader.html] - type: testharness - [FileReader States -- abort] - expected: FAIL - - [FileReader States -- events] - expected: FAIL - diff --git a/tests/wpt/metadata/FileAPI/idlharness.html.ini b/tests/wpt/metadata/FileAPI/idlharness.html.ini index a2b56459bec..645001eb1c0 100644 --- a/tests/wpt/metadata/FileAPI/idlharness.html.ini +++ b/tests/wpt/metadata/FileAPI/idlharness.html.ini @@ -21,15 +21,6 @@ [FileReaderSync interface: operation readAsDataURL(Blob)] expected: FAIL - [FileReader interface: operation readAsArrayBuffer(Blob)] - expected: FAIL - - [FileReader interface: new FileReader() must inherit property "readAsArrayBuffer" with the proper type (0)] - expected: FAIL - - [FileReader interface: calling readAsArrayBuffer(Blob) on new FileReader() with too few arguments must throw TypeError] - expected: FAIL - [FileReader interface: operation readAsBinaryString(Blob)] expected: FAIL diff --git a/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini b/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini index c53d42272a0..8e58f76bca3 100644 --- a/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini +++ b/tests/wpt/metadata/FileAPI/idlharness.worker.js.ini @@ -3,15 +3,6 @@ [URL interface: operation createFor(Blob)] expected: FAIL - [FileReader interface: operation readAsArrayBuffer(Blob)] - expected: FAIL - - [FileReader interface: new FileReader() must inherit property "readAsArrayBuffer" with the proper type (0)] - expected: FAIL - - [FileReader interface: calling readAsArrayBuffer(Blob) on new FileReader() with too few arguments must throw TypeError] - expected: FAIL - [FileReaderSync interface: operation readAsArrayBuffer(Blob)] expected: FAIL diff --git a/tests/wpt/metadata/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini b/tests/wpt/metadata/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini index 6936324c1b0..ccfda894482 100644 --- a/tests/wpt/metadata/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini +++ b/tests/wpt/metadata/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini @@ -3,9 +3,3 @@ [test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer] expected: FAIL - [test FileReader InvalidStateError exception for readAsArrayBuffer] - expected: FAIL - - [test FileReader InvalidStateError exception in onloadstart event for readAsArrayBuffer] - expected: FAIL -