summaryrefslogtreecommitdiff
path: root/op_crates/file/lib.rs
diff options
context:
space:
mode:
authorLuca Casonato <lucacasonato@yahoo.com>2021-04-07 15:22:14 +0200
committerGitHub <noreply@github.com>2021-04-07 15:22:14 +0200
commit966ce7de8a23f63d0f30b1748fe69ccaf07519e0 (patch)
tree3275ca96a835fe91a62a73d5a4c83bf6ca917b66 /op_crates/file/lib.rs
parent2865f39bec6da135a2d2d679a65e7ff139131bd7 (diff)
feat: blob URL support (#10045)
This commit adds blob URL support. Blob URLs are stored in a process global storage, that can be accessed from all workers, and the module loader. Blob URLs can be created using `URL.createObjectURL` and revoked using `URL.revokeObjectURL`. This commit does not add support for `fetch`ing blob URLs. This will be added in a follow up commit.
Diffstat (limited to 'op_crates/file/lib.rs')
-rw-r--r--op_crates/file/lib.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/op_crates/file/lib.rs b/op_crates/file/lib.rs
index c7e690433..4cfe4eed4 100644
--- a/op_crates/file/lib.rs
+++ b/op_crates/file/lib.rs
@@ -1,7 +1,85 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+use deno_core::error::null_opbuf;
+use deno_core::error::AnyError;
+use deno_core::url::Url;
use deno_core::JsRuntime;
+use deno_core::ModuleSpecifier;
+use deno_core::ZeroCopyBuf;
+use std::collections::HashMap;
use std::path::PathBuf;
+use std::sync::Arc;
+use std::sync::Mutex;
+use uuid::Uuid;
+
+#[derive(Clone)]
+pub struct Blob {
+ pub data: Vec<u8>,
+ pub media_type: String,
+}
+
+pub struct Location(pub Url);
+
+#[derive(Default, Clone)]
+pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
+
+impl BlobUrlStore {
+ pub fn get(&self, url: &ModuleSpecifier) -> Result<Option<Blob>, AnyError> {
+ let blob_store = self.0.lock().unwrap();
+ Ok(blob_store.get(url).cloned())
+ }
+
+ pub fn insert(&self, blob: Blob, maybe_location: Option<Url>) -> Url {
+ let origin = if let Some(location) = maybe_location {
+ location.origin().ascii_serialization()
+ } else {
+ "null".to_string()
+ };
+ let id = Uuid::new_v4();
+ let url = Url::parse(&format!("blob:{}/{}", origin, id)).unwrap();
+
+ let mut blob_store = self.0.lock().unwrap();
+ blob_store.insert(url.clone(), blob);
+
+ url
+ }
+
+ pub fn remove(&self, url: &ModuleSpecifier) {
+ let mut blob_store = self.0.lock().unwrap();
+ blob_store.remove(&url);
+ }
+}
+
+pub fn op_file_create_object_url(
+ state: &mut deno_core::OpState,
+ media_type: String,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<String, AnyError> {
+ let data = zero_copy.ok_or_else(null_opbuf)?;
+ let blob = Blob {
+ data: data.to_vec(),
+ media_type,
+ };
+
+ let maybe_location = state.try_borrow::<Location>();
+ let blob_store = state.borrow::<BlobUrlStore>();
+
+ let url =
+ blob_store.insert(blob, maybe_location.map(|location| location.0.clone()));
+
+ Ok(url.to_string())
+}
+
+pub fn op_file_revoke_object_url(
+ state: &mut deno_core::OpState,
+ url: String,
+ _zero_copy: Option<ZeroCopyBuf>,
+) -> Result<(), AnyError> {
+ let url = Url::parse(&url)?;
+ let blob_store = state.borrow::<BlobUrlStore>();
+ blob_store.remove(&url);
+ Ok(())
+}
/// Load and execute the javascript code.
pub fn init(isolate: &mut JsRuntime) {
@@ -11,6 +89,10 @@ pub fn init(isolate: &mut JsRuntime) {
"deno:op_crates/file/02_filereader.js",
include_str!("02_filereader.js"),
),
+ (
+ "deno:op_crates/file/03_blob_url.js",
+ include_str!("03_blob_url.js"),
+ ),
];
for (url, source_code) in files {
isolate.execute(url, source_code).unwrap();