From 966ce7de8a23f63d0f30b1748fe69ccaf07519e0 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Wed, 7 Apr 2021 15:22:14 +0200 Subject: 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. --- op_crates/file/lib.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'op_crates/file/lib.rs') 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, + pub media_type: String, +} + +pub struct Location(pub Url); + +#[derive(Default, Clone)] +pub struct BlobUrlStore(Arc>>); + +impl BlobUrlStore { + pub fn get(&self, url: &ModuleSpecifier) -> Result, AnyError> { + let blob_store = self.0.lock().unwrap(); + Ok(blob_store.get(url).cloned()) + } + + pub fn insert(&self, blob: Blob, maybe_location: Option) -> 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, +) -> Result { + let data = zero_copy.ok_or_else(null_opbuf)?; + let blob = Blob { + data: data.to_vec(), + media_type, + }; + + let maybe_location = state.try_borrow::(); + let blob_store = state.borrow::(); + + 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, +) -> Result<(), AnyError> { + let url = Url::parse(&url)?; + let blob_store = state.borrow::(); + 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(); -- cgit v1.2.3