Skip to content

Commit

Permalink
Implement Blob methods (text/arraybuffer)
Browse files Browse the repository at this point in the history
  • Loading branch information
kunalmohan committed Jan 14, 2020
1 parent 5688e87 commit bc10ca9
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 89 deletions.
43 changes: 43 additions & 0 deletions components/script/dom/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::compartments::{AlreadyInCompartment, InCompartment};
use crate::dom::bindings::codegen::Bindings::BlobBinding;
use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use crate::dom::bindings::codegen::UnionTypes::ArrayBufferOrArrayBufferViewOrBlobOrString;
Expand All @@ -12,12 +13,18 @@ use crate::dom::bindings::serializable::{Serializable, StorageKey};
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::structuredclone::StructuredDataHolder;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use dom_struct::dom_struct;
use encoding_rs::UTF_8;
use js::jsapi::JSObject;
use js::typedarray::{ArrayBuffer, CreateWith};
use msg::constellation_msg::{BlobId, BlobIndex, PipelineNamespaceId};
use net_traits::filemanager_thread::RelativePos;
use script_traits::serializable::BlobImpl;
use std::collections::HashMap;
use std::num::NonZeroU32;
use std::ptr;
use std::rc::Rc;
use uuid::Uuid;

// https://w3c.github.io/FileAPI/#blob
Expand Down Expand Up @@ -222,6 +229,42 @@ impl BlobMethods for Blob {
let blob_impl = BlobImpl::new_sliced(rel_pos, self.blob_id.clone(), type_string);
Blob::new(&*self.global(), blob_impl)
}

// https://w3c.github.io/FileAPI/#text-method-algo
fn Text(&self) -> Rc<Promise> {
let in_compartment_proof = AlreadyInCompartment::assert(&self.global());
let p = Promise::new_in_current_compartment(
&self.global(),
InCompartment::Already(&in_compartment_proof),
);
let bytes = self.get_bytes().expect("Could not get blob contents");
let (text, _, _) = UTF_8.decode(&bytes);
let text = DOMString::from(text);
p.resolve_native(&text);
p
}

// https://w3c.github.io/FileAPI/#arraybuffer-method-algo
#[allow(unsafe_code)]
fn ArrayBuffer(&self) -> Rc<Promise> {
let in_compartment_proof = AlreadyInCompartment::assert(&self.global());
let p = Promise::new_in_current_compartment(
&self.global(),
InCompartment::Already(&in_compartment_proof),
);
let bytes = self.get_bytes().expect("Could not get blob contents");
let cx = &*self.global().get_cx();
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()
);

p.resolve_native(&*array_buffer);
p
}
}
}

/// Get the normalized, MIME-parsable type string
Expand Down
43 changes: 38 additions & 5 deletions components/script/dom/globalscope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlo
use crate::dom::bindings::conversions::{root_from_object, root_from_object_static};
use crate::dom::bindings::error::{report_pending_exception, ErrorInfo};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::settings_stack::{entry_global, incumbent_global, AutoEntryScript};
Expand All @@ -30,6 +30,7 @@ use crate::dom::messageevent::MessageEvent;
use crate::dom::messageport::MessagePort;
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use crate::dom::performance::Performance;
use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::dom::workletglobalscope::WorkletGlobalScope;
Expand Down Expand Up @@ -68,7 +69,9 @@ use js::rust::{HandleValue, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{BlobId, MessagePortId, MessagePortRouterId, PipelineId};
use net_traits::blob_url_store::{get_blob_origin, BlobBuf};
use net_traits::filemanager_thread::{FileManagerThreadMsg, ReadFileProgress, RelativePos};
use net_traits::filemanager_thread::{
FileManagerResult, FileManagerThreadMsg, ReadFileProgress, RelativePos,
};
use net_traits::image_cache::ImageCache;
use net_traits::{CoreResourceMsg, CoreResourceThread, IpcSend, ResourceThreads};
use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_time};
Expand All @@ -89,6 +92,7 @@ use std::ops::Index;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use time::{get_time, Timespec};
use uuid::Uuid;

Expand Down Expand Up @@ -1241,18 +1245,47 @@ impl GlobalScope {
}

fn read_file(&self, id: Uuid) -> Result<Vec<u8>, ()> {
let recv = self.send_msg(id);
GlobalScope::read_msg(recv)
}

#[allow(dead_code)]
fn read_file_async(&self, id: Uuid, promise: Rc<Promise>) {
let recv = self.send_msg(id);
let trusted_promise = TrustedPromise::new(promise);
let canceller = self.task_canceller(TaskSourceName::FileReading);
let task_source = self.file_reading_task_source();
thread::spawn(move || {
let bytes = GlobalScope::read_msg(recv).unwrap();
let _ = task_source.queue_with_canceller(
task!(resolve_native: move || {
let promise = trusted_promise.root();
promise.resolve_native(&bytes);
}),
&canceller,
);
});
}

fn send_msg(&self, id: Uuid) -> profile_ipc::IpcReceiver<FileManagerResult<ReadFileProgress>> {
let resource_threads = self.resource_threads();
let (chan, recv) =
profile_ipc::channel(self.time_profiler_chan().clone()).map_err(|_| ())?;
let (chan, recv) = profile_ipc::channel(self.time_profiler_chan().clone())
.map_err(|_| ())
.unwrap();
let origin = get_blob_origin(&self.get_url());
let check_url_validity = false;
let msg = FileManagerThreadMsg::ReadFile(chan, id, check_url_validity, origin);
let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg));
recv
}

fn read_msg(
object: profile_ipc::IpcReceiver<FileManagerResult<ReadFileProgress>>,
) -> Result<Vec<u8>, ()> {
let mut bytes = vec![];

loop {
match recv.recv().unwrap() {
match object.recv().unwrap() {
Ok(ReadFileProgress::Meta(mut blob_buf)) => {
bytes.append(&mut blob_buf.bytes);
},
Expand Down
3 changes: 3 additions & 0 deletions components/script/dom/webidls/Blob.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ interface Blob {
Blob slice(optional [Clamp] long long start,
optional [Clamp] long long end,
optional DOMString contentType);

[NewObject] Promise<DOMString> text();
[NewObject] Promise<ArrayBuffer> arrayBuffer();
};

dictionary BlobPropertyBag {
Expand Down
33 changes: 0 additions & 33 deletions tests/wpt/metadata/FileAPI/blob/Blob-array-buffer.any.js.ini

This file was deleted.

51 changes: 0 additions & 51 deletions tests/wpt/metadata/FileAPI/blob/Blob-text.any.js.ini

This file was deleted.

0 comments on commit bc10ca9

Please sign in to comment.