Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove DataSlice, fix #12249 #12258

Merged
merged 1 commit into from Jul 5, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -135,8 +135,8 @@ impl<UI: 'static + UIProvider> FileManager<UI> {
Err(_) => { let _ = sender.send(Err(FileManagerThreadError::ReadFileError)); }
}
}
FileManagerThreadMsg::TransferMemory(entry, rel_pos, sender, origin) =>
self.transfer_memory(entry, rel_pos, sender, origin),
FileManagerThreadMsg::TransferMemory(entry, sender, origin) =>
self.transfer_memory(entry, sender, origin),
FileManagerThreadMsg::AddSlicedEntry(id, rel_pos, sender, origin) =>
self.add_sliced_entry(id, rel_pos, sender, origin),
FileManagerThreadMsg::LoadBlob(load_data, consumer) => {
@@ -418,8 +418,9 @@ impl<UI: 'static + UIProvider> FileManager<UI> {
}
}

fn transfer_memory(&mut self, entry: BlobURLStoreEntry, rel_pos: RelativePos,
sender: IpcSender<Result<SelectedFileId, BlobURLStoreError>>, origin: FileOrigin) {
fn transfer_memory(&mut self, entry: BlobURLStoreEntry,
sender: IpcSender<Result<SelectedFileId, BlobURLStoreError>>,
origin: FileOrigin) {
match Url::parse(&origin) { // parse to check sanity
Ok(_) => {
let id = Uuid::new_v4();
@@ -428,9 +429,8 @@ impl<UI: 'static + UIProvider> FileManager<UI> {
file_impl: FileImpl::Memory(entry),
refs: Cell::new(1),
});
let sliced_id = SelectedFileId(id.simple().to_string());

self.add_sliced_entry(sliced_id, rel_pos, sender, origin);
let _ = sender.send(Ok(SelectedFileId(id.simple().to_string())));
}
Err(_) => {
let _ = sender.send(Err(BlobURLStoreError::InvalidOrigin));
@@ -130,7 +130,7 @@ pub enum FileManagerThreadMsg {
LoadBlob(LoadData, LoadConsumer),

/// Add an entry and send back the associated uuid
TransferMemory(BlobURLStoreEntry, RelativePos, IpcSender<Result<SelectedFileId, BlobURLStoreError>>, FileOrigin),
TransferMemory(BlobURLStoreEntry, IpcSender<Result<SelectedFileId, BlobURLStoreError>>, FileOrigin),

/// Add a sliced entry pointing to the parent id with a relative slicing positing
AddSlicedEntry(SelectedFileId, RelativePos, IpcSender<Result<SelectedFileId, BlobURLStoreError>>, FileOrigin),
@@ -19,92 +19,32 @@ use net_traits::blob_url_store::BlobURLStoreEntry;
use net_traits::filemanager_thread::{FileManagerThreadMsg, SelectedFileId, RelativePos};
use std::ascii::AsciiExt;
use std::cell::Cell;
use std::ops::Range;
use std::sync::Arc;

#[derive(Clone, JSTraceable)]
pub struct DataSlice {
bytes: Arc<Vec<u8>>,
bytes_start: usize,
bytes_end: usize
}

impl DataSlice {
/// Construct DataSlice from reference counted bytes
pub fn new(bytes: Arc<Vec<u8>>, start: Option<i64>, end: Option<i64>) -> DataSlice {
let range = RelativePos::from_opts(start, end).to_abs_range(bytes.len());

DataSlice {
bytes: bytes,
bytes_start: range.start,
bytes_end: range.end,
}
}

/// Construct data slice from a vector of bytes
pub fn from_bytes(bytes: Vec<u8>) -> DataSlice {
DataSlice::new(Arc::new(bytes), None, None)
}

/// Construct an empty data slice
pub fn empty() -> DataSlice {
DataSlice {
bytes: Arc::new(Vec::new()),
bytes_start: 0,
bytes_end: 0,
}
}

/// Get sliced bytes
pub fn get_bytes(&self) -> &[u8] {
&self.bytes[self.bytes_start..self.bytes_end]
}

/// Get length of sliced bytes
pub fn size(&self) -> u64 {
(self.bytes_end as u64) - (self.bytes_start as u64)
}

/// Further adjust the slice range based on passed-in relative positions
pub fn slice(&self, pos: &RelativePos) -> DataSlice {
let old_size = self.size();
let range = pos.to_abs_range(old_size as usize);
DataSlice {
bytes: self.bytes.clone(),
bytes_start: self.bytes_start + range.start,
bytes_end: self.bytes_start + range.end,
}
}
}
use std::ops::Index;

#[must_root]
#[derive(JSTraceable)]
pub enum BlobImpl {
/// File-based blob, including id and possibly cached content
File(SelectedFileId, DOMRefCell<Option<DataSlice>>),
File(SelectedFileId, DOMRefCell<Option<Vec<u8>>>),
/// Memory-based blob
Memory(DataSlice),
Memory(Vec<u8>),
/// Sliced blob, including parent blob and
/// relative positions representing current slicing range,
/// it is leaf of a two-layer fat tree
Sliced(JS<Blob>, RelativePos),
}

impl BlobImpl {
/// Construct memory-backed BlobImpl from DataSlice
pub fn new_from_slice(slice: DataSlice) -> BlobImpl {
BlobImpl::Memory(slice)
/// Construct memory-backed BlobImpl
#[allow(unrooted_must_root)]
pub fn new_from_bytes(bytes: Vec<u8>) -> BlobImpl {
BlobImpl::Memory(bytes)
}

/// Construct file-backed BlobImpl from File ID
pub fn new_from_file(file_id: SelectedFileId) -> BlobImpl {
BlobImpl::File(file_id, DOMRefCell::new(None))
}

/// Construct empty, memory-backed BlobImpl
pub fn new_from_empty_slice() -> BlobImpl {
BlobImpl::new_from_slice(DataSlice::empty())
}
}

// https://w3c.github.io/FileAPI/#blob
@@ -178,12 +118,11 @@ impl Blob {
}
};

let slice = DataSlice::from_bytes(bytes);
Ok(Blob::new(global, BlobImpl::new_from_slice(slice), blobPropertyBag.get_typestring()))
Ok(Blob::new(global, BlobImpl::new_from_bytes(bytes), blobPropertyBag.get_typestring()))
}

/// Get a slice to inner data, this might incur synchronous read and caching
pub fn get_slice(&self) -> Result<DataSlice, ()> {
pub fn get_bytes(&self) -> Result<Vec<u8>, ()> {
match *self.blob_impl.borrow() {
BlobImpl::File(ref id, ref cached) => {
let buffer = match *cached.borrow() {
@@ -204,17 +143,14 @@ impl Blob {
}
BlobImpl::Memory(ref s) => Ok(s.clone()),
BlobImpl::Sliced(ref parent, ref rel_pos) => {
let dataslice = parent.get_slice_or_empty();
Ok(dataslice.slice(rel_pos))
parent.get_bytes().map(|v| {
let range = rel_pos.to_abs_range(v.len());
v.index(range).to_vec()
})
}
}
}

/// Try to get a slice, and if any exception happens, return the empty slice
pub fn get_slice_or_empty(&self) -> DataSlice {
self.get_slice().unwrap_or(DataSlice::empty())
}

pub fn get_id(&self) -> SelectedFileId {
match *self.blob_impl.borrow() {
BlobImpl::File(ref id, _) => id.clone(),
@@ -228,8 +164,8 @@ impl Blob {
}
BlobImpl::File(ref parent_id, _) =>
self.create_sliced_id(parent_id, rel_pos),
BlobImpl::Memory(ref parent_slice) => {
let parent_id = parent.promote_to_file(parent_slice);
BlobImpl::Memory(ref bytes) => {
let parent_id = parent.promote_to_file(bytes);
*self.blob_impl.borrow_mut() = BlobImpl::Sliced(parent.clone(), rel_pos.clone());
self.create_sliced_id(&parent_id, rel_pos)
}
@@ -240,15 +176,10 @@ impl Blob {

/// Promite memory-based Blob to file-based,
/// The bytes in data slice will be transferred to file manager thread
fn promote_to_file(&self, self_slice: &DataSlice) -> SelectedFileId {
fn promote_to_file(&self, bytes: &[u8]) -> SelectedFileId {
let global = self.global();
let origin = global.r().get_url().origin().unicode_serialization();
let filemanager = global.r().resource_threads().sender();
let bytes = self_slice.get_bytes();
let rel_pos = RelativePos::from_abs_range(Range {
start: self_slice.bytes_start,
end: self_slice.bytes_end,
}, self_slice.bytes.len());

let entry = BlobURLStoreEntry {
type_string: self.typeString.clone(),
@@ -257,7 +188,7 @@ impl Blob {
};

let (tx, rx) = ipc::channel().unwrap();
let _ = filemanager.send(FileManagerThreadMsg::TransferMemory(entry, rel_pos, tx, origin.clone()));
let _ = filemanager.send(FileManagerThreadMsg::TransferMemory(entry, tx, origin.clone()));

match rx.recv().unwrap() {
Ok(new_id) => SelectedFileId(new_id.0),
@@ -285,7 +216,7 @@ impl Blob {
}
}

fn read_file(global: GlobalRef, id: SelectedFileId) -> Result<DataSlice, ()> {
fn read_file(global: GlobalRef, id: SelectedFileId) -> Result<Vec<u8>, ()> {
let file_manager = global.filemanager_thread();
let (chan, recv) = ipc::channel().map_err(|_|())?;
let origin = global.get_url().origin().unicode_serialization();
@@ -300,8 +231,7 @@ fn read_file(global: GlobalRef, id: SelectedFileId) -> Result<DataSlice, ()> {
}
};

let bytes = result.map_err(|_|())?;
Ok(DataSlice::from_bytes(bytes))
result.map_err(|_|())
}

/// Extract bytes from BlobParts, used by Blob and File constructor
@@ -316,7 +246,8 @@ pub fn blob_parts_to_bytes(blobparts: Vec<BlobOrString>) -> Result<Vec<u8>, ()>
ret.append(&mut bytes);
},
&BlobOrString::Blob(ref b) => {
ret.append(&mut b.get_slice_or_empty().bytes.to_vec());
let mut bytes = b.get_bytes().unwrap_or(vec![]);
ret.append(&mut bytes);
},
}
}
@@ -327,7 +258,11 @@ pub fn blob_parts_to_bytes(blobparts: Vec<BlobOrString>) -> Result<Vec<u8>, ()>
impl BlobMethods for Blob {
// https://w3c.github.io/FileAPI/#dfn-size
fn Size(&self) -> u64 {
self.get_slice_or_empty().size()
// XXX: This will incur reading if file-based
match self.get_bytes() {
Ok(s) => s.len() as u64,
_ => 0,
}
}

// https://w3c.github.io/FileAPI/#dfn-type
@@ -10,7 +10,7 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::blob::{Blob, BlobImpl, DataSlice, blob_parts_to_bytes};
use dom::blob::{Blob, BlobImpl, blob_parts_to_bytes};
use dom::window::Window;
use net_traits::filemanager_thread::SelectedFile;
use time;
@@ -71,9 +71,8 @@ impl File {
let ref blobPropertyBag = filePropertyBag.parent;
let typeString = blobPropertyBag.get_typestring();

let slice = DataSlice::from_bytes(bytes);
let modified = filePropertyBag.lastModified;
Ok(File::new(global, BlobImpl::new_from_slice(slice), filename, modified, &typeString))
Ok(File::new(global, BlobImpl::new_from_bytes(bytes), filename, modified, &typeString))
}

pub fn name(&self) -> &DOMString {
@@ -13,7 +13,7 @@ use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::blob::{Blob, DataSlice};
use dom::blob::Blob;
use dom::domexception::{DOMErrorName, DOMException};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
@@ -27,6 +27,7 @@ use script_runtime::ScriptThreadEventCategory::FileRead;
use script_runtime::{ScriptChan, CommonScriptMsg};
use script_thread::Runnable;
use std::cell::Cell;
use std::sync::Arc;
use string_cache::Atom;
use util::thread::spawn_named;

@@ -160,7 +161,7 @@ impl FileReader {

// https://w3c.github.io/FileAPI/#dfn-readAsText
pub fn process_read_eof(filereader: TrustedFileReader, gen_id: GenerationId,
data: ReadMetaData, blob_contents: DataSlice) {
data: ReadMetaData, blob_contents: Arc<Vec<u8>>) {
let fr = filereader.root();

macro_rules! return_on_abort(
@@ -176,12 +177,11 @@ impl FileReader {
fr.change_ready_state(FileReaderReadyState::Done);
// Step 8.2

let bytes = blob_contents.get_bytes();
let output = match data.function {
FileReaderFunction::ReadAsDataUrl =>
FileReader::perform_readasdataurl(data, bytes),
FileReader::perform_readasdataurl(data, &blob_contents),
FileReaderFunction::ReadAsText =>
FileReader::perform_readastext(data, bytes),
FileReader::perform_readastext(data, &blob_contents),
};

*fr.result.borrow_mut() = Some(output);
@@ -349,7 +349,7 @@ impl FileReader {
self.change_ready_state(FileReaderReadyState::Loading);

// Step 4
let blob_contents = blob.get_slice_or_empty();
let blob_contents = Arc::new(blob.get_bytes().unwrap_or(vec![]));

let type_ = blob.Type();

@@ -376,7 +376,7 @@ pub enum FileReaderEvent {
ProcessRead(TrustedFileReader, GenerationId),
ProcessReadData(TrustedFileReader, GenerationId),
ProcessReadError(TrustedFileReader, GenerationId, DOMErrorName),
ProcessReadEOF(TrustedFileReader, GenerationId, ReadMetaData, DataSlice)
ProcessReadEOF(TrustedFileReader, GenerationId, ReadMetaData, Arc<Vec<u8>>)
}

impl Runnable for FileReaderEvent {
@@ -400,7 +400,7 @@ impl Runnable for FileReaderEvent {
}

// https://w3c.github.io/FileAPI/#thread-read-operation
fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, blob_contents: DataSlice,
fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, blob_contents: Arc<Vec<u8>>,
filereader: TrustedFileReader, script_chan: Box<ScriptChan + Send>) {
let chan = &script_chan;
// Step 4
@@ -126,8 +126,9 @@ impl FormData {
Some(fname) => {
let global = self.global();
let name = DOMString::from(fname.0);
let slice = blob.get_slice_or_empty();
Root::upcast(File::new(global.r(), BlobImpl::new_from_slice(slice), name, None, ""))
let bytes = blob.get_bytes().unwrap_or(vec![]);

Root::upcast(File::new(global.r(), BlobImpl::new_from_bytes(bytes), name, None, ""))
}
None => Root::from_ref(blob)
}
@@ -324,9 +324,9 @@ impl HTMLFormElement {
content_disposition,
content_type));

let slice = f.upcast::<Blob>().get_slice_or_empty();
let bytes = &f.upcast::<Blob>().get_bytes().unwrap_or(vec![])[..];

let decoded = encoding.decode(&slice.get_bytes(), DecoderTrap::Replace)
let decoded = encoding.decode(bytes, DecoderTrap::Replace)
.expect("Invalid encoding in file");
result.push_str(&decoded);
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.