Implemented FileReader::readAsArrayBuffer

This commit is contained in:
Nikhil Shagrithaya 2016-08-10 23:49:43 +05:30
parent 7e96f87565
commit 51ef05bf3d
7 changed files with 73 additions and 55 deletions

View file

@ -2237,6 +2237,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'js::error::throw_type_error', 'js::error::throw_type_error',
'js::jsapi::HandleValue', 'js::jsapi::HandleValue',
'js::jsapi::JSContext', 'js::jsapi::JSContext',
'js::jsapi::JSObject',
'js::jsapi::MutableHandleValue', 'js::jsapi::MutableHandleValue',
'js::jsval::JSVal', 'js::jsval::JSVal',
] ]
@ -4047,6 +4048,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
elif type.isPrimitive(): elif type.isPrimitive():
name = type.name name = type.name
typeName = builtinNames[type.tag()] typeName = builtinNames[type.tag()]
elif type.isObject():
name = type.name
typeName = "*mut JSObject"
else: else:
raise TypeError("Can't handle %s in unions yet" % type) raise TypeError("Can't handle %s in unions yet" % type)
@ -4056,7 +4060,6 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
isDefinitelyObject=True) isDefinitelyObject=True)
template = info.template template = info.template
assert not type.isObject()
jsConversion = string.Template(template).substitute({ jsConversion = string.Template(template).substitute({
"val": "value", "val": "value",
}) })
@ -4176,7 +4179,10 @@ class CGUnionConversionStruct(CGThing):
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
if len(objectMemberTypes) > 0: 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: else:
object = None object = None
@ -4191,7 +4197,8 @@ class CGUnionConversionStruct(CGThing):
hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object or mozMapObject hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object or mozMapObject
if hasObjectTypes: 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") templateBody = CGList([], "\n")
if interfaceObject: if interfaceObject:
templateBody.append(interfaceObject) templateBody.append(interfaceObject)

View file

@ -6,6 +6,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::FileReaderBinding::{self, FileReaderConstants, FileReaderMethods}; 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::error::{Error, ErrorResult, Fallible};
use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root}; 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::label::encoding_from_whatwg_label;
use encoding::types::{DecoderTrap, EncodingRef}; use encoding::types::{DecoderTrap, EncodingRef};
use hyper::mime::{Attr, Mime}; 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 rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
use script_thread::RunnableWrapper; use script_thread::RunnableWrapper;
use std::cell::Cell; use std::cell::Cell;
use std::ptr;
use std::sync::Arc; use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use task_source::TaskSource; use task_source::TaskSource;
@ -35,6 +42,7 @@ use util::thread::spawn_named;
pub enum FileReaderFunction { pub enum FileReaderFunction {
ReadAsText, ReadAsText,
ReadAsDataUrl, ReadAsDataUrl,
ReadAsArrayBuffer,
} }
pub type TrustedFileReader = Trusted<FileReader>; pub type TrustedFileReader = Trusted<FileReader>;
@ -68,12 +76,18 @@ pub enum FileReaderReadyState {
Done = FileReaderConstants::DONE, Done = FileReaderConstants::DONE,
} }
#[derive(HeapSizeOf, JSTraceable)]
pub enum FileReaderResult {
ArrayBuffer(Heap<JSVal>),
String(DOMString),
}
#[dom_struct] #[dom_struct]
pub struct FileReader { pub struct FileReader {
eventtarget: EventTarget, eventtarget: EventTarget,
ready_state: Cell<FileReaderReadyState>, ready_state: Cell<FileReaderReadyState>,
error: MutNullableHeap<JS<DOMException>>, error: MutNullableHeap<JS<DOMException>>,
result: DOMRefCell<Option<DOMString>>, result: DOMRefCell<Option<FileReaderResult>>,
generation_id: Cell<GenerationId>, generation_id: Cell<GenerationId>,
} }
@ -159,6 +173,7 @@ impl FileReader {
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
#[allow(unsafe_code)]
pub fn process_read_eof(filereader: TrustedFileReader, gen_id: GenerationId, pub fn process_read_eof(filereader: TrustedFileReader, gen_id: GenerationId,
data: ReadMetaData, blob_contents: Arc<Vec<u8>>) { data: ReadMetaData, blob_contents: Arc<Vec<u8>>) {
let fr = filereader.root(); let fr = filereader.root();
@ -176,15 +191,17 @@ impl FileReader {
fr.change_ready_state(FileReaderReadyState::Done); fr.change_ready_state(FileReaderReadyState::Done);
// Step 8.2 // Step 8.2
let output = match data.function { match data.function {
FileReaderFunction::ReadAsDataUrl => FileReaderFunction::ReadAsDataUrl =>
FileReader::perform_readasdataurl(data, &blob_contents), FileReader::perform_readasdataurl(&fr.result, data, &blob_contents),
FileReaderFunction::ReadAsText => 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 // Step 8.3
fr.dispatch_progress_event(atom!("load"), 0, None); fr.dispatch_progress_event(atom!("load"), 0, None);
return_on_abort!(); return_on_abort!();
@ -198,8 +215,7 @@ impl FileReader {
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
fn perform_readastext(data: ReadMetaData, blob_bytes: &[u8]) fn perform_readastext(result: &DOMRefCell<Option<FileReaderResult>>, data: ReadMetaData, blob_bytes: &[u8]) {
-> DOMString {
let blob_label = &data.label; let blob_label = &data.label;
let blob_type = &data.blobtype; let blob_type = &data.blobtype;
@ -225,12 +241,11 @@ impl FileReader {
let convert = blob_bytes; let convert = blob_bytes;
// Step 7 // Step 7
let output = enc.decode(convert, DecoderTrap::Replace).unwrap(); 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 //https://w3c.github.io/FileAPI/#dfn-readAsDataURL
fn perform_readasdataurl(data: ReadMetaData, bytes: &[u8]) fn perform_readasdataurl(result: &DOMRefCell<Option<FileReaderResult>>, data: ReadMetaData, bytes: &[u8]) {
-> DOMString {
let config = Config { let config = Config {
char_set: CharacterSet::UrlSafe, char_set: CharacterSet::UrlSafe,
newline: Newline::LF, newline: Newline::LF,
@ -245,7 +260,23 @@ impl FileReader {
format!("data:{};base64,{}", data.blobtype, base64) 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<Option<FileReaderResult>>,
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 // https://w3c.github.io/FileAPI/#dfn-onloadend
event_handler!(loadend, GetOnloadend, SetOnloadend); 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 // https://w3c.github.io/FileAPI/#dfn-readAsDataURL
fn ReadAsDataURL(&self, blob: &Blob) -> ErrorResult { fn ReadAsDataURL(&self, blob: &Blob) -> ErrorResult {
self.read(FileReaderFunction::ReadAsDataUrl, blob, None) self.read(FileReaderFunction::ReadAsDataUrl, blob, None)
@ -302,9 +337,18 @@ impl FileReaderMethods for FileReader {
self.error.get() self.error.get()
} }
#[allow(unsafe_code)]
// https://w3c.github.io/FileAPI/#dfn-result // https://w3c.github.io/FileAPI/#dfn-result
fn GetResult(&self) -> Option<DOMString> { fn GetResult(&self, _: *mut JSContext) -> Option<StringOrObject> {
self.result.borrow().clone() 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 // https://w3c.github.io/FileAPI/#dfn-readyState

View file

@ -4,13 +4,13 @@
// http://dev.w3.org/2006/webapi/FileAPI/#APIASynch // http://dev.w3.org/2006/webapi/FileAPI/#APIASynch
//typedef (DOMString or ArrayBuffer) FileReaderResult; typedef (DOMString or object) FileReaderResult;
[Constructor, Exposed=(Window,Worker)] [Constructor, Exposed=(Window,Worker)]
interface FileReader: EventTarget { interface FileReader: EventTarget {
// async read methods // async read methods
//[Throws] [Throws]
//void readAsArrayBuffer(Blob blob); void readAsArrayBuffer(Blob blob);
[Throws] [Throws]
void readAsText(Blob blob, optional DOMString label); void readAsText(Blob blob, optional DOMString label);
[Throws] [Throws]
@ -25,8 +25,7 @@ interface FileReader: EventTarget {
readonly attribute unsigned short readyState; readonly attribute unsigned short readyState;
// File or Blob data // File or Blob data
//readonly attribute FileReaderResult? result; readonly attribute FileReaderResult? result;
readonly attribute DOMString? result;
readonly attribute DOMException? error; readonly attribute DOMException? error;

View file

@ -1,8 +0,0 @@
[fileReader.html]
type: testharness
[FileReader States -- abort]
expected: FAIL
[FileReader States -- events]
expected: FAIL

View file

@ -21,15 +21,6 @@
[FileReaderSync interface: operation readAsDataURL(Blob)] [FileReaderSync interface: operation readAsDataURL(Blob)]
expected: FAIL 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)] [FileReader interface: operation readAsBinaryString(Blob)]
expected: FAIL expected: FAIL

View file

@ -3,15 +3,6 @@
[URL interface: operation createFor(Blob)] [URL interface: operation createFor(Blob)]
expected: FAIL 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)] [FileReaderSync interface: operation readAsArrayBuffer(Blob)]
expected: FAIL expected: FAIL

View file

@ -3,9 +3,3 @@
[test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer] [test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer]
expected: FAIL expected: FAIL
[test FileReader InvalidStateError exception for readAsArrayBuffer]
expected: FAIL
[test FileReader InvalidStateError exception in onloadstart event for readAsArrayBuffer]
expected: FAIL