summaryrefslogtreecommitdiff
path: root/extensions/web/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/web/lib.rs')
-rw-r--r--extensions/web/lib.rs101
1 files changed, 99 insertions, 2 deletions
diff --git a/extensions/web/lib.rs b/extensions/web/lib.rs
index 95adb822a..b2906acaf 100644
--- a/extensions/web/lib.rs
+++ b/extensions/web/lib.rs
@@ -1,12 +1,15 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::bad_resource_id;
+use deno_core::error::null_opbuf;
use deno_core::error::range_error;
use deno_core::error::type_error;
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::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
@@ -17,15 +20,21 @@ use encoding_rs::DecoderResult;
use encoding_rs::Encoding;
use serde::Deserialize;
use serde::Serialize;
-
use std::borrow::Cow;
use std::cell::RefCell;
+use std::collections::HashMap;
use std::fmt;
use std::path::PathBuf;
+use std::sync::Arc;
+use std::sync::Mutex;
use std::usize;
+use uuid::Uuid;
/// Load and execute the javascript code.
-pub fn init() -> Extension {
+pub fn init(
+ blob_url_store: BlobUrlStore,
+ maybe_location: Option<Url>,
+) -> Extension {
Extension::builder()
.js(include_js_files!(
prefix "deno:extensions/web",
@@ -38,6 +47,9 @@ pub fn init() -> Extension {
"04_global_interfaces.js",
"05_base64.js",
"08_text_encoding.js",
+ "09_file.js",
+ "10_filereader.js",
+ "11_blob_url.js",
"12_location.js",
))
.ops(vec![
@@ -50,7 +62,22 @@ pub fn init() -> Extension {
("op_encoding_new_decoder", op_sync(op_encoding_new_decoder)),
("op_encoding_decode", op_sync(op_encoding_decode)),
("op_encoding_encode_into", op_sync(op_encoding_encode_into)),
+ (
+ "op_file_create_object_url",
+ op_sync(op_file_create_object_url),
+ ),
+ (
+ "op_file_revoke_object_url",
+ op_sync(op_file_revoke_object_url),
+ ),
])
+ .state(move |state| {
+ state.put(blob_url_store.clone());
+ if let Some(location) = maybe_location.clone() {
+ state.put(Location(location));
+ }
+ Ok(())
+ })
.build()
}
@@ -318,3 +345,73 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
.map(|_| "DOMExceptionInvalidCharacterError")
})
}
+
+#[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,
+ _: (),
+) -> Result<(), AnyError> {
+ let url = Url::parse(&url)?;
+ let blob_store = state.borrow::<BlobUrlStore>();
+ blob_store.remove(&url);
+ Ok(())
+}