mirror of
https://github.com/denoland/deno.git
synced 2024-11-01 09:24:20 -04:00
0260b488fb
Extensions allow declarative extensions to "JsRuntime" (ops, state, JS or middleware). This allows for: - `op_crates` to be plug-and-play & self-contained, reducing complexity leaked to consumers - op middleware (like metrics_op) to be opt-in and for new middleware (unstable, tracing,...) - `MainWorker` and `WebWorker` to be composable, allowing users to extend workers with their ops whilst benefiting from the other infrastructure (inspector, etc...) In short extensions improve deno's modularity, reducing complexity and leaky abstractions for embedders and the internal codebase.
120 lines
2.9 KiB
Rust
120 lines
2.9 KiB
Rust
// 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::include_js_files;
|
|
use deno_core::op_sync;
|
|
use deno_core::url::Url;
|
|
use deno_core::Extension;
|
|
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(Debug, Clone)]
|
|
pub struct Blob {
|
|
pub data: Vec<u8>,
|
|
pub media_type: String,
|
|
}
|
|
|
|
pub struct Location(pub Url);
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
|
|
|
|
impl BlobUrlStore {
|
|
pub fn get(&self, mut url: Url) -> Result<Option<Blob>, AnyError> {
|
|
let blob_store = self.0.lock().unwrap();
|
|
url.set_fragment(None);
|
|
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(())
|
|
}
|
|
|
|
pub fn init(
|
|
blob_url_store: BlobUrlStore,
|
|
maybe_location: Option<Url>,
|
|
) -> Extension {
|
|
Extension::with_ops(
|
|
include_js_files!(
|
|
prefix "deno:op_crates/file",
|
|
"01_file.js",
|
|
"02_filereader.js",
|
|
"03_blob_url.js",
|
|
),
|
|
vec![
|
|
(
|
|
"op_file_create_object_url",
|
|
op_sync(op_file_create_object_url),
|
|
),
|
|
(
|
|
"op_file_revoke_object_url",
|
|
op_sync(op_file_revoke_object_url),
|
|
),
|
|
],
|
|
Some(Box::new(move |state| {
|
|
state.put(blob_url_store.clone());
|
|
if let Some(location) = maybe_location.clone() {
|
|
state.put(Location(location));
|
|
}
|
|
Ok(())
|
|
})),
|
|
)
|
|
}
|
|
|
|
pub fn get_declaration() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_file.d.ts")
|
|
}
|