aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/blob.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/blob.rs')
-rw-r--r--components/script/dom/blob.rs29
1 files changed, 21 insertions, 8 deletions
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index 27aa382c3fc..c5c5c480707 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -7,7 +7,7 @@ use std::ptr;
use std::rc::Rc;
use base::id::{BlobId, BlobIndex};
-use constellation_traits::BlobImpl;
+use constellation_traits::{BlobData, BlobImpl};
use dom_struct::dom_struct;
use encoding_rs::UTF_8;
use js::jsapi::JSObject;
@@ -33,7 +33,7 @@ use crate::dom::readablestream::ReadableStream;
use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_runtime::CanGc;
-// https://w3c.github.io/FileAPI/#blob
+/// <https://w3c.github.io/FileAPI/#dfn-Blob>
#[dom_struct]
pub(crate) struct Blob {
reflector_: Reflector,
@@ -198,7 +198,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
self.get_stream(can_gc)
}
- // https://w3c.github.io/FileAPI/#slice-method-algo
+ /// <https://w3c.github.io/FileAPI/#slice-method-algo>
fn Slice(
&self,
start: Option<i64>,
@@ -206,11 +206,24 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
content_type: Option<DOMString>,
can_gc: CanGc,
) -> DomRoot<Blob> {
- let type_string =
- normalize_type_string(content_type.unwrap_or(DOMString::from("")).as_ref());
- let rel_pos = RelativePos::from_opts(start, end);
- let blob_impl = BlobImpl::new_sliced(rel_pos, self.blob_id, type_string);
- Blob::new(&self.global(), blob_impl, can_gc)
+ let global = self.global();
+ let type_string = normalize_type_string(&content_type.unwrap_or_default());
+
+ // If our parent is already a sliced blob then we reference the data from the grandparent instead,
+ // to keep the blob ancestry chain short.
+ let (parent, range) = match *global.get_blob_data(&self.blob_id) {
+ BlobData::Sliced(grandparent, parent_range) => {
+ let range = RelativePos {
+ start: parent_range.start + start.unwrap_or_default(),
+ end: end.map(|end| end + parent_range.start).or(parent_range.end),
+ };
+ (grandparent, range)
+ },
+ _ => (self.blob_id, RelativePos::from_opts(start, end)),
+ };
+
+ let blob_impl = BlobImpl::new_sliced(range, parent, type_string);
+ Blob::new(&global, blob_impl, can_gc)
}
// https://w3c.github.io/FileAPI/#text-method-algo