diff options
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/fetch/20_headers.js | 3 | ||||
-rw-r--r-- | extensions/fetch/21_formdata.js | 3 | ||||
-rw-r--r-- | extensions/fetch/22_body.js | 3 | ||||
-rw-r--r-- | extensions/fetch/22_http_client.js | 3 | ||||
-rw-r--r-- | extensions/fetch/23_request.js | 3 | ||||
-rw-r--r-- | extensions/fetch/23_response.js | 3 | ||||
-rw-r--r-- | extensions/fetch/Cargo.toml | 2 | ||||
-rw-r--r-- | extensions/fetch/lib.rs | 2 | ||||
-rw-r--r-- | extensions/file/Cargo.toml | 18 | ||||
-rw-r--r-- | extensions/file/README.md | 5 | ||||
-rw-r--r-- | extensions/file/internal.d.ts | 18 | ||||
-rw-r--r-- | extensions/file/lib.deno_file.d.ts | 40 | ||||
-rw-r--r-- | extensions/file/lib.rs | 120 | ||||
-rw-r--r-- | extensions/web/09_file.js (renamed from extensions/file/01_file.js) | 1 | ||||
-rw-r--r-- | extensions/web/10_filereader.js (renamed from extensions/file/02_filereader.js) | 1 | ||||
-rw-r--r-- | extensions/web/11_blob_url.js (renamed from extensions/file/03_blob_url.js) | 1 | ||||
-rw-r--r-- | extensions/web/Cargo.toml | 1 | ||||
-rw-r--r-- | extensions/web/README.md | 3 | ||||
-rw-r--r-- | extensions/web/internal.d.ts | 10 | ||||
-rw-r--r-- | extensions/web/lib.deno_web.d.ts | 36 | ||||
-rw-r--r-- | extensions/web/lib.rs | 101 |
21 files changed, 156 insertions, 221 deletions
diff --git a/extensions/fetch/20_headers.js b/extensions/fetch/20_headers.js index 5f865749a..24dcdb74a 100644 --- a/extensions/fetch/20_headers.js +++ b/extensions/fetch/20_headers.js @@ -3,8 +3,7 @@ // @ts-check /// <reference path="../webidl/internal.d.ts" /> /// <reference path="../web/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/21_formdata.js b/extensions/fetch/21_formdata.js index beae69aca..32a4e69a7 100644 --- a/extensions/fetch/21_formdata.js +++ b/extensions/fetch/21_formdata.js @@ -3,8 +3,7 @@ // @ts-check /// <reference path="../webidl/internal.d.ts" /> /// <reference path="../web/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/22_body.js b/extensions/fetch/22_body.js index dcf1128a7..5039ab910 100644 --- a/extensions/fetch/22_body.js +++ b/extensions/fetch/22_body.js @@ -5,8 +5,7 @@ /// <reference path="../url/internal.d.ts" /> /// <reference path="../url/lib.deno_url.d.ts" /> /// <reference path="../web/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/22_http_client.js b/extensions/fetch/22_http_client.js index 770080cc9..9900cfb58 100644 --- a/extensions/fetch/22_http_client.js +++ b/extensions/fetch/22_http_client.js @@ -4,8 +4,7 @@ /// <reference path="../webidl/internal.d.ts" /> /// <reference path="../web/internal.d.ts" /> /// <reference path="../url/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/23_request.js b/extensions/fetch/23_request.js index d03023687..ad05b5cd8 100644 --- a/extensions/fetch/23_request.js +++ b/extensions/fetch/23_request.js @@ -3,8 +3,7 @@ // @ts-check /// <reference path="../webidl/internal.d.ts" /> /// <reference path="../web/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/23_response.js b/extensions/fetch/23_response.js index b1b037187..a8fd52162 100644 --- a/extensions/fetch/23_response.js +++ b/extensions/fetch/23_response.js @@ -4,8 +4,7 @@ /// <reference path="../webidl/internal.d.ts" /> /// <reference path="../web/internal.d.ts" /> /// <reference path="../url/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> +/// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> /// <reference path="./11_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> diff --git a/extensions/fetch/Cargo.toml b/extensions/fetch/Cargo.toml index c01af459a..27ab2e05d 100644 --- a/extensions/fetch/Cargo.toml +++ b/extensions/fetch/Cargo.toml @@ -17,7 +17,7 @@ path = "lib.rs" bytes = "1.0.1" data-url = "0.1.0" deno_core = { version = "0.89.0", path = "../../core" } -deno_file = { version = "0.7.0", path = "../file" } +deno_web = { version = "0.39.0", path = "../web" } http = "0.2.4" reqwest = { version = "0.11.3", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli"] } serde = { version = "1.0.125", features = ["derive"] } diff --git a/extensions/fetch/lib.rs b/extensions/fetch/lib.rs index 2fbd38b3a..5638b1f33 100644 --- a/extensions/fetch/lib.rs +++ b/extensions/fetch/lib.rs @@ -25,7 +25,7 @@ use deno_core::ResourceId; use deno_core::ZeroCopyBuf; use data_url::DataUrl; -use deno_file::BlobUrlStore; +use deno_web::BlobUrlStore; use reqwest::header::HeaderMap; use reqwest::header::HeaderName; use reqwest::header::HeaderValue; diff --git a/extensions/file/Cargo.toml b/extensions/file/Cargo.toml deleted file mode 100644 index da70cf1b8..000000000 --- a/extensions/file/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -[package] -name = "deno_file" -version = "0.7.0" -edition = "2018" -description = "File API implementation for Deno" -authors = ["the Deno authors"] -license = "MIT" -readme = "README.md" -repository = "https://github.com/denoland/deno" - -[lib] -path = "lib.rs" - -[dependencies] -deno_core = { version = "0.89.0", path = "../../core" } -uuid = { version = "0.8.2", features = ["v4"] } diff --git a/extensions/file/README.md b/extensions/file/README.md deleted file mode 100644 index c421bf004..000000000 --- a/extensions/file/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# deno_file - -This crate implements the File API. - -Spec: https://w3c.github.io/FileAPI diff --git a/extensions/file/internal.d.ts b/extensions/file/internal.d.ts deleted file mode 100644 index dd892e736..000000000 --- a/extensions/file/internal.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -/// <reference no-default-lib="true" /> -/// <reference lib="esnext" /> - -declare namespace globalThis { - declare namespace __bootstrap { - declare var file: { - Blob: typeof Blob & { - [globalThis.__bootstrap.file._byteSequence]: Uint8Array; - }; - readonly _byteSequence: unique symbol; - File: typeof File & { - [globalThis.__bootstrap.file._byteSequence]: Uint8Array; - }; - }; - } -} diff --git a/extensions/file/lib.deno_file.d.ts b/extensions/file/lib.deno_file.d.ts deleted file mode 100644 index a907c3f50..000000000 --- a/extensions/file/lib.deno_file.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -/// <reference no-default-lib="true" /> -/// <reference lib="esnext" /> - -type BlobPart = BufferSource | Blob | string; - -interface BlobPropertyBag { - type?: string; - endings?: "transparent" | "native"; -} - -/** A file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system. */ -declare class Blob { - constructor(blobParts?: BlobPart[], options?: BlobPropertyBag); - - readonly size: number; - readonly type: string; - arrayBuffer(): Promise<ArrayBuffer>; - slice(start?: number, end?: number, contentType?: string): Blob; - stream(): ReadableStream<Uint8Array>; - text(): Promise<string>; -} - -interface FilePropertyBag extends BlobPropertyBag { - lastModified?: number; -} - -/** Provides information about files and allows JavaScript in a web page to - * access their content. */ -declare class File extends Blob { - constructor( - fileBits: BlobPart[], - fileName: string, - options?: FilePropertyBag, - ); - - readonly lastModified: number; - readonly name: string; -} diff --git a/extensions/file/lib.rs b/extensions/file/lib.rs deleted file mode 100644 index 1dcc02d27..000000000 --- a/extensions/file/lib.rs +++ /dev/null @@ -1,120 +0,0 @@ -// 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, - _: (), -) -> 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::builder() - .js(include_js_files!( - prefix "deno:extensions/file", - "01_file.js", - "02_filereader.js", - "03_blob_url.js", - )) - .ops(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), - ), - ]) - .state(move |state| { - state.put(blob_url_store.clone()); - if let Some(location) = maybe_location.clone() { - state.put(Location(location)); - } - Ok(()) - }) - .build() -} - -pub fn get_declaration() -> PathBuf { - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_file.d.ts") -} diff --git a/extensions/file/01_file.js b/extensions/web/09_file.js index 42298c3a1..403bbee35 100644 --- a/extensions/file/01_file.js +++ b/extensions/web/09_file.js @@ -7,7 +7,6 @@ /// <reference path="../web/internal.d.ts" /> /// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> -/// <reference path="./lib.deno_file.d.ts" /> /// <reference lib="esnext" /> "use strict"; diff --git a/extensions/file/02_filereader.js b/extensions/web/10_filereader.js index 7cc40f7a5..b8bb6172a 100644 --- a/extensions/file/02_filereader.js +++ b/extensions/web/10_filereader.js @@ -7,7 +7,6 @@ /// <reference path="../web/internal.d.ts" /> /// <reference path="../web/lib.deno_web.d.ts" /> /// <reference path="./internal.d.ts" /> -/// <reference path="./lib.deno_file.d.ts" /> /// <reference lib="esnext" /> "use strict"; diff --git a/extensions/file/03_blob_url.js b/extensions/web/11_blob_url.js index 2b5e16b55..d030d79bd 100644 --- a/extensions/file/03_blob_url.js +++ b/extensions/web/11_blob_url.js @@ -9,7 +9,6 @@ /// <reference path="../url/internal.d.ts" /> /// <reference path="../url/lib.deno_url.d.ts" /> /// <reference path="./internal.d.ts" /> -/// <reference path="./lib.deno_file.d.ts" /> /// <reference lib="esnext" /> "use strict"; diff --git a/extensions/web/Cargo.toml b/extensions/web/Cargo.toml index a914d1b48..05a0f17f2 100644 --- a/extensions/web/Cargo.toml +++ b/extensions/web/Cargo.toml @@ -18,6 +18,7 @@ base64 = "0.13.0" deno_core = { version = "0.89.0", path = "../../core" } encoding_rs = "0.8.28" serde = "1.0" +uuid = { version = "0.8.2", features = ["v4"] } [dev-dependencies] futures = "0.3.15" diff --git a/extensions/web/README.md b/extensions/web/README.md index 03c1b7f89..d847ae52e 100644 --- a/extensions/web/README.md +++ b/extensions/web/README.md @@ -1,5 +1,6 @@ # deno web -Op crate that implements Event, TextEncoder, TextDecoder. +Op crate that implements Event, TextEncoder, TextDecoder and File API +(https://w3c.github.io/FileAPI). Testing for text encoding is done via WPT in cli/. diff --git a/extensions/web/internal.d.ts b/extensions/web/internal.d.ts index ebfa0d39e..4492e6554 100644 --- a/extensions/web/internal.d.ts +++ b/extensions/web/internal.d.ts @@ -70,5 +70,15 @@ declare namespace globalThis { atob(data: string): string; btoa(data: string): string; }; + + declare var file: { + Blob: typeof Blob & { + [globalThis.__bootstrap.file._byteSequence]: Uint8Array; + }; + readonly _byteSequence: unique symbol; + File: typeof File & { + [globalThis.__bootstrap.file._byteSequence]: Uint8Array; + }; + }; } } diff --git a/extensions/web/lib.deno_web.d.ts b/extensions/web/lib.deno_web.d.ts index 0c3673351..a1b6a0595 100644 --- a/extensions/web/lib.deno_web.d.ts +++ b/extensions/web/lib.deno_web.d.ts @@ -341,3 +341,39 @@ declare var FileReader: { readonly EMPTY: number; readonly LOADING: number; }; + +type BlobPart = BufferSource | Blob | string; + +interface BlobPropertyBag { + type?: string; + endings?: "transparent" | "native"; +} + +/** A file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system. */ +declare class Blob { + constructor(blobParts?: BlobPart[], options?: BlobPropertyBag); + + readonly size: number; + readonly type: string; + arrayBuffer(): Promise<ArrayBuffer>; + slice(start?: number, end?: number, contentType?: string): Blob; + stream(): ReadableStream<Uint8Array>; + text(): Promise<string>; +} + +interface FilePropertyBag extends BlobPropertyBag { + lastModified?: number; +} + +/** Provides information about files and allows JavaScript in a web page to + * access their content. */ +declare class File extends Blob { + constructor( + fileBits: BlobPart[], + fileName: string, + options?: FilePropertyBag, + ); + + readonly lastModified: number; + readonly name: string; +} 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(()) +} |